sechandler.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. // SecHandler.cpp: implementation of the CSecHandler class.
  14. //
  15. //////////////////////////////////////////////////////////////////////
  16. #include "sechandler.hpp"
  17. #include "bindutil.hpp"
  18. #include <map>
  19. #include <string>
  20. #include "espcontext.hpp"
  21. //////////////////////////////////////////////////////////////////////
  22. // Construction/Destruction
  23. //////////////////////////////////////////////////////////////////////
  24. SecHandler::SecHandler()
  25. {
  26. }
  27. SecHandler::~SecHandler()
  28. {
  29. }
  30. void SecHandler::setSecManger(ISecManager* mgr)
  31. {
  32. m_secmgr.set(mgr);
  33. }
  34. void SecHandler::setResources(ISecResourceList* rlist)
  35. {
  36. m_resources.set(rlist);
  37. }
  38. void SecHandler::setUser(ISecUser* user)
  39. {
  40. m_user.set(user);
  41. }
  42. void SecHandler::setFeatureAuthMap(IAuthMap * map)
  43. {
  44. if(map != NULL)
  45. m_feature_authmap.set(map);
  46. }
  47. void SecHandler::setSecureContext(IEspSecureContext* secureContext)
  48. {
  49. m_secureContext.set(secureContext);
  50. }
  51. bool SecHandler::authorizeSecFeature(const char * pszFeatureUrl, const char* UserID, const char* CompanyID, SecAccessFlags & required_access,bool bCheckTrial,int DebitUnits, SecUserStatus & user_status)
  52. {
  53. if(m_user.get()==0)
  54. throw MakeStringException(500,"No user defined in SecHandler::authorizeSecFeature");
  55. user_status = SecUserStatus_Unknown;
  56. //lets see is our primary user allowed to access the resource.
  57. bool bPrimaryAccessAllowed = authorizeSecFeature(pszFeatureUrl,required_access);
  58. if(bPrimaryAccessAllowed==false)
  59. return false;
  60. //by now the prime ISecUser will have been fully initialized. We should be able
  61. //..to tell its status.
  62. if(m_user->getStatus() == SecUserStatus_FreeTrial || m_user->getStatus() == SecUserStatus_Rollover)
  63. {
  64. bool bReturn = true;
  65. if(bCheckTrial==true)
  66. bReturn = authorizeTrial(*m_user.get(),pszFeatureUrl,required_access);
  67. user_status = m_user->getStatus();
  68. return bReturn;
  69. }
  70. //m_user should be the user who logs in. This may not be the user whose resource we are looking for.
  71. //if userid and companyid are blank then we must be authenticating a normal user.. so continue on..
  72. if(UserID==0 || *UserID=='\0' || CompanyID==0 || *CompanyID=='\0')
  73. return bPrimaryAccessAllowed;
  74. //see do we have a cached version of our secondary user.....
  75. //.. if we do then check it...
  76. Owned<ISecUser> pSecondaryUser;
  77. pSecondaryUser.set(m_secmgr->findUser(UserID));
  78. if(pSecondaryUser.get()== NULL)
  79. {
  80. pSecondaryUser.setown(m_secmgr->createUser(UserID));
  81. if (!pSecondaryUser)
  82. return false;
  83. pSecondaryUser->setRealm(CompanyID);
  84. bool bSecondaryAccessAllowed = m_secmgr->initUser(*pSecondaryUser.get());
  85. if(bSecondaryAccessAllowed==false)
  86. return false;
  87. m_secmgr->addUser(*pSecondaryUser.get());
  88. }
  89. // currently not the responsibility of this service to authenticate the secondary user.
  90. //we just need to chech and see if on a free trial whether they should be allowed continue
  91. if(pSecondaryUser->getStatus() == SecUserStatus_FreeTrial || pSecondaryUser->getStatus() == SecUserStatus_Rollover)
  92. {
  93. //if the primary user is inhouse then we only want to check for a free trial
  94. // if a debit units value has been passed in.
  95. if(m_user->getStatus() == SecUserStatus_Inhouse && DebitUnits == 0)
  96. {
  97. if (getEspLogLevel() >= LogNormal)
  98. DBGLOG("Inhouse primary user and DebitUtits are 0 so not decrementing free trial");
  99. return true;
  100. }
  101. if (DebitUnits > 0)
  102. pSecondaryUser->setPropertyInt("debitunits",DebitUnits);
  103. bool bReturn = true;
  104. if(bCheckTrial==true)
  105. bReturn = authorizeTrial(*pSecondaryUser,pszFeatureUrl,required_access);
  106. user_status = pSecondaryUser->getStatus();
  107. return bReturn;
  108. }
  109. return true;
  110. }
  111. bool SecHandler::authorizeTrial(ISecUser& user,const char* pszFeatureUrl, SecAccessFlags & required_access)
  112. {
  113. int trial_access = m_secmgr->authorizeEx(RT_TRIAL,user,pszFeatureUrl);
  114. if(trial_access < required_access)
  115. throw MakeStringException(201,"Your company has used up all of their free transaction credits");
  116. return true;
  117. }
  118. bool SecHandler::authorizeSecFeature(const char* pszFeatureUrl, SecAccessFlags& access)
  119. {
  120. StringArray features;
  121. features.append(pszFeatureUrl);
  122. Owned<IEspStringIntMap> pmap=createStringIntMap();
  123. bool rc = authorizeSecFeatures(features, *pmap);
  124. if (rc)
  125. {
  126. int accessAllowed = pmap->queryValue(pszFeatureUrl);
  127. if (accessAllowed == -1)
  128. rc = false;
  129. else
  130. access = (SecAccessFlags) accessAllowed;
  131. }
  132. return rc;
  133. }
  134. bool SecHandler::authorizeSecFeatures(StringArray & features, IEspStringIntMap & pmap)
  135. {
  136. return authorizeSecReqFeatures(features, pmap, NULL);
  137. }
  138. bool SecHandler::validateSecFeaturesAccess(MapStringTo<SecAccessFlags> & accessmap, bool throwExcpt)
  139. {
  140. StringArray features;
  141. unsigned reqarray[100];
  142. if (accessmap.ordinality() >= 100)
  143. throw MakeStringException(-1, "Attempting to validate too many security features!");
  144. HashIterator iter(accessmap);
  145. int index = 0;
  146. ForEach(iter)
  147. {
  148. IMapping &cur = iter.query();
  149. const char * key = (const char *)cur.getKey();
  150. SecAccessFlags val = *accessmap.getValue(key);
  151. features.append(key);
  152. reqarray[index++] = val;
  153. }
  154. Owned<IEspStringIntMap> pmap=createStringIntMap();
  155. if (authorizeSecReqFeatures(features, *pmap, reqarray))
  156. {
  157. for(unsigned i = 0; i < features.length(); i++)
  158. {
  159. int accessAllowed = pmap->queryValue(features.item(i));
  160. if ((accessAllowed == -1) || (reqarray[i] && ((unsigned)accessAllowed < reqarray[i])))
  161. {
  162. if (throwExcpt)
  163. throw MakeStringException(-1, "Access Denied!");
  164. return false;
  165. }
  166. }
  167. return true;
  168. }
  169. if (throwExcpt)
  170. throw MakeStringException(-1, "Access Denied!");
  171. return false;
  172. }
  173. bool SecHandler::authorizeSecReqFeatures(StringArray & features, IEspStringIntMap & pmap, unsigned *required)
  174. {
  175. if(features.length() == 0)
  176. return false;
  177. if(m_secmgr.get() == NULL)
  178. {
  179. for(unsigned i = 0; i < features.length(); i++)
  180. {
  181. const char* feature = features.item(i);
  182. if(feature != NULL && feature[0] != 0)
  183. pmap.setValue(feature, SecAccess_Full);
  184. }
  185. return true;
  186. }
  187. if(m_user.get() == NULL)
  188. {
  189. AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authorization", "Access Denied: No username provided");
  190. return false;
  191. }
  192. Owned<ISecResourceList> plist = m_secmgr->createResourceList("FeatureMap");
  193. std::map<std::string, std::string> namemap;
  194. unsigned i;
  195. for(i = 0; i < features.length(); i++)
  196. {
  197. const char* feature = features.item(i);
  198. if(feature == NULL || feature[0] == 0)
  199. continue;
  200. if(m_feature_authmap.get() == NULL)
  201. {
  202. plist->addResource(feature);
  203. namemap[feature] = feature;
  204. }
  205. else
  206. {
  207. ISecResourceList* rlist = m_feature_authmap->queryResourceList(feature);
  208. ISecResource* resource = NULL;
  209. if(rlist != NULL && (resource = rlist->queryResource((unsigned)0)) != NULL)
  210. {
  211. plist->addResource(resource->clone());
  212. namemap[resource->getName()] = feature;
  213. }
  214. else
  215. {
  216. // Use the feature name as the resource name if no authmap was found
  217. ISecResource* res = plist->addResource(feature);
  218. res->setRequiredAccessFlags(SecAccess_Unknown);
  219. namemap[feature] = feature;
  220. }
  221. }
  222. }
  223. bool auth_ok = false;
  224. try
  225. {
  226. auth_ok = m_secmgr->authorize(*m_user.get(), plist, m_secureContext.get());
  227. }
  228. catch(IException* e)
  229. {
  230. StringBuffer errmsg;
  231. e->errorMessage(errmsg);
  232. IERRLOG("Exception authorizing, error=%s\n", errmsg.str());
  233. return false;
  234. }
  235. catch(...)
  236. {
  237. IERRLOG("Unknown exception authorizing\n");
  238. return false;
  239. }
  240. if(auth_ok)
  241. {
  242. for(i = 0; i < (unsigned)plist->count(); i++)
  243. {
  244. ISecResource* resource = plist->queryResource(i);
  245. if(resource != NULL)
  246. {
  247. std::string feature = namemap[resource->getName()];
  248. if(feature.size() == 0)
  249. continue;
  250. pmap.setValue(feature.c_str(), resource->getAccessFlags());
  251. if (required && required[i]>0 && resource->getAccessFlags()<required[i])
  252. {
  253. AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authorization", "Access Denied: Not enough access rights for resource", "Resource: %s [%s]", resource->getName(), resource->getDescription());
  254. }
  255. }
  256. }
  257. }
  258. return auth_ok;
  259. }
  260. bool SecHandler::validateSecFeatureAccess(const char* pszFeatureUrl, unsigned required, bool throwExcpt)
  261. {
  262. StringArray features;
  263. features.append(pszFeatureUrl);
  264. unsigned reqarray[1];
  265. reqarray[0] = required;
  266. Owned<IEspStringIntMap> pmap=createStringIntMap();
  267. if (authorizeSecReqFeatures(features, *pmap, reqarray))
  268. {
  269. int accessAllowed = pmap->queryValue(pszFeatureUrl);
  270. if ((accessAllowed == -1) || (required && (accessAllowed < required)))
  271. {
  272. if (throwExcpt)
  273. throw MakeStringException(-1, "Access Denied!");
  274. return false;
  275. }
  276. else
  277. return true;
  278. }
  279. if (throwExcpt)
  280. throw MakeStringException(-1, "Access Denied!");
  281. return false;
  282. }
  283. void SecHandler::AuditMessage(AuditType type, const char *filterType, const char *title, const char *parms, ...)
  284. {
  285. va_list args;
  286. va_start(args, parms);
  287. StringBuffer msg(title);
  288. msg.appendf("\n\tProcess: esp\n\tUser: %s", m_user->getName());
  289. if (parms)
  290. msg.append("\n\t").valist_appendf(parms, args);
  291. va_end(args);
  292. AUDIT(type, msg.str());
  293. }
  294. void SecHandler::AuditMessage(AuditType type, const char *filterType, const char *title)
  295. {
  296. VStringBuffer msg("%s\n\tProcess: esp\n\tUser: %s", title, m_user->getName());
  297. AUDIT(type, msg.str());
  298. }