ws_espcontrolservice.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2015 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. #ifdef _USE_OPENLDAP
  14. #include "ldapsecurity.ipp"
  15. #endif
  16. #include "ws_espcontrolservice.hpp"
  17. #include "jlib.hpp"
  18. #include "exception_util.hpp"
  19. #include "dasds.hpp"
  20. #define SDS_LOCK_TIMEOUT (5*60*1000) // 5 mins
  21. const char* CWSESPControlEx::readSessionTimeStamp(int t, StringBuffer& str)
  22. {
  23. CDateTime time;
  24. time.set(t);
  25. return time.getString(str).str();
  26. }
  27. IEspSession* CWSESPControlEx::setSessionInfo(IPropertyTree* espSessionTree, unsigned port, IEspSession* session)
  28. {
  29. if (espSessionTree == nullptr)
  30. return nullptr;
  31. StringBuffer createTimeStr, lastAccessedStr, TimeoutAtStr;
  32. int lastAccessed = espSessionTree->getPropInt(PropSessionLastAccessed, 0);
  33. session->setPort(port);
  34. session->setID(espSessionTree->queryProp(PropSessionExternalID));
  35. session->setUserID(espSessionTree->queryProp(PropSessionUserID));
  36. session->setNetworkAddress(espSessionTree->queryProp(PropSessionNetworkAddress));
  37. session->setCreateTime(readSessionTimeStamp(espSessionTree->getPropInt(PropSessionCreateTime, 0), createTimeStr));
  38. session->setLastAccessed(readSessionTimeStamp(espSessionTree->getPropInt(PropSessionLastAccessed, 0), lastAccessedStr));
  39. session->setTimeoutAt(readSessionTimeStamp(espSessionTree->getPropInt(PropSessionTimeoutAt, 0), TimeoutAtStr));
  40. session->setTimeoutByAdmin(espSessionTree->getPropBool(PropSessionTimeoutByAdmin, false));
  41. return session;
  42. }
  43. void CWSESPControlEx::init(IPropertyTree *cfg, const char *process, const char *service)
  44. {
  45. if(cfg == NULL)
  46. throw MakeStringException(-1, "Can't initialize CWSESPControlEx, cfg is NULL");
  47. espProcess.set(process);
  48. VStringBuffer xpath("Software/EspProcess[@name=\"%s\"]", process);
  49. IPropertyTree* espCFG = cfg->queryPropTree(xpath.str());
  50. if (!espCFG)
  51. throw MakeStringException(-1, "Can't find EspBinding for %s", process);
  52. Owned<IPropertyTreeIterator> it = espCFG->getElements("AuthDomains/AuthDomain");
  53. ForEach(*it)
  54. {
  55. IPropertyTree& authDomain = it->query();
  56. StringBuffer name = authDomain.queryProp("@domainName");
  57. if (name.isEmpty())
  58. name.set("default");
  59. sessionTimeoutMinutesMap.setValue(name.str(), authDomain.getPropInt("@sessionTimeoutMinutes", 0));
  60. }
  61. }
  62. bool CWSESPControlEx::onSetLogging(IEspContext& context, IEspSetLoggingRequest& req, IEspSetLoggingResponse& resp)
  63. {
  64. try
  65. {
  66. #ifdef _USE_OPENLDAP
  67. CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
  68. if(secmgr && !secmgr->isSuperUser(context.queryUser()))
  69. throw MakeStringException(ECLWATCH_SUPER_USER_ACCESS_DENIED, "Failed to change log settings. Permission denied.");
  70. #endif
  71. if (!m_container)
  72. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Failed to access container.");
  73. if (!req.getLoggingLevel_isNull())
  74. m_container->setLogLevel(req.getLoggingLevel());
  75. if (!req.getLogRequests_isNull())
  76. m_container->setLogRequests(req.getLogRequests());
  77. if (!req.getLogResponses_isNull())
  78. m_container->setLogResponses(req.getLogResponses());
  79. resp.setStatus(0);
  80. resp.setMessage("Logging settings are updated.");
  81. }
  82. catch(IException* e)
  83. {
  84. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  85. }
  86. return true;
  87. }
  88. IRemoteConnection* CWSESPControlEx::querySDSConnection(const char* xpath, unsigned mode, unsigned timeout)
  89. {
  90. Owned<IRemoteConnection> globalLock = querySDS().connect(xpath, myProcessSession(), mode, timeout);
  91. if (!globalLock)
  92. throw MakeStringException(ECLWATCH_INTERNAL_ERROR, "Unable to connect to ESP Session information in dali %s", xpath);
  93. return globalLock.getClear();
  94. }
  95. IRemoteConnection* CWSESPControlEx::querySDSConnectionForESPSession(unsigned mode, unsigned timeout)
  96. {
  97. VStringBuffer xpath("/%s/%s[@name='%s']", PathSessionRoot, PathSessionProcess, espProcess.get());
  98. return querySDSConnection(xpath.str(), mode, timeout);
  99. }
  100. bool CWSESPControlEx::onSessionQuery(IEspContext& context, IEspSessionQueryRequest& req, IEspSessionQueryResponse& resp)
  101. {
  102. try
  103. {
  104. #ifdef _USE_OPENLDAP
  105. CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
  106. if(secmgr && !secmgr->isSuperUser(context.queryUser()))
  107. throw MakeStringException(ECLWATCH_SUPER_USER_ACCESS_DENIED, "Failed to query session. Permission denied.");
  108. #endif
  109. StringBuffer xpath;
  110. setSessionXPath(false, nullptr, req.getUserID(), req.getFromIP(), xpath);
  111. IArrayOf<IEspSession> sessions;
  112. Owned<IRemoteConnection> globalLock = querySDSConnectionForESPSession(RTM_LOCK_READ, SESSION_SDS_LOCK_TIMEOUT);
  113. Owned<IPropertyTreeIterator> iter = globalLock->queryRoot()->getElements("*");
  114. ForEach(*iter)
  115. {
  116. IPropertyTree& appSessionTree = iter->query();
  117. unsigned port = appSessionTree.getPropInt("@port");
  118. Owned<IPropertyTreeIterator> iter1 = appSessionTree.getElements(xpath.str());
  119. ForEach(*iter1)
  120. {
  121. IPropertyTree& sessionTree = iter1->query();
  122. Owned<IEspSession> s = createSession();
  123. setSessionInfo(&sessionTree, port, s);
  124. sessions.append(*s.getLink());
  125. }
  126. }
  127. resp.setSessions(sessions);
  128. }
  129. catch(IException* e)
  130. {
  131. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  132. }
  133. return true;
  134. }
  135. bool CWSESPControlEx::onSessionInfo(IEspContext& context, IEspSessionInfoRequest& req, IEspSessionInfoResponse& resp)
  136. {
  137. try
  138. {
  139. #ifdef _USE_OPENLDAP
  140. CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
  141. if(secmgr && !secmgr->isSuperUser(context.queryUser()))
  142. throw MakeStringException(ECLWATCH_SUPER_USER_ACCESS_DENIED, "Failed to get session information. Permission denied.");
  143. #endif
  144. StringBuffer id = req.getID();
  145. if (id.trim().isEmpty())
  146. throw MakeStringException(ECLWATCH_INVALID_INPUT, "ID not specified.");
  147. unsigned port = 8010;
  148. if (!req.getPort_isNull())
  149. port = req.getPort();
  150. Owned<IRemoteConnection> globalLock;
  151. VStringBuffer xpath("/%s/%s[@name='%s']/%s[@port='%d']/%s[%s='%s']", PathSessionRoot, PathSessionProcess, espProcess.get(),
  152. PathSessionApplication, port, PathSessionSession, PropSessionExternalID, id.str());
  153. try
  154. {
  155. globalLock.setown(querySDSConnection(xpath.str(), RTM_LOCK_READ, SESSION_SDS_LOCK_TIMEOUT));
  156. }
  157. catch(IException* e)
  158. {
  159. VStringBuffer msg("Failed to get session info for id %s on port %u: ", id.str(), port);
  160. e->errorMessage(msg);
  161. e->Release();
  162. throw MakeStringException(ECLWATCH_INVALID_INPUT, "%s", msg.str());
  163. }
  164. setSessionInfo(globalLock->queryRoot(), port, &resp.updateSession());
  165. }
  166. catch(IException* e)
  167. {
  168. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  169. }
  170. return true;
  171. }
  172. bool CWSESPControlEx::onCleanSession(IEspContext& context, IEspCleanSessionRequest& req, IEspCleanSessionResponse& resp)
  173. {
  174. try
  175. {
  176. #ifdef _USE_OPENLDAP
  177. CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
  178. if(secmgr && !secmgr->isSuperUser(context.queryUser()))
  179. throw MakeStringException(ECLWATCH_SUPER_USER_ACCESS_DENIED, "Failed to clean session. Permission denied.");
  180. #endif
  181. StringBuffer id, userID, fromIP;
  182. bool allSessions = req.getAllSessions();
  183. if (!allSessions)
  184. {
  185. id.set(req.getID());
  186. userID.set(req.getUserID());
  187. fromIP.set(req.getFromIP());
  188. if ((id.trim().isEmpty()) && (userID.trim().isEmpty()) && (fromIP.trim().isEmpty()))
  189. throw MakeStringException(ECLWATCH_INVALID_INPUT, "ID, userID or FromIP has to be specified.");
  190. }
  191. cleanSessions(allSessions, id.str(), userID.str(), fromIP.str());
  192. resp.setStatus(0);
  193. resp.setMessage("Session is cleaned.");
  194. }
  195. catch(IException* e)
  196. {
  197. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  198. }
  199. return true;
  200. }
  201. bool CWSESPControlEx::onSetSessionTimeout(IEspContext& context, IEspSetSessionTimeoutRequest& req, IEspSetSessionTimeoutResponse& resp)
  202. {
  203. try
  204. {
  205. #ifdef _USE_OPENLDAP
  206. CLdapSecManager* secmgr = dynamic_cast<CLdapSecManager*>(context.querySecManager());
  207. if(secmgr && !secmgr->isSuperUser(context.queryUser()))
  208. throw MakeStringException(ECLWATCH_SUPER_USER_ACCESS_DENIED, "Failed to set session timeout. Permission denied.");
  209. #endif
  210. StringBuffer id, userID, fromIP;
  211. bool allSessions = req.getAllSessions();
  212. if (!allSessions)
  213. {
  214. id.set(req.getID());
  215. userID.set(req.getUserID());
  216. fromIP.set(req.getFromIP());
  217. if ((id.trim().isEmpty()) && (userID.trim().isEmpty()) && (fromIP.trim().isEmpty()))
  218. throw MakeStringException(ECLWATCH_INVALID_INPUT, "ID, userID or FromIP has to be specified.");
  219. }
  220. int timeoutMinutes = req.getTimeoutMinutes_isNull() ? 0 : req.getTimeoutMinutes();
  221. if (timeoutMinutes <= 0)
  222. cleanSessions(allSessions, id.str(), userID.str(), fromIP.str());
  223. else
  224. {
  225. StringBuffer searchPath;
  226. setSessionXPath(allSessions, id.str(), userID.str(), fromIP.str(), searchPath);
  227. Owned<IRemoteConnection> globalLock = querySDSConnectionForESPSession(RTM_LOCK_WRITE, SESSION_SDS_LOCK_TIMEOUT);
  228. Owned<IPropertyTreeIterator> iter = globalLock->queryRoot()->getElements("*");
  229. ForEach(*iter)
  230. {
  231. Owned<IPropertyTreeIterator> iter1 = iter->query().getElements(searchPath.str());
  232. ForEach(*iter1)
  233. setSessionTimeout(timeoutMinutes, iter1->query());
  234. }
  235. }
  236. resp.setStatus(0);
  237. resp.setMessage("Session timeout is updated.");
  238. }
  239. catch(IException* e)
  240. {
  241. FORWARDEXCEPTION(context, e, ECLWATCH_INTERNAL_ERROR);
  242. }
  243. return true;
  244. }
  245. const char* CWSESPControlEx::setSessionXPath(bool allSessions, const char* id, const char* userID, const char* fromIP, StringBuffer& xPath)
  246. {
  247. if (allSessions)
  248. {
  249. xPath.set("*");
  250. return xPath.str();
  251. }
  252. if (!isEmptyString(userID))
  253. xPath.setf("%s[%s='%s']", PathSessionSession, PropSessionUserID, userID);
  254. else if (!isEmptyString(fromIP))
  255. xPath.setf("%s[%s='%s']", PathSessionSession, PropSessionNetworkAddress, fromIP);
  256. else if (!isEmptyString(id))
  257. xPath.setf("%s[%s='%s']", PathSessionSession, PropSessionExternalID, id);
  258. else
  259. xPath.set("*");
  260. return xPath.str();
  261. }
  262. void CWSESPControlEx::cleanSessions(bool allSessions, const char* _id, const char* _userID, const char* _fromIP)
  263. {
  264. StringBuffer searchPath;
  265. setSessionXPath(allSessions, _id, _userID, _fromIP, searchPath);
  266. Owned<IRemoteConnection> globalLock = querySDSConnectionForESPSession(RTM_LOCK_WRITE, SESSION_SDS_LOCK_TIMEOUT);
  267. Owned<IPropertyTreeIterator> iter = globalLock->queryRoot()->getElements("*");
  268. ForEach(*iter)
  269. {
  270. IArrayOf<IPropertyTree> toRemove;
  271. Owned<IPropertyTreeIterator> iter1 = iter->query().getElements(searchPath.str());
  272. ForEach(*iter1)
  273. toRemove.append(*LINK(&iter1->query()));
  274. ForEachItemIn(i, toRemove)
  275. iter->query().removeTree(&toRemove.item(i));
  276. }
  277. }
  278. void CWSESPControlEx::setSessionTimeout(int timeoutMinutes, IPropertyTree& session)
  279. {
  280. CDateTime timeNow;
  281. timeNow.setNow();
  282. time_t simple = timeNow.getSimple() + timeoutMinutes*60;
  283. session.setPropInt64(PropSessionTimeoutAt, simple);
  284. session.setPropBool(PropSessionTimeoutByAdmin, true);
  285. }