sechandler.cpp 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. // SecHandler.cpp: implementation of the CSecHandler class.
  15. //
  16. //////////////////////////////////////////////////////////////////////
  17. #include "sechandler.hpp"
  18. #include "bindutil.hpp"
  19. #include <map>
  20. #include <string>
  21. #include "espcontext.hpp"
  22. //////////////////////////////////////////////////////////////////////
  23. // Construction/Destruction
  24. //////////////////////////////////////////////////////////////////////
  25. SecHandler::SecHandler()
  26. {
  27. }
  28. SecHandler::~SecHandler()
  29. {
  30. }
  31. void SecHandler::setSecManger(ISecManager* mgr)
  32. {
  33. m_secmgr.set(mgr);
  34. }
  35. void SecHandler::setResources(ISecResourceList* rlist)
  36. {
  37. m_resources.set(rlist);
  38. }
  39. void SecHandler::setUser(ISecUser* user)
  40. {
  41. m_user.set(user);
  42. }
  43. void SecHandler::setFeatureAuthMap(IAuthMap * map)
  44. {
  45. if(map != NULL)
  46. m_feature_authmap.set(map);
  47. }
  48. bool SecHandler::authorizeSecFeature(const char * pszFeatureUrl, const char* UserID, const char* CompanyID, SecAccessFlags & required_access,bool bCheckTrial,int DebitUnits, SecUserStatus & user_status)
  49. {
  50. if(m_user.get()==0)
  51. throw MakeStringException(500,"No user defined in SecHandler::authorizeSecFeature");
  52. user_status = SecUserStatus_Unknown;
  53. //lets see is our primary user allowed to access the resource.
  54. bool bPrimaryAccessAllowed = authorizeSecFeature(pszFeatureUrl,required_access);
  55. if(bPrimaryAccessAllowed==false)
  56. return false;
  57. //by now the prime ISecUser will have been fully initialized. We should be able
  58. //..to tell its status.
  59. if(m_user->getStatus() == SecUserStatus_FreeTrial || m_user->getStatus() == SecUserStatus_Rollover)
  60. {
  61. bool bReturn = true;
  62. if(bCheckTrial==true)
  63. bReturn = authorizeTrial(*m_user.get(),pszFeatureUrl,required_access);
  64. user_status = m_user->getStatus();
  65. return bReturn;
  66. }
  67. //m_user should be the user who logs in. This may not be the user whose resource we are looking for.
  68. //if userid and companyid are blank then we must be authenticating a normal user.. so continue on..
  69. if(UserID==0 || *UserID=='\0' || CompanyID==0 || *CompanyID=='\0')
  70. return bPrimaryAccessAllowed;
  71. //see do we have a cached version of our secondary user.....
  72. //.. if we do then check it...
  73. Owned<ISecUser> pSecondaryUser;
  74. pSecondaryUser.set(m_secmgr->findUser(UserID));
  75. if(pSecondaryUser.get()== NULL)
  76. {
  77. pSecondaryUser.setown(m_secmgr->createUser(UserID));
  78. pSecondaryUser->setRealm(CompanyID);
  79. bool bSecondaryAccessAllowed = m_secmgr->initUser(*pSecondaryUser.get());
  80. if(bSecondaryAccessAllowed==false)
  81. return false;
  82. m_secmgr->addUser(*pSecondaryUser.get());
  83. }
  84. // currently not the responsibility of this service to authenticate the secondary user.
  85. //we just need to chech and see if on a free trial whether they should be allowed continue
  86. if(pSecondaryUser->getStatus() == SecUserStatus_FreeTrial || pSecondaryUser->getStatus() == SecUserStatus_Rollover)
  87. {
  88. //if the primary user is inhouse then we only want to check for a free trial
  89. // if a debit units value has been passed in.
  90. if(m_user->getStatus() == SecUserStatus_Inhouse && DebitUnits == 0)
  91. {
  92. if (getEspLogLevel() >= LogNormal)
  93. DBGLOG("Inhouse primary user and DebitUtits are 0 so not decrementing free trial");
  94. return true;
  95. }
  96. if (DebitUnits > 0)
  97. pSecondaryUser->setPropertyInt("debitunits",DebitUnits);
  98. bool bReturn = true;
  99. if(bCheckTrial==true)
  100. bReturn = authorizeTrial(*pSecondaryUser,pszFeatureUrl,required_access);
  101. user_status = pSecondaryUser->getStatus();
  102. return bReturn;
  103. }
  104. return true;
  105. }
  106. bool SecHandler::authorizeTrial(ISecUser& user,const char* pszFeatureUrl, SecAccessFlags & required_access)
  107. {
  108. int trial_access = m_secmgr->authorizeEx(RT_TRIAL,user,pszFeatureUrl);
  109. if(trial_access < required_access)
  110. throw MakeStringException(201,"Your company has used up all of their free transaction credits");
  111. return true;
  112. }
  113. bool SecHandler::authorizeSecFeature(const char* pszFeatureUrl, SecAccessFlags& access)
  114. {
  115. StringArray features;
  116. features.append(pszFeatureUrl);
  117. Owned<IEspStringIntMap> pmap=createStringIntMap();
  118. bool rc = authorizeSecFeatures(features, *pmap);
  119. if (rc)
  120. {
  121. int accessAllowed = pmap->queryValue(pszFeatureUrl);
  122. if (accessAllowed == -1)
  123. rc = false;
  124. else
  125. access = (SecAccessFlags) accessAllowed;
  126. }
  127. return rc;
  128. }
  129. bool SecHandler::authorizeSecFeatures(StringArray & features, IEspStringIntMap & pmap)
  130. {
  131. return authorizeSecReqFeatures(features, pmap, NULL);
  132. }
  133. bool SecHandler::authorizeSecReqFeatures(StringArray & features, IEspStringIntMap & pmap, unsigned *required)
  134. {
  135. if(features.length() == 0)
  136. return false;
  137. if(m_secmgr.get() == NULL)
  138. {
  139. for(int i = 0; i < features.length(); i++)
  140. {
  141. const char* feature = features.item(i);
  142. if(feature != NULL && feature[0] != 0)
  143. pmap.setValue(feature, SecAccess_Full);
  144. }
  145. return true;
  146. }
  147. if(m_user.get() == NULL)
  148. {
  149. AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authorization", "Access Denied: No username provided", NULL);
  150. return false;
  151. }
  152. Owned<ISecResourceList> plist = m_secmgr->createResourceList("FeatureMap");
  153. std::map<std::string, std::string> namemap;
  154. int i;
  155. for(i = 0; i < features.length(); i++)
  156. {
  157. const char* feature = features.item(i);
  158. if(feature == NULL || feature[0] == 0)
  159. continue;
  160. if(m_feature_authmap.get() == NULL)
  161. {
  162. plist->addResource(feature);
  163. namemap[feature] = feature;
  164. }
  165. else
  166. {
  167. ISecResourceList* rlist = m_feature_authmap->queryResourceList(feature);
  168. ISecResource* resource = NULL;
  169. if(rlist != NULL && (resource = rlist->queryResource((unsigned)0)) != NULL)
  170. {
  171. plist->addResource(resource->clone());
  172. namemap[resource->getName()] = feature;
  173. }
  174. else
  175. {
  176. // Use the feature name as the resource name if no authmap was found
  177. ISecResource* res = plist->addResource(feature);
  178. res->setRequiredAccessFlags(SecAccess_Unknown);
  179. namemap[feature] = feature;
  180. }
  181. }
  182. }
  183. bool auth_ok = false;
  184. try
  185. {
  186. auth_ok = m_secmgr->authorize(*m_user.get(), plist);
  187. }
  188. catch(IException* e)
  189. {
  190. StringBuffer errmsg;
  191. e->errorMessage(errmsg);
  192. ERRLOG("Exception authorizing, error=%s\n", errmsg.str());
  193. return false;
  194. }
  195. catch(...)
  196. {
  197. ERRLOG("Unknown exception authorizing\n");
  198. return false;
  199. }
  200. if(auth_ok)
  201. {
  202. for(i = 0; i < plist->count(); i++)
  203. {
  204. ISecResource* resource = plist->queryResource(i);
  205. if(resource != NULL)
  206. {
  207. std::string feature = namemap[resource->getName()];
  208. if(feature.size() == 0)
  209. continue;
  210. pmap.setValue(feature.c_str(), resource->getAccessFlags());
  211. if (required && required[i]>0 && resource->getAccessFlags()<required[i])
  212. {
  213. AuditMessage(AUDIT_TYPE_ACCESS_FAILURE, "Authorization", "Access Denied: Not enough access rights for resource", "Resource: %s [%s]", resource->getName(), resource->getDescription());
  214. }
  215. }
  216. }
  217. }
  218. return auth_ok;
  219. }
  220. bool SecHandler::validateSecFeatureAccess(const char* pszFeatureUrl, unsigned required, bool throwExcpt)
  221. {
  222. StringArray features;
  223. features.append(pszFeatureUrl);
  224. unsigned reqarray[1];
  225. reqarray[0] = required;
  226. Owned<IEspStringIntMap> pmap=createStringIntMap();
  227. if (authorizeSecReqFeatures(features, *pmap, reqarray))
  228. {
  229. int accessAllowed = pmap->queryValue(pszFeatureUrl);
  230. if ((accessAllowed == -1) || (required && (accessAllowed < required)))
  231. {
  232. if (throwExcpt)
  233. throw MakeStringException(-1, "Access Denied!");
  234. return false;
  235. }
  236. else
  237. return true;
  238. }
  239. if (throwExcpt)
  240. throw MakeStringException(-1, "Access Denied!");
  241. return false;
  242. }
  243. void SecHandler::AuditMessage(AuditType type, const char *filterType, const char *title, const char *parms, ...)
  244. {
  245. va_list args;
  246. va_start(args, parms);
  247. StringBuffer msg;
  248. StringBuffer format(title);
  249. format.appendf("\n\tProcess: esp\n\tUser: %s", m_user->getName());
  250. if (parms)
  251. format.append("\n\t").append(parms);
  252. msg.valist_appendf(format.str(), args);
  253. va_end(args);
  254. AUDIT(type, msg.str());
  255. }