fixed compiler warnings; minor refactoring
[public/netxms.git] / src / server / core / session.cpp
CommitLineData
7a4c94ee 1/*
5039dede 2** NetXMS - Network Management System
69e8229d 3** Copyright (C) 2003-2017 Raden Solutions
5039dede
AK
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18**
19** File: session.cpp
20**
21**/
22
23#include "nxcore.h"
fdbee7f8 24#include <netxms_mt.h>
bf6fb6c3 25#include <nxtools.h>
9ece2b31 26#include <nxstat.h>
5039dede
AK
27
28#ifdef _WIN32
29#include <psapi.h>
30#else
31#include <dirent.h>
32#endif
33
4ef60905
AK
34#ifdef WITH_ZMQ
35#include "zeromq.h"
36#endif
37
c733fcc4 38// WARNING! this hack works only for d2i_X509(); be careful when adding new code
5039dede
AK
39#ifdef OPENSSL_CONST
40# undef OPENSSL_CONST
41#endif
42#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
43# define OPENSSL_CONST const
44#else
45# define OPENSSL_CONST
46#endif
47
534e1b83
VK
48/**
49 * Constants
50 */
5039dede
AK
51#define TRAP_CREATE 1
52#define TRAP_UPDATE 2
53#define TRAP_DELETE 3
54
b9b2b87b 55#define MAX_MSG_SIZE 4194304
5039dede 56
534e1b83
VK
57/**
58 * Externals
59 */
5039dede 60extern Queue g_nodePollerQueue;
d140955e 61extern Queue g_dciCacheLoaderQueue;
b239e165 62extern ThreadPool *g_dataCollectorThreadPool;
5039dede 63
2a964810 64void UnregisterClientSession(int id);
b9b2b87b 65void ResetDiscoveryPoller();
b368969c 66NXCPMessage *ForwardMessageToReportingServer(NXCPMessage *request, ClientSession *session);
bc7767c4 67void RemovePendingFileTransferRequests(ClientSession *session);
ba889094 68bool UpdateAddressListFromMessage(NXCPMessage *msg);
4fd0b7ca 69void FillComponentsMessage(NXCPMessage *msg);
c733fcc4 70
0cf6fcbd
VK
71void GetPredictionEngines(NXCPMessage *msg);
72bool GetPredictedData(ClientSession *session, const NXCPMessage *request, NXCPMessage *response, DataCollectionTarget *dcTarget);
5039dede 73
3c463101 74void GetAgentTunnels(NXCPMessage *msg);
c733fcc4
VK
75UINT32 BindAgentTunnel(UINT32 tunnelId, UINT32 nodeId);
76UINT32 UnbindAgentTunnel(UINT32 nodeId);
77
78
534e1b83
VK
79/**
80 * Node poller start data
81 */
5039dede
AK
82typedef struct
83{
84 ClientSession *pSession;
91b3cba9 85 DataCollectionTarget *pTarget;
5039dede 86 int iPollType;
967893bb 87 UINT32 dwRqId;
5039dede
AK
88} POLLER_START_DATA;
89
534e1b83
VK
90/**
91 * Additional processing thread start data
92 */
5039dede
AK
93typedef struct
94{
95 ClientSession *pSession;
b368969c 96 NXCPMessage *pMsg;
5039dede
AK
97} PROCTHREAD_START_DATA;
98
534e1b83 99/**
c044d4f3 100 * Callback to delete agent connections for loading files in destructor
7cf549ad 101 */
102static void DeleteCallback(NetObj* obj, void *data)
103{
7dd6369a 104 ((AgentConnection *)obj)->decRefCount();
7cf549ad 105}
106
107/**
8581943e
VK
108 * Callback for sending image library delete notifications
109 */
110static void ImageLibraryDeleteCallback(ClientSession *pSession, void *pArg)
111{
b8b6cd2f 112 pSession->onLibraryImageChange(*((const uuid *)pArg), true);
8581943e
VK
113}
114
115/**
534e1b83
VK
116 * Additional message processing thread starters
117 */
5039dede
AK
118#define CALL_IN_NEW_THREAD(func, msg) \
119{ \
120 PROCTHREAD_START_DATA *pData = (PROCTHREAD_START_DATA *)malloc(sizeof(PROCTHREAD_START_DATA)); \
121 pData->pSession = this; \
122 pData->pMsg = msg; \
123 msg = NULL; /* prevent deletion by main processing thread*/ \
c044d4f3 124 InterlockedIncrement(&m_refCount); \
134c3d00 125 ThreadPoolExecute(g_mainThreadPool, ThreadStarter_##func, pData); \
5039dede
AK
126}
127
128#define DEFINE_THREAD_STARTER(func) \
134c3d00 129void ClientSession::ThreadStarter_##func(void *pArg) \
5039dede 130{ \
43750f03 131 ((PROCTHREAD_START_DATA *)pArg)->pSession->debugPrintf(6, _T("Method ") _T(#func) _T(" called on background thread")); \
5039dede 132 ((PROCTHREAD_START_DATA *)pArg)->pSession->func(((PROCTHREAD_START_DATA *)pArg)->pMsg); \
c044d4f3 133 InterlockedDecrement(&((PROCTHREAD_START_DATA *)pArg)->pSession->m_refCount); \
5039dede
AK
134 delete ((PROCTHREAD_START_DATA *)pArg)->pMsg; \
135 free(pArg); \
5039dede
AK
136}
137
78ccd7b4 138DEFINE_THREAD_STARTER(cancelFileMonitoring)
92c51b1d 139DEFINE_THREAD_STARTER(clearDCIData)
1da08bc6 140DEFINE_THREAD_STARTER(createObject)
e31c8e60 141DEFINE_THREAD_STARTER(executeAction)
78ccd7b4 142DEFINE_THREAD_STARTER(executeScript)
e9bf9011 143DEFINE_THREAD_STARTER(executeLibraryScript)
78ccd7b4 144DEFINE_THREAD_STARTER(fileManagerControl)
80e0db05 145DEFINE_THREAD_STARTER(findIpAddress)
78ccd7b4 146DEFINE_THREAD_STARTER(findMacAddress)
f1984eb9 147DEFINE_THREAD_STARTER(findHostname)
78ccd7b4
VK
148DEFINE_THREAD_STARTER(findNodeConnection)
149DEFINE_THREAD_STARTER(forceDCIPoll)
150DEFINE_THREAD_STARTER(forwardToReportingServer)
151DEFINE_THREAD_STARTER(getAgentFile)
3ddc492b 152DEFINE_THREAD_STARTER(getAlarms)
2bac37f9 153DEFINE_THREAD_STARTER(getAlarmEvents)
78ccd7b4
VK
154DEFINE_THREAD_STARTER(getCollectedData)
155DEFINE_THREAD_STARTER(getLocationHistory)
156DEFINE_THREAD_STARTER(getNetworkPath)
0cf6fcbd 157DEFINE_THREAD_STARTER(getPredictedData)
78ccd7b4
VK
158DEFINE_THREAD_STARTER(getRoutingTable)
159DEFINE_THREAD_STARTER(getServerFile)
160DEFINE_THREAD_STARTER(getServerLogQueryData)
161DEFINE_THREAD_STARTER(getSwitchForwardingDatabase)
162DEFINE_THREAD_STARTER(getTableCollectedData)
163DEFINE_THREAD_STARTER(importConfiguration)
3c35018e 164DEFINE_THREAD_STARTER(openHelpdeskIssue)
78ccd7b4
VK
165DEFINE_THREAD_STARTER(processConsoleCommand)
166DEFINE_THREAD_STARTER(queryAgentTable)
167DEFINE_THREAD_STARTER(queryL2Topology)
168DEFINE_THREAD_STARTER(queryParameter)
169DEFINE_THREAD_STARTER(queryServerLog)
78ccd7b4 170DEFINE_THREAD_STARTER(sendMib)
7cf549ad 171DEFINE_THREAD_STARTER(uploadUserFileToAgent)
badd6e08
VK
172DEFINE_THREAD_STARTER(getRepositories)
173DEFINE_THREAD_STARTER(addRepository)
174DEFINE_THREAD_STARTER(modifyRepository)
175DEFINE_THREAD_STARTER(deleteRepository)
5039dede 176
534e1b83
VK
177/**
178 * Client communication read thread starter
179 */
180THREAD_RESULT THREAD_CALL ClientSession::readThreadStarter(void *pArg)
5039dede 181{
930a2a62 182 ThreadSetName("SessionReader");
62768df3 183 ((ClientSession *)pArg)->readThread();
5039dede
AK
184
185 // When ClientSession::ReadThread exits, all other session
186 // threads are already stopped, so we can safely destroy
187 // session object
2a964810 188 UnregisterClientSession(((ClientSession *)pArg)->getId());
5039dede
AK
189 delete (ClientSession *)pArg;
190 return THREAD_OK;
191}
192
134c3d00 193 /**
534e1b83
VK
194 * Client communication write thread starter
195 */
196THREAD_RESULT THREAD_CALL ClientSession::writeThreadStarter(void *pArg)
5039dede 197{
930a2a62 198 ThreadSetName("SessionWriter");
62768df3 199 ((ClientSession *)pArg)->writeThread();
5039dede
AK
200 return THREAD_OK;
201}
202
534e1b83
VK
203/**
204 * Received message processing thread starter
205 */
206THREAD_RESULT THREAD_CALL ClientSession::processingThreadStarter(void *pArg)
5039dede 207{
930a2a62 208 ThreadSetName("SessionProc");
62768df3 209 ((ClientSession *)pArg)->processingThread();
5039dede
AK
210 return THREAD_OK;
211}
212
534e1b83 213/**
534e1b83
VK
214 * Client session class constructor
215 */
f0718805 216ClientSession::ClientSession(SOCKET hSocket, const InetAddress& addr)
5039dede 217{
b784f8ac
VK
218 m_sendQueue = new Queue;
219 m_requestQueue = new Queue;
5039dede 220 m_hSocket = hSocket;
2a964810
VK
221 m_id = -1;
222 m_state = SESSION_STATE_INIT;
5039dede
AK
223 m_pCtx = NULL;
224 m_hWriteThread = INVALID_THREAD_HANDLE;
225 m_hProcessingThread = INVALID_THREAD_HANDLE;
d3a7cf4c 226 m_mutexSocketWrite = MutexCreate();
5039dede
AK
227 m_mutexSendObjects = MutexCreate();
228 m_mutexSendAlarms = MutexCreate();
229 m_mutexSendActions = MutexCreate();
230 m_mutexSendAuditLog = MutexCreate();
5039dede 231 m_mutexPollerInit = MutexCreate();
c044d4f3 232 m_subscriptionLock = MutexCreate();
84ea7692 233 m_subscriptions = new StringObjectMap<UINT32>(true);
5039dede 234 m_dwFlags = 0;
f8c6f10f 235 m_clientType = CLIENT_TYPE_DESKTOP;
f0718805
VK
236 m_clientAddr = addr;
237 m_clientAddr.toString(m_workstation);
91f6b72c 238 m_webServerAddress[0] = 0;
77a08c86
VK
239 m_loginName[0] = 0;
240 _tcscpy(m_sessionName, _T("<not logged in>"));
241 _tcscpy(m_clientInfo, _T("n/a"));
5039dede 242 m_dwUserId = INVALID_INDEX;
c044d4f3 243 m_dwSystemAccess = 0;
5039dede
AK
244 m_dwOpenDCIListSize = 0;
245 m_pOpenDCIList = NULL;
246 m_ppEPPRuleList = NULL;
c044d4f3 247 m_wCurrentCmd = 0;
c044d4f3
VK
248 m_dwNumRecordsToUpload = 0;
249 m_dwRecordsUploaded = 0;
250 m_refCount = 0;
5039dede 251 m_dwEncryptionRqId = 0;
c044d4f3 252 m_dwEncryptionResult = 0;
5039dede 253 m_condEncryptionSetup = INVALID_CONDITION_HANDLE;
200d662d 254 m_console = NULL;
a51628e2 255 m_loginTime = time(NULL);
33dfe57e 256 m_musicTypeList.add(_T("wav"));
2a964810 257 _tcscpy(m_language, _T("en"));
45ac5dd0 258 m_serverCommands = new HashMap<UINT32, CommandExec>(true);
b8b6cd2f 259 m_downloadFileMap = new HashMap<UINT32, ServerDownloadFileInfo>(true);
5039dede
AK
260}
261
534e1b83
VK
262/**
263 * Destructor
264 */
5039dede
AK
265ClientSession::~ClientSession()
266{
267 if (m_hSocket != -1)
268 closesocket(m_hSocket);
b784f8ac
VK
269 delete m_sendQueue;
270 delete m_requestQueue;
d3a7cf4c 271 MutexDestroy(m_mutexSocketWrite);
5039dede
AK
272 MutexDestroy(m_mutexSendObjects);
273 MutexDestroy(m_mutexSendAlarms);
274 MutexDestroy(m_mutexSendActions);
275 MutexDestroy(m_mutexSendAuditLog);
5039dede 276 MutexDestroy(m_mutexPollerInit);
c044d4f3 277 MutexDestroy(m_subscriptionLock);
84ea7692
VK
278 delete m_subscriptions;
279 free(m_pOpenDCIList);
5039dede
AK
280 if (m_ppEPPRuleList != NULL)
281 {
967893bb 282 UINT32 i;
5039dede
AK
283
284 if (m_dwFlags & CSF_EPP_UPLOAD) // Aborted in the middle of EPP transfer
285 for(i = 0; i < m_dwRecordsUploaded; i++)
286 delete m_ppEPPRuleList[i];
287 free(m_ppEPPRuleList);
288 }
98abc9f1
VK
289 if (m_pCtx != NULL)
290 m_pCtx->decRefCount();
5039dede
AK
291 if (m_condEncryptionSetup != INVALID_CONDITION_HANDLE)
292 ConditionDestroy(m_condEncryptionSetup);
7a4c94ee 293
200d662d
VK
294 if (m_console != NULL)
295 {
296 delete m_console->pMsg;
297 free(m_console);
298 }
810bd8c4 299 m_musicTypeList.clear();
a6312bd6 300 if (m_agentConn.size() > 0)
7cf549ad 301 {
302 m_agentConn.forEach(&DeleteCallback, NULL);
303 }
45ac5dd0
EJ
304
305 delete m_serverCommands;
69e8229d 306 delete m_downloadFileMap;
5039dede
AK
307}
308
534e1b83
VK
309/**
310 * Start all threads
311 */
200d662d 312void ClientSession::run()
5039dede 313{
534e1b83
VK
314 m_hWriteThread = ThreadCreateEx(writeThreadStarter, 0, this);
315 m_hProcessingThread = ThreadCreateEx(processingThreadStarter, 0, this);
534e1b83 316 ThreadCreate(readThreadStarter, 0, this);
5039dede
AK
317}
318
534e1b83
VK
319/**
320 * Print debug information
321 */
322void ClientSession::debugPrintf(int level, const TCHAR *format, ...)
5039dede 323{
2df047f4 324 if (level <= nxlog_get_debug_level())
5039dede
AK
325 {
326 va_list args;
6be0a20b 327 TCHAR buffer[8192];
5039dede
AK
328
329 va_start(args, format);
6be0a20b 330 _vsntprintf(buffer, 8192, format, args);
5039dede 331 va_end(args);
2a964810 332 DbgPrintf(level, _T("[CLSN-%d] %s"), m_id, buffer);
5039dede
AK
333 }
334}
335
534e1b83 336/**
badd6e08
VK
337 * Write audit log
338 */
339void ClientSession::writeAuditLog(const TCHAR *subsys, bool success, UINT32 objectId, const TCHAR *format, ...)
340{
341 va_list args;
342 va_start(args, format);
343 WriteAuditLog2(subsys, success, m_dwUserId, m_workstation, m_id, objectId, format, args);
344 va_end(args);
345}
346
347/**
dbb49f94
VK
348 * Write audit log with old and new values for changed entity
349 */
350void ClientSession::writeAuditLogWithValues(const TCHAR *subsys, bool success, UINT32 objectId, const TCHAR *oldValue, const TCHAR *newValue, const TCHAR *format, ...)
351{
352 va_list args;
353 va_start(args, format);
354 WriteAuditLogWithValues2(subsys, success, m_dwUserId, m_workstation, m_id, objectId, oldValue, newValue, format, args);
355 va_end(args);
356}
357
358/**
0d402aa8
VK
359 * Write audit log with old and new values for changed entity
360 */
361void ClientSession::writeAuditLogWithValues(const TCHAR *subsys, bool success, UINT32 objectId, json_t *oldValue, json_t *newValue, const TCHAR *format, ...)
362{
363 va_list args;
364 va_start(args, format);
365 WriteAuditLogWithJsonValues2(subsys, success, m_dwUserId, m_workstation, m_id, objectId, oldValue, newValue, format, args);
366 va_end(args);
367}
368
369/**
c044d4f3
VK
370 * Check channel subscription
371 */
372bool ClientSession::isSubscribedTo(const TCHAR *channel) const
373{
374 MutexLock(m_subscriptionLock);
84ea7692 375 bool subscribed = m_subscriptions->contains(channel);
c044d4f3
VK
376 MutexUnlock(m_subscriptionLock);
377 return subscribed;
378}
379
380/**
534e1b83
VK
381 * Read thread
382 */
62768df3 383void ClientSession::readThread()
5039dede 384{
5039dede 385 TCHAR szBuffer[256];
967893bb 386 UINT32 i;
fffcff95 387 NetObj *object;
5039dede 388
6be0a20b
VK
389 SocketMessageReceiver receiver(m_hSocket, 4096, MAX_MSG_SIZE);
390 while(true)
5039dede 391 {
6be0a20b 392 MessageReceiverResult result;
b368969c 393 NXCPMessage *msg = receiver.readMessage(900000, &result);
5039dede
AK
394
395 // Check for decryption error
6be0a20b 396 if (result == MSGRECV_DECRYPTION_FAILURE)
5039dede 397 {
bf6fb6c3 398 debugPrintf(4, _T("readThread: Unable to decrypt received message"));
5039dede
AK
399 continue;
400 }
401
b368969c 402 // Receive error
6be0a20b 403 if (msg == NULL)
5039dede 404 {
578958a5
VK
405 if (result == MSGRECV_CLOSED)
406 debugPrintf(5, _T("readThread: connection closed"));
407 else
408 debugPrintf(5, _T("readThread: message receiving error (%s)"), AbstractMessageReceiver::resultToText(result));
6be0a20b 409 break;
5039dede
AK
410 }
411
2df047f4 412 if (nxlog_get_debug_level() >= 8)
934f53da 413 {
b368969c 414 String msgDump = NXCPMessage::dump(receiver.getRawMessageBuffer(), NXCP_VERSION);
934f53da
VK
415 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR *)msgDump);
416 }
417
5039dede 418 // Special handling for raw messages
6be0a20b 419 if (msg->isBinary())
5039dede 420 {
b368969c 421 debugPrintf(6, _T("Received raw message %s"), NXCPMessageCodeName(msg->getCode(), szBuffer));
6be0a20b 422
b368969c
VK
423 if ((msg->getCode() == CMD_FILE_DATA) ||
424 (msg->getCode() == CMD_ABORT_FILE_TRANSFER))
5039dede 425 {
b8b6cd2f 426 ServerDownloadFileInfo *dInfo = m_downloadFileMap->get(msg->getId());
7b45b90d 427 if (dInfo != NULL)
5039dede 428 {
b368969c 429 if (msg->getCode() == CMD_FILE_DATA)
5039dede 430 {
b8b6cd2f 431 if (dInfo->write(msg->getBinaryData(), msg->getBinaryDataSize(), msg->isCompressedStream()))
5039dede 432 {
6be0a20b 433 if (msg->isEndOfFile())
5039dede 434 {
534e1b83 435 debugPrintf(6, _T("Got end of file marker"));
b368969c 436 NXCPMessage response;
5039dede 437
b368969c
VK
438 response.setCode(CMD_REQUEST_COMPLETED);
439 response.setId(msg->getId());
440 response.setField(VID_RCC, RCC_SUCCESS);
6be0a20b 441 sendMessage(&response);
5039dede 442
7b45b90d 443 dInfo->close(true);
69e8229d 444 m_downloadFileMap->remove(msg->getId());
5039dede
AK
445 }
446 }
447 else
448 {
534e1b83 449 debugPrintf(6, _T("I/O error"));
5039dede 450 // I/O error
b368969c 451 NXCPMessage response;
5039dede 452
b368969c
VK
453 response.setCode(CMD_REQUEST_COMPLETED);
454 response.setId(msg->getId());
455 response.setField(VID_RCC, RCC_IO_ERROR);
6be0a20b 456 sendMessage(&response);
5039dede 457
7b45b90d 458 dInfo->close(false);
69e8229d 459 m_downloadFileMap->remove(msg->getId());
5039dede
AK
460 }
461 }
462 else
463 {
464 // Abort current file transfer because of client's problem
7b45b90d 465 dInfo->close(false);
69e8229d 466 m_downloadFileMap->remove(msg->getId());
5039dede
AK
467 }
468 }
469 else
470 {
b368969c 471 AgentConnection *conn = (AgentConnection *)m_agentConn.get(msg->getId());
6be0a20b 472 if (conn != NULL)
7cf549ad 473 {
b368969c 474 if (msg->getCode() == CMD_FILE_DATA)
7cf549ad 475 {
6be0a20b 476 if (conn->sendMessage(msg)) //send raw message
7cf549ad 477 {
6be0a20b 478 if (msg->isEndOfFile())
7cf549ad 479 {
480 debugPrintf(6, _T("Got end of file marker"));
481 //get response with specific ID if ok< then send ok, else send error
b368969c 482 m_agentConn.remove(msg->getId());
7dd6369a 483 conn->decRefCount();
7cf549ad 484
b368969c
VK
485 NXCPMessage response;
486 response.setCode(CMD_REQUEST_COMPLETED);
487 response.setId(msg->getId());
488 response.setField(VID_RCC, RCC_SUCCESS);
6be0a20b 489 sendMessage(&response);
7cf549ad 490 }
491 }
492 else
493 {
494 debugPrintf(6, _T("Error while sending to agent"));
495 // I/O error
b368969c 496 m_agentConn.remove(msg->getId());
7dd6369a 497 conn->decRefCount();
7cf549ad 498
b368969c
VK
499 NXCPMessage response;
500 response.setCode(CMD_REQUEST_COMPLETED);
501 response.setId(msg->getId());
502 response.setField(VID_RCC, RCC_IO_ERROR); //set result that came from agent
6be0a20b 503 sendMessage(&response);
7cf549ad 504 }
505 }
506 else
507 {
508 // Resend abort message
6be0a20b 509 conn->sendMessage(msg);
b368969c 510 m_agentConn.remove(msg->getId());
7dd6369a 511 conn->decRefCount();
7cf549ad 512 }
513 }
514 else
515 {
b368969c 516 debugPrintf(4, _T("Out of state message (ID: %d)"), msg->getId());
7cf549ad 517 }
5039dede
AK
518 }
519 }
6be0a20b 520 delete msg;
5039dede
AK
521 }
522 else
523 {
b368969c 524 if ((msg->getCode() == CMD_SESSION_KEY) && (msg->getId() == m_dwEncryptionRqId))
5039dede 525 {
b368969c 526 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(msg->getCode(), szBuffer));
6be0a20b
VK
527 m_dwEncryptionResult = SetupEncryptionContext(msg, &m_pCtx, NULL, g_pServerKey, NXCP_VERSION);
528 receiver.setEncryptionContext(m_pCtx);
5039dede
AK
529 ConditionSet(m_condEncryptionSetup);
530 m_dwEncryptionRqId = 0;
6be0a20b 531 delete msg;
5039dede 532 }
b368969c 533 else if (msg->getCode() == CMD_KEEPALIVE)
5039dede 534 {
b368969c
VK
535 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(msg->getCode(), szBuffer));
536 respondToKeepalive(msg->getId());
6be0a20b 537 delete msg;
5039dede
AK
538 }
539 else
540 {
b784f8ac 541 m_requestQueue->put(msg);
5039dede
AK
542 }
543 }
544 }
5039dede 545
134c3d00
VK
546 // Mark as terminated (sendMessage calls will not work after that point)
547 m_dwFlags |= CSF_TERMINATED;
548
5039dede 549 // Notify other threads to exit
b368969c 550 NXCP_MESSAGE *rawMsg;
b784f8ac 551 while((rawMsg = (NXCP_MESSAGE *)m_sendQueue->get()) != NULL)
134c3d00 552 free(rawMsg);
b784f8ac 553 m_sendQueue->put(INVALID_POINTER_VALUE);
6be0a20b 554
b368969c 555 NXCPMessage *msg;
b784f8ac 556 while((msg = (NXCPMessage *)m_requestQueue->get()) != NULL)
6be0a20b 557 delete msg;
b784f8ac 558 m_requestQueue->put(INVALID_POINTER_VALUE);
5039dede
AK
559
560 // Wait for other threads to finish
561 ThreadJoin(m_hWriteThread);
562 ThreadJoin(m_hProcessingThread);
5039dede 563
bc7767c4
VK
564 // remove all pending file transfers from reporting server
565 RemovePendingFileTransferRequests(this);
566
5039dede 567 // Remove all locks created by this session
2a964810 568 RemoveAllSessionLocks(m_id);
5039dede
AK
569 for(i = 0; i < m_dwOpenDCIListSize; i++)
570 {
fffcff95
VK
571 object = FindObjectById(m_pOpenDCIList[i]);
572 if (object != NULL)
46e2b370 573 if (object->isDataCollectionTarget() || (object->getObjectClass() == OBJECT_TEMPLATE))
2a964810 574 ((Template *)object)->unlockDCIList(m_id);
5039dede
AK
575 }
576
577 // Waiting while reference count becomes 0
c044d4f3 578 if (m_refCount > 0)
5039dede 579 {
534e1b83 580 debugPrintf(3, _T("Waiting for pending requests..."));
5039dede
AK
581 do
582 {
583 ThreadSleep(1);
c044d4f3 584 } while(m_refCount > 0);
5039dede
AK
585 }
586
a77272b7
VK
587 if (m_dwFlags & CSF_AUTHENTICATED)
588 {
a0efa7b5 589 CALL_ALL_MODULES(pfClientSessionClose, (this));
77a08c86 590 WriteAuditLog(AUDIT_SECURITY, TRUE, m_dwUserId, m_workstation, m_id, 0, _T("User logged out (client: %s)"), m_clientInfo);
a77272b7 591 }
534e1b83 592 debugPrintf(3, _T("Session closed"));
5039dede
AK
593}
594
534e1b83
VK
595/**
596 * Network write thread
597 */
62768df3 598void ClientSession::writeThread()
5039dede 599{
6be0a20b 600 while(true)
5039dede 601 {
b784f8ac 602 NXCP_MESSAGE *rawMsg = (NXCP_MESSAGE *)m_sendQueue->getOrBlock();
6be0a20b 603 if (rawMsg == INVALID_POINTER_VALUE) // Session termination indicator
5039dede
AK
604 break;
605
134c3d00 606 sendRawMessage(rawMsg);
6be0a20b 607 free(rawMsg);
5039dede
AK
608 }
609}
610
534e1b83 611/**
534e1b83
VK
612 * Message processing thread
613 */
62768df3 614void ClientSession::processingThread()
5039dede 615{
b368969c 616 NXCPMessage *pMsg;
35f836fe 617 TCHAR szBuffer[128];
967893bb 618 UINT32 i;
5039dede
AK
619 int status;
620
4970ef34 621 while(true)
5039dede 622 {
b784f8ac 623 pMsg = (NXCPMessage *)m_requestQueue->getOrBlock();
5039dede
AK
624 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
625 break;
626
b368969c 627 m_wCurrentCmd = pMsg->getCode();
534e1b83 628 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(m_wCurrentCmd, szBuffer));
7a4c94ee 629 if (!(m_dwFlags & CSF_AUTHENTICATED) &&
630 (m_wCurrentCmd != CMD_LOGIN) &&
5039dede
AK
631 (m_wCurrentCmd != CMD_GET_SERVER_INFO) &&
632 (m_wCurrentCmd != CMD_REQUEST_ENCRYPTION) &&
a854d114
VK
633 (m_wCurrentCmd != CMD_GET_MY_CONFIG) &&
634 (m_wCurrentCmd != CMD_REGISTER_AGENT))
5039dede
AK
635 {
636 delete pMsg;
637 continue;
638 }
639
2a964810 640 m_state = SESSION_STATE_PROCESSING;
5039dede
AK
641 switch(m_wCurrentCmd)
642 {
643 case CMD_LOGIN:
711e5e9a 644 login(pMsg);
5039dede
AK
645 break;
646 case CMD_GET_SERVER_INFO:
b368969c 647 sendServerInfo(pMsg->getId());
5039dede 648 break;
5039dede 649 case CMD_GET_MY_CONFIG:
6b29839d 650 sendConfigForAgent(pMsg);
5039dede
AK
651 break;
652 case CMD_GET_OBJECTS:
62768df3
VK
653 sendAllObjects(pMsg);
654 break;
655 case CMD_GET_SELECTED_OBJECTS:
656 sendSelectedObjects(pMsg);
5039dede 657 break;
5039dede 658 case CMD_GET_CONFIG_VARLIST:
c85c8ef2
VK
659 getConfigurationVariables(pMsg->getId());
660 break;
661 case CMD_GET_PUBLIC_CONFIG_VAR:
662 getPublicConfigurationVariable(pMsg);
5039dede
AK
663 break;
664 case CMD_SET_CONFIG_VARIABLE:
c85c8ef2 665 setConfigurationVariable(pMsg);
5039dede 666 break;
c7aa788e
EJ
667 case CMD_SET_CONFIG_TO_DEFAULT:
668 setDefaultConfigurationVariableValues(pMsg);
669 break;
5039dede 670 case CMD_DELETE_CONFIG_VARIABLE:
c85c8ef2 671 deleteConfigurationVariable(pMsg);
5039dede
AK
672 break;
673 case CMD_CONFIG_GET_CLOB:
1da08bc6 674 getConfigCLOB(pMsg);
5039dede
AK
675 break;
676 case CMD_CONFIG_SET_CLOB:
1da08bc6 677 setConfigCLOB(pMsg);
5039dede 678 break;
a881eafa
VK
679 case CMD_GET_ALARM_CATEGORIES:
680 getAlarmCategories(pMsg->getId());
6a6b96c0 681 break;
a881eafa 682 case CMD_MODIFY_ALARM_CATEGORY:
6a6b96c0
EJ
683 modifyAlarmCategory(pMsg);
684 break;
a881eafa
VK
685 case CMD_DELETE_ALARM_CATEGORY:
686 deleteAlarmCategory(pMsg);
6a6b96c0 687 break;
5039dede 688 case CMD_LOAD_EVENT_DB:
1b281c3e 689 sendEventDB(pMsg);
5039dede
AK
690 break;
691 case CMD_SET_EVENT_INFO:
8eb2d92b 692 modifyEventTemplate(pMsg);
5039dede
AK
693 break;
694 case CMD_DELETE_EVENT_TEMPLATE:
8eb2d92b 695 deleteEventTemplate(pMsg);
5039dede
AK
696 break;
697 case CMD_GENERATE_EVENT_CODE:
b368969c 698 generateEventCode(pMsg->getId());
5039dede
AK
699 break;
700 case CMD_MODIFY_OBJECT:
92c51b1d 701 modifyObject(pMsg);
5039dede
AK
702 break;
703 case CMD_SET_OBJECT_MGMT_STATUS:
1da08bc6 704 changeObjectMgmtStatus(pMsg);
5039dede 705 break;
7e18667a
VK
706 case CMD_ENTER_MAINT_MODE:
707 enterMaintenanceMode(pMsg);
708 break;
709 case CMD_LEAVE_MAINT_MODE:
710 leaveMaintenanceMode(pMsg);
711 break;
5039dede 712 case CMD_LOAD_USER_DB:
b368969c 713 sendUserDB(pMsg->getId());
5039dede
AK
714 break;
715 case CMD_CREATE_USER:
b1e9b6b3 716 createUser(pMsg);
5039dede
AK
717 break;
718 case CMD_UPDATE_USER:
b1e9b6b3 719 updateUser(pMsg);
5039dede 720 break;
2d8d8ea2 721 case CMD_DETACH_LDAP_USER:
722 detachLdapUser(pMsg);
723 break;
5039dede 724 case CMD_DELETE_USER:
b1e9b6b3 725 deleteUser(pMsg);
5039dede
AK
726 break;
727 case CMD_LOCK_USER_DB:
b368969c 728 lockUserDB(pMsg->getId(), TRUE);
5039dede
AK
729 break;
730 case CMD_UNLOCK_USER_DB:
b368969c 731 lockUserDB(pMsg->getId(), FALSE);
5039dede
AK
732 break;
733 case CMD_SET_PASSWORD:
b1e9b6b3 734 setPassword(pMsg);
5039dede 735 break;
77a08c86
VK
736 case CMD_VALIDATE_PASSWORD:
737 validatePassword(pMsg);
738 break;
5039dede 739 case CMD_GET_NODE_DCI_LIST:
92c51b1d 740 openNodeDCIList(pMsg);
5039dede
AK
741 break;
742 case CMD_UNLOCK_NODE_DCI_LIST:
92c51b1d 743 closeNodeDCIList(pMsg);
5039dede
AK
744 break;
745 case CMD_CREATE_NEW_DCI:
746 case CMD_MODIFY_NODE_DCI:
747 case CMD_DELETE_NODE_DCI:
92c51b1d 748 modifyNodeDCI(pMsg);
5039dede
AK
749 break;
750 case CMD_SET_DCI_STATUS:
92c51b1d 751 changeDCIStatus(pMsg);
5039dede
AK
752 break;
753 case CMD_COPY_DCI:
92c51b1d 754 copyDCI(pMsg);
5039dede
AK
755 break;
756 case CMD_APPLY_TEMPLATE:
92c51b1d 757 applyTemplate(pMsg);
5039dede
AK
758 break;
759 case CMD_GET_DCI_DATA:
92c51b1d
VK
760 CALL_IN_NEW_THREAD(getCollectedData, pMsg);
761 break;
762 case CMD_GET_TABLE_DCI_DATA:
763 CALL_IN_NEW_THREAD(getTableCollectedData, pMsg);
5039dede
AK
764 break;
765 case CMD_CLEAR_DCI_DATA:
92c51b1d 766 CALL_IN_NEW_THREAD(clearDCIData, pMsg);
5039dede 767 break;
79633a65 768 case CMD_FORCE_DCI_POLL:
769 CALL_IN_NEW_THREAD(forceDCIPoll, pMsg);
770 break;
5039dede 771 case CMD_OPEN_EPP:
c9630390 772 openEPP(pMsg);
5039dede
AK
773 break;
774 case CMD_CLOSE_EPP:
b368969c 775 closeEPP(pMsg->getId());
5039dede
AK
776 break;
777 case CMD_SAVE_EPP:
92c51b1d 778 saveEPP(pMsg);
5039dede
AK
779 break;
780 case CMD_EPP_RECORD:
92c51b1d 781 processEPPRecord(pMsg);
5039dede
AK
782 break;
783 case CMD_GET_MIB_TIMESTAMP:
b368969c 784 sendMIBTimestamp(pMsg->getId());
5039dede
AK
785 break;
786 case CMD_GET_MIB:
b08d31f4 787 CALL_IN_NEW_THREAD(sendMib, pMsg);
5039dede
AK
788 break;
789 case CMD_CREATE_OBJECT:
1da08bc6 790 CALL_IN_NEW_THREAD(createObject, pMsg);
5039dede
AK
791 break;
792 case CMD_BIND_OBJECT:
1da08bc6 793 changeObjectBinding(pMsg, TRUE);
5039dede
AK
794 break;
795 case CMD_UNBIND_OBJECT:
1da08bc6
VK
796 changeObjectBinding(pMsg, FALSE);
797 break;
798 case CMD_ADD_CLUSTER_NODE:
799 addClusterNode(pMsg);
5039dede 800 break;
5039dede 801 case CMD_GET_ALL_ALARMS:
3ddc492b 802 CALL_IN_NEW_THREAD(getAlarms, pMsg);
5039dede 803 break;
4644eee7
VK
804 case CMD_GET_ALARM_COMMENTS:
805 getAlarmComments(pMsg);
5039dede 806 break;
b81d7b7d 807 case CMD_SET_ALARM_STATUS_FLOW:
808 updateAlarmStatusFlow(pMsg);
809 break;
4644eee7
VK
810 case CMD_UPDATE_ALARM_COMMENT:
811 updateAlarmComment(pMsg);
1b94acbf 812 break;
4644eee7
VK
813 case CMD_DELETE_ALARM_COMMENT:
814 deleteAlarmComment(pMsg);
f82a8b5d 815 break;
4d00760d
VK
816 case CMD_GET_ALARM:
817 getAlarm(pMsg);
818 break;
b1e9b6b3 819 case CMD_GET_ALARM_EVENTS:
2bac37f9 820 CALL_IN_NEW_THREAD(getAlarmEvents, pMsg);
b1e9b6b3 821 break;
5039dede 822 case CMD_ACK_ALARM:
1add6d73 823 acknowledgeAlarm(pMsg);
5039dede 824 break;
5f6bc78c
VK
825 case CMD_RESOLVE_ALARM:
826 resolveAlarm(pMsg, false);
827 break;
5039dede 828 case CMD_TERMINATE_ALARM:
a881eafa 829 resolveAlarm(pMsg, true);
5039dede
AK
830 break;
831 case CMD_DELETE_ALARM:
1add6d73 832 deleteAlarm(pMsg);
5039dede 833 break;
a881eafa
VK
834 case CMD_BULK_RESOLVE_ALARMS:
835 bulkResolveAlarms(pMsg, false);
836 break;
837 case CMD_BULK_TERMINATE_ALARMS:
838 bulkResolveAlarms(pMsg, true);
839 break;
3c35018e
VK
840 case CMD_OPEN_HELPDESK_ISSUE:
841 CALL_IN_NEW_THREAD(openHelpdeskIssue, pMsg);
842 break;
6cedeb69
VK
843 case CMD_GET_HELPDESK_URL:
844 getHelpdeskUrl(pMsg);
845 break;
1eb0b101
VK
846 case CMD_UNLINK_HELPDESK_ISSUE:
847 unlinkHelpdeskIssue(pMsg);
848 break;
5039dede 849 case CMD_CREATE_ACTION:
1b94acbf 850 createAction(pMsg);
5039dede
AK
851 break;
852 case CMD_MODIFY_ACTION:
1b94acbf 853 updateAction(pMsg);
5039dede
AK
854 break;
855 case CMD_DELETE_ACTION:
1b94acbf 856 deleteAction(pMsg);
5039dede
AK
857 break;
858 case CMD_LOAD_ACTIONS:
b368969c 859 sendAllActions(pMsg->getId());
5039dede 860 break;
5039dede 861 case CMD_DELETE_OBJECT:
f5d16551 862 deleteObject(pMsg);
5039dede
AK
863 break;
864 case CMD_POLL_NODE:
92c51b1d 865 forcedNodePoll(pMsg);
5039dede
AK
866 break;
867 case CMD_TRAP:
b1e9b6b3 868 onTrap(pMsg);
5039dede
AK
869 break;
870 case CMD_WAKEUP_NODE:
b1e9b6b3 871 onWakeUpNode(pMsg);
5039dede 872 break;
5039dede 873 case CMD_CREATE_TRAP:
fdbee7f8 874 editTrap(TRAP_CREATE, pMsg);
5039dede
AK
875 break;
876 case CMD_MODIFY_TRAP:
fdbee7f8 877 editTrap(TRAP_UPDATE, pMsg);
5039dede
AK
878 break;
879 case CMD_DELETE_TRAP:
fdbee7f8 880 editTrap(TRAP_DELETE, pMsg);
5039dede
AK
881 break;
882 case CMD_LOAD_TRAP_CFG:
b368969c 883 sendAllTraps(pMsg->getId());
5039dede
AK
884 break;
885 case CMD_GET_TRAP_CFG_RO:
b368969c 886 sendAllTraps2(pMsg->getId());
5039dede
AK
887 break;
888 case CMD_QUERY_PARAMETER:
46117060 889 CALL_IN_NEW_THREAD(queryParameter, pMsg);
5039dede 890 break;
55bdca5a
VK
891 case CMD_QUERY_TABLE:
892 CALL_IN_NEW_THREAD(queryAgentTable, pMsg);
893 break;
5039dede 894 case CMD_LOCK_PACKAGE_DB:
b368969c 895 LockPackageDB(pMsg->getId(), TRUE);
5039dede
AK
896 break;
897 case CMD_UNLOCK_PACKAGE_DB:
b368969c 898 LockPackageDB(pMsg->getId(), FALSE);
5039dede
AK
899 break;
900 case CMD_GET_PACKAGE_LIST:
b368969c 901 SendAllPackages(pMsg->getId());
5039dede
AK
902 break;
903 case CMD_INSTALL_PACKAGE:
904 InstallPackage(pMsg);
905 break;
906 case CMD_REMOVE_PACKAGE:
907 RemovePackage(pMsg);
908 break;
909 case CMD_GET_PARAMETER_LIST:
074498ac 910 getParametersList(pMsg);
5039dede
AK
911 break;
912 case CMD_DEPLOY_PACKAGE:
913 DeployPackage(pMsg);
914 break;
915 case CMD_GET_LAST_VALUES:
b9a8e081
VK
916 getLastValues(pMsg);
917 break;
2ab9314f 918 case CMD_GET_DCI_VALUES:
919 getLastValuesByDciId(pMsg);
920 break;
b9a8e081
VK
921 case CMD_GET_TABLE_LAST_VALUES:
922 getTableLastValues(pMsg);
5039dede 923 break;
711e5e9a
VK
924 case CMD_GET_THRESHOLD_SUMMARY:
925 getThresholdSummary(pMsg);
926 break;
5039dede 927 case CMD_GET_USER_VARIABLE:
fdbee7f8 928 getUserVariable(pMsg);
5039dede
AK
929 break;
930 case CMD_SET_USER_VARIABLE:
fdbee7f8 931 setUserVariable(pMsg);
5039dede
AK
932 break;
933 case CMD_DELETE_USER_VARIABLE:
fdbee7f8 934 deleteUserVariable(pMsg);
5039dede
AK
935 break;
936 case CMD_ENUM_USER_VARIABLES:
fdbee7f8 937 enumUserVariables(pMsg);
5039dede
AK
938 break;
939 case CMD_COPY_USER_VARIABLE:
fdbee7f8 940 copyUserVariable(pMsg);
5039dede 941 break;
4c789f9e
VK
942 case CMD_CHANGE_ZONE:
943 changeObjectZone(pMsg);
5039dede
AK
944 break;
945 case CMD_REQUEST_ENCRYPTION:
9e9d631e 946 setupEncryption(pMsg);
5039dede
AK
947 break;
948 case CMD_GET_AGENT_CONFIG:
92c51b1d 949 getAgentConfig(pMsg);
5039dede
AK
950 break;
951 case CMD_UPDATE_AGENT_CONFIG:
92c51b1d 952 updateAgentConfig(pMsg);
5039dede
AK
953 break;
954 case CMD_EXECUTE_ACTION:
e31c8e60 955 CALL_IN_NEW_THREAD(executeAction, pMsg);
5039dede
AK
956 break;
957 case CMD_GET_OBJECT_TOOLS:
b576249a 958 getObjectTools(pMsg->getId());
5039dede
AK
959 break;
960 case CMD_EXEC_TABLE_TOOL:
0e950f45 961 execTableTool(pMsg);
5039dede
AK
962 break;
963 case CMD_GET_OBJECT_TOOL_DETAILS:
b576249a 964 getObjectToolDetails(pMsg);
5039dede
AK
965 break;
966 case CMD_UPDATE_OBJECT_TOOL:
0e950f45 967 updateObjectTool(pMsg);
5039dede
AK
968 break;
969 case CMD_DELETE_OBJECT_TOOL:
0e950f45 970 deleteObjectTool(pMsg);
5039dede 971 break;
9dd47420 972 case CMD_CHANGE_OBJECT_TOOL_STATUS:
6f8e39e5 973 changeObjectToolStatus(pMsg);
03f4f212 974 break;
5039dede 975 case CMD_GENERATE_OBJECT_TOOL_ID:
b368969c 976 generateObjectToolId(pMsg->getId());
5039dede
AK
977 break;
978 case CMD_CHANGE_SUBSCRIPTION:
b1e9b6b3 979 changeSubscription(pMsg);
5039dede 980 break;
5039dede 981 case CMD_GET_SERVER_STATS:
b368969c 982 sendServerStats(pMsg->getId());
5039dede
AK
983 break;
984 case CMD_GET_SCRIPT_LIST:
b368969c 985 sendScriptList(pMsg->getId());
5039dede
AK
986 break;
987 case CMD_GET_SCRIPT:
0c7aca90 988 sendScript(pMsg);
5039dede
AK
989 break;
990 case CMD_UPDATE_SCRIPT:
0c7aca90 991 updateScript(pMsg);
5039dede
AK
992 break;
993 case CMD_RENAME_SCRIPT:
0c7aca90 994 renameScript(pMsg);
5039dede
AK
995 break;
996 case CMD_DELETE_SCRIPT:
0c7aca90 997 deleteScript(pMsg);
5039dede
AK
998 break;
999 case CMD_GET_SESSION_LIST:
b368969c 1000 SendSessionList(pMsg->getId());
5039dede
AK
1001 break;
1002 case CMD_KILL_SESSION:
1003 KillSession(pMsg);
1004 break;
5039dede
AK
1005 case CMD_START_SNMP_WALK:
1006 StartSnmpWalk(pMsg);
1007 break;
5039dede 1008 case CMD_RESOLVE_DCI_NAMES:
241c2740 1009 resolveDCINames(pMsg);
5039dede
AK
1010 break;
1011 case CMD_GET_DCI_INFO:
1012 SendDCIInfo(pMsg);
1013 break;
071fd171
VK
1014 case CMD_GET_DCI_THRESHOLDS:
1015 sendDCIThresholds(pMsg);
1016 break;
5039dede 1017 case CMD_GET_DCI_EVENTS_LIST:
25a1e9d0
VK
1018 getDCIEventList(pMsg);
1019 break;
1020 case CMD_GET_DCI_SCRIPT_LIST:
1021 getDCIScriptList(pMsg);
5039dede 1022 break;
74526d25
VK
1023 case CMD_GET_PERFTAB_DCI_LIST:
1024 sendPerfTabDCIList(pMsg);
5039dede
AK
1025 break;
1026 case CMD_PUSH_DCI_DATA:
6fd6de0a 1027 pushDCIData(pMsg);
5039dede
AK
1028 break;
1029 case CMD_GET_AGENT_CFG_LIST:
b368969c 1030 sendAgentCfgList(pMsg->getId());
5039dede
AK
1031 break;
1032 case CMD_OPEN_AGENT_CONFIG:
1033 OpenAgentConfig(pMsg);
1034 break;
1035 case CMD_SAVE_AGENT_CONFIG:
1036 SaveAgentConfig(pMsg);
1037 break;
1038 case CMD_DELETE_AGENT_CONFIG:
1039 DeleteAgentConfig(pMsg);
1040 break;
1041 case CMD_SWAP_AGENT_CONFIGS:
1042 SwapAgentConfigs(pMsg);
1043 break;
1044 case CMD_GET_OBJECT_COMMENTS:
1045 SendObjectComments(pMsg);
1046 break;
1047 case CMD_UPDATE_OBJECT_COMMENTS:
6fd6de0a 1048 updateObjectComments(pMsg);
5039dede
AK
1049 break;
1050 case CMD_GET_ADDR_LIST:
6fd6de0a 1051 getAddrList(pMsg);
5039dede
AK
1052 break;
1053 case CMD_SET_ADDR_LIST:
6fd6de0a 1054 setAddrList(pMsg);
5039dede
AK
1055 break;
1056 case CMD_RESET_COMPONENT:
92c51b1d 1057 resetComponent(pMsg);
5039dede 1058 break;
a7ff20a5
VK
1059 case CMD_EXPORT_CONFIGURATION:
1060 exportConfiguration(pMsg);
5039dede 1061 break;
a7ff20a5 1062 case CMD_IMPORT_CONFIGURATION:
78ccd7b4 1063 CALL_IN_NEW_THREAD(importConfiguration, pMsg);
5039dede
AK
1064 break;
1065 case CMD_GET_GRAPH_LIST:
aed41472 1066 sendGraphList(pMsg);
5039dede 1067 break;
7a4c94ee 1068 case CMD_SAVE_GRAPH:
6f8e39e5 1069 saveGraph(pMsg);
7a4c94ee 1070 break;
5039dede 1071 case CMD_DELETE_GRAPH:
6f8e39e5 1072 deleteGraph(pMsg);
5039dede
AK
1073 break;
1074 case CMD_ADD_CA_CERTIFICATE:
493beadc 1075 addCACertificate(pMsg);
5039dede
AK
1076 break;
1077 case CMD_DELETE_CERTIFICATE:
493beadc 1078 deleteCertificate(pMsg);
5039dede
AK
1079 break;
1080 case CMD_UPDATE_CERT_COMMENTS:
493beadc 1081 updateCertificateComments(pMsg);
5039dede
AK
1082 break;
1083 case CMD_GET_CERT_LIST:
b368969c 1084 getCertificateList(pMsg->getId());
5039dede
AK
1085 break;
1086 case CMD_QUERY_L2_TOPOLOGY:
84880c89 1087 CALL_IN_NEW_THREAD(queryL2Topology, pMsg);
5039dede
AK
1088 break;
1089 case CMD_SEND_SMS:
b1e9b6b3 1090 sendSMS(pMsg);
5039dede
AK
1091 break;
1092 case CMD_GET_COMMUNITY_LIST:
b368969c 1093 SendCommunityList(pMsg->getId());
5039dede
AK
1094 break;
1095 case CMD_UPDATE_COMMUNITY_LIST:
1096 UpdateCommunityList(pMsg);
1097 break;
df8a4ca2 1098 case CMD_GET_USM_CREDENTIALS:
b368969c 1099 sendUsmCredentials(pMsg->getId());
df8a4ca2
VK
1100 break;
1101 case CMD_UPDATE_USM_CREDENTIALS:
1102 updateUsmCredentials(pMsg);
1103 break;
00420032 1104 case CMD_GET_PERSISTENT_STORAGE:
1105 getPersistantStorage(pMsg->getId());
5039dede 1106 break;
00420032 1107 case CMD_SET_PSTORAGE_VALUE:
1108 setPstorageValue(pMsg);
5039dede 1109 break;
00420032 1110 case CMD_DELETE_PSTORAGE_VALUE:
1111 deletePstorageValue(pMsg);
5039dede 1112 break;
5039dede 1113 case CMD_REGISTER_AGENT:
1da08bc6 1114 registerAgent(pMsg);
5039dede
AK
1115 break;
1116 case CMD_GET_SERVER_FILE:
1da08bc6 1117 CALL_IN_NEW_THREAD(getServerFile, pMsg);
5039dede 1118 break;
6f16f12d
VK
1119 case CMD_GET_AGENT_FILE:
1120 CALL_IN_NEW_THREAD(getAgentFile, pMsg);
1121 break;
9fa031cd 1122 case CMD_CANCEL_FILE_MONITORING:
1123 CALL_IN_NEW_THREAD(cancelFileMonitoring, pMsg);
1124 break;
4d0c32f3 1125 case CMD_TEST_DCI_TRANSFORMATION:
1da08bc6 1126 testDCITransformation(pMsg);
4d0c32f3 1127 break;
529956a0 1128 case CMD_EXECUTE_SCRIPT:
1129 CALL_IN_NEW_THREAD(executeScript, pMsg);
1130 break;
e9bf9011
VK
1131 case CMD_EXECUTE_LIBRARY_SCRIPT:
1132 CALL_IN_NEW_THREAD(executeLibraryScript, pMsg);
1133 break;
ab621f39 1134 case CMD_GET_JOB_LIST:
b368969c 1135 sendJobList(pMsg->getId());
ab621f39 1136 break;
f40831eb 1137 case CMD_CANCEL_JOB:
45d84f8a
VK
1138 cancelJob(pMsg);
1139 break;
8d9f7450
VK
1140 case CMD_HOLD_JOB:
1141 holdJob(pMsg);
1142 break;
1143 case CMD_UNHOLD_JOB:
1144 unholdJob(pMsg);
1145 break;
45d84f8a 1146 case CMD_DEPLOY_AGENT_POLICY:
93599cfd
VK
1147 deployAgentPolicy(pMsg, false);
1148 break;
1149 case CMD_UNINSTALL_AGENT_POLICY:
1150 deployAgentPolicy(pMsg, true);
f40831eb 1151 break;
d83dc1f0
VK
1152 case CMD_GET_CURRENT_USER_ATTR:
1153 getUserCustomAttribute(pMsg);
1154 break;
1155 case CMD_SET_CURRENT_USER_ATTR:
1156 setUserCustomAttribute(pMsg);
1157 break;
e05b1945
VK
1158 case CMD_OPEN_SERVER_LOG:
1159 openServerLog(pMsg);
1160 break;
1161 case CMD_CLOSE_SERVER_LOG:
1162 closeServerLog(pMsg);
1163 break;
1164 case CMD_QUERY_LOG:
1165 CALL_IN_NEW_THREAD(queryServerLog, pMsg);
1166 break;
1167 case CMD_GET_LOG_DATA:
1168 CALL_IN_NEW_THREAD(getServerLogQueryData, pMsg);
1169 break;
630e15d6
VK
1170 case CMD_FIND_NODE_CONNECTION:
1171 CALL_IN_NEW_THREAD(findNodeConnection, pMsg);
1172 break;
06a93345
VK
1173 case CMD_FIND_MAC_LOCATION:
1174 CALL_IN_NEW_THREAD(findMacAddress, pMsg);
1175 break;
80e0db05
VK
1176 case CMD_FIND_IP_LOCATION:
1177 CALL_IN_NEW_THREAD(findIpAddress, pMsg);
1178 break;
f1984eb9
EJ
1179 case CMD_FIND_HOSTNAME_LOCATION:
1180 CALL_IN_NEW_THREAD(findHostname, pMsg);
1181 break;
e6b9439a
AK
1182 case CMD_GET_IMAGE:
1183 sendLibraryImage(pMsg);
1184 break;
1185 case CMD_CREATE_IMAGE:
1186 updateLibraryImage(pMsg);
1187 break;
1188 case CMD_DELETE_IMAGE:
1189 deleteLibraryImage(pMsg);
1190 break;
1191 case CMD_MODIFY_IMAGE:
1192 updateLibraryImage(pMsg);
1193 break;
1194 case CMD_LIST_IMAGES:
1195 listLibraryImages(pMsg);
1196 break;
f69c6203
VK
1197 case CMD_EXECUTE_SERVER_COMMAND:
1198 executeServerCommand(pMsg);
1199 break;
e5b8d60e 1200 case CMD_STOP_SERVER_COMMAND:
45ac5dd0
EJ
1201 stopServerCommand(pMsg);
1202 break;
1a5e0c22
VK
1203 case CMD_LIST_SERVER_FILES:
1204 listServerFileStore(pMsg);
1205 break;
619e5c9b
VK
1206 case CMD_UPLOAD_FILE_TO_AGENT:
1207 uploadFileToAgent(pMsg);
1208 break;
68f898c9
VK
1209 case CMD_UPLOAD_FILE:
1210 receiveFile(pMsg);
1211 break;
1212 case CMD_DELETE_FILE:
1213 deleteFile(pMsg);
1214 break;
200d662d 1215 case CMD_OPEN_CONSOLE:
b368969c 1216 openConsole(pMsg->getId());
200d662d
VK
1217 break;
1218 case CMD_CLOSE_CONSOLE:
b368969c 1219 closeConsole(pMsg->getId());
200d662d
VK
1220 break;
1221 case CMD_ADM_REQUEST:
1222 CALL_IN_NEW_THREAD(processConsoleCommand, pMsg);
1223 break;
7f632dfe
VK
1224 case CMD_GET_VLANS:
1225 getVlans(pMsg);
1226 break;
6d069676
VK
1227 case CMD_GET_NETWORK_PATH:
1228 CALL_IN_NEW_THREAD(getNetworkPath, pMsg);
1229 break;
8836184f
VK
1230 case CMD_GET_NODE_COMPONENTS:
1231 getNodeComponents(pMsg);
1232 break;
caa04e26
VK
1233 case CMD_GET_NODE_SOFTWARE:
1234 getNodeSoftware(pMsg);
1235 break;
46ee6286
VK
1236 case CMD_GET_WINPERF_OBJECTS:
1237 getWinPerfObjects(pMsg);
1238 break;
fdbee7f8
VK
1239 case CMD_LIST_MAPPING_TABLES:
1240 listMappingTables(pMsg);
1241 break;
1242 case CMD_GET_MAPPING_TABLE:
1243 getMappingTable(pMsg);
1244 break;
1245 case CMD_UPDATE_MAPPING_TABLE:
1246 updateMappingTable(pMsg);
1247 break;
1248 case CMD_DELETE_MAPPING_TABLE:
1249 deleteMappingTable(pMsg);
1250 break;
d5de1d1d
VK
1251 case CMD_GET_WIRELESS_STATIONS:
1252 getWirelessStations(pMsg);
1253 break;
b4c2a628 1254 case CMD_GET_SUMMARY_TABLES:
b368969c 1255 getSummaryTables(pMsg->getId());
b4c2a628
VK
1256 break;
1257 case CMD_GET_SUMMARY_TABLE_DETAILS:
1258 getSummaryTableDetails(pMsg);
1259 break;
1260 case CMD_MODIFY_SUMMARY_TABLE:
1261 modifySummaryTable(pMsg);
1262 break;
1263 case CMD_DELETE_SUMMARY_TABLE:
1264 deleteSummaryTable(pMsg);
1265 break;
1266 case CMD_QUERY_SUMMARY_TABLE:
1267 querySummaryTable(pMsg);
1268 break;
5389f7b0
VK
1269 case CMD_QUERY_ADHOC_SUMMARY_TABLE:
1270 queryAdHocSummaryTable(pMsg);
1271 break;
ceb0fc8d
VK
1272 case CMD_GET_SUBNET_ADDRESS_MAP:
1273 getSubnetAddressMap(pMsg);
1274 break;
d39de9a8
VK
1275 case CMD_GET_EFFECTIVE_RIGHTS:
1276 getEffectiveRights(pMsg);
1277 break;
f3e2e618 1278 case CMD_GET_FOLDER_SIZE:
d9821bd7 1279 case CMD_GET_FOLDER_CONTENT:
7cf549ad 1280 case CMD_FILEMGR_DELETE_FILE:
1281 case CMD_FILEMGR_RENAME_FILE:
1282 case CMD_FILEMGR_MOVE_FILE:
5de546a2 1283 case CMD_FILEMGR_CREATE_FOLDER:
74d0b136 1284 CALL_IN_NEW_THREAD(fileManagerControl, pMsg);
7cf549ad 1285 break;
1286 case CMD_FILEMGR_UPLOAD:
1287 CALL_IN_NEW_THREAD(uploadUserFileToAgent, pMsg);
d9821bd7 1288 break;
c44cf458
VK
1289 case CMD_GET_SWITCH_FDB:
1290 CALL_IN_NEW_THREAD(getSwitchForwardingDatabase, pMsg);
1291 break;
1292 case CMD_GET_ROUTING_TABLE:
1293 CALL_IN_NEW_THREAD(getRoutingTable, pMsg);
1294 break;
4899db4d 1295 case CMD_GET_LOC_HISTORY:
1296 CALL_IN_NEW_THREAD(getLocationHistory, pMsg);
1297 break;
d9e5a5be 1298 case CMD_TAKE_SCREENSHOT:
1299 getScreenshot(pMsg);
1300 break;
5f573844
VK
1301 case CMD_COMPILE_SCRIPT:
1302 compileScript(pMsg);
1303 break;
4b535d78 1304 case CMD_CLEAN_AGENT_DCI_CONF:
1305 cleanAgentDciConfiguration(pMsg);
1306 break;
1307 case CMD_RESYNC_AGENT_DCI_CONF:
1308 resyncAgentDciConfiguration(pMsg);
1309 break;
a44a910c 1310 case CMD_LIST_SCHEDULE_CALLBACKS:
ec13a467 1311 getSchedulerTaskHandlers(pMsg);
a44a910c 1312 break;
1313 case CMD_LIST_SCHEDULES:
ec13a467 1314 getScheduledTasks(pMsg);
a44a910c 1315 break;
1316 case CMD_ADD_SCHEDULE:
ec13a467 1317 addScheduledTask(pMsg);
a44a910c 1318 break;
1319 case CMD_UPDATE_SCHEDULE:
ec13a467 1320 updateScheduledTask(pMsg);
a44a910c 1321 break;
1322 case CMD_REMOVE_SCHEDULE:
ec13a467 1323 removeScheduledTask(pMsg);
d6aca8c9 1324 break;
badd6e08
VK
1325 case CMD_GET_REPOSITORIES:
1326 CALL_IN_NEW_THREAD(getRepositories, pMsg);
1327 break;
1328 case CMD_ADD_REPOSITORY:
1329 CALL_IN_NEW_THREAD(addRepository, pMsg);
1330 break;
1331 case CMD_MODIFY_REPOSITORY:
1332 CALL_IN_NEW_THREAD(modifyRepository, pMsg);
1333 break;
1334 case CMD_DELETE_REPOSITORY:
1335 CALL_IN_NEW_THREAD(deleteRepository, pMsg);
1336 break;
3c463101
VK
1337 case CMD_GET_AGENT_TUNNELS:
1338 getAgentTunnels(pMsg);
3b89a4c1
VK
1339 break;
1340 case CMD_BIND_AGENT_TUNNEL:
1341 bindAgentTunnel(pMsg);
1342 break;
c733fcc4
VK
1343 case CMD_UNBIND_AGENT_TUNNEL:
1344 unbindAgentTunnel(pMsg);
1345 break;
0cf6fcbd
VK
1346 case CMD_GET_PREDICTION_ENGINES:
1347 getPredictionEngines(pMsg);
1348 break;
1349 case CMD_GET_PREDICTED_DATA:
1350 CALL_IN_NEW_THREAD(getPredictedData, pMsg);
1351 break;
4ef60905
AK
1352#ifdef WITH_ZMQ
1353 case CMD_ZMQ_SUBSCRIBE_EVENT:
1354 zmqManageSubscription(pMsg, zmq::EVENT, true);
1355 break;
1356 case CMD_ZMQ_UNSUBSCRIBE_EVENT:
1357 zmqManageSubscription(pMsg, zmq::EVENT, false);
1358 break;
1359 case CMD_ZMQ_SUBSCRIBE_DATA:
1360 zmqManageSubscription(pMsg, zmq::DATA, true);
1361 break;
1362 case CMD_ZMQ_UNSUBSCRIBE_DATA:
1363 zmqManageSubscription(pMsg, zmq::DATA, false);
1364 break;
529c5844 1365 case CMD_ZMQ_GET_EVT_SUBSCRIPTIONS:
4ef60905
AK
1366 zmqListSubscriptions(pMsg, zmq::EVENT);
1367 break;
529c5844 1368 case CMD_ZMQ_GET_DATA_SUBSCRIPTIONS:
4ef60905
AK
1369 zmqListSubscriptions(pMsg, zmq::DATA);
1370 break;
1371#endif
5039dede 1372 default:
d75003e1
AK
1373 if ((m_wCurrentCmd >> 8) == 0x11)
1374 {
1375 // Reporting Server range (0x1100 - 0x11FF)
1376 CALL_IN_NEW_THREAD(forwardToReportingServer, pMsg);
1377 break;
1378 }
1379
5039dede
AK
1380 // Pass message to loaded modules
1381 for(i = 0; i < g_dwNumModules; i++)
1382 {
534e1b83 1383 if (g_pModuleList[i].pfClientCommandHandler != NULL)
5039dede 1384 {
534e1b83 1385 status = g_pModuleList[i].pfClientCommandHandler(m_wCurrentCmd, pMsg, this);
5039dede
AK
1386 if (status != NXMOD_COMMAND_IGNORED)
1387 {
1388 if (status == NXMOD_COMMAND_ACCEPTED_ASYNC)
1389 {
1390 pMsg = NULL; // Prevent deletion
5039dede
AK
1391 }
1392 break; // Message was processed by the module
1393 }
1394 }
1395 }
1396 if (i == g_dwNumModules)
1397 {
b368969c 1398 NXCPMessage response;
5039dede 1399
b368969c
VK
1400 response.setId(pMsg->getId());
1401 response.setCode(CMD_REQUEST_COMPLETED);
1402 response.setField(VID_RCC, RCC_NOT_IMPLEMENTED);
e05b1945 1403 sendMessage(&response);
5039dede
AK
1404 }
1405 break;
1406 }
1407 delete pMsg;
2a964810 1408 m_state = (m_dwFlags & CSF_AUTHENTICATED) ? SESSION_STATE_IDLE : SESSION_STATE_INIT;
5039dede
AK
1409 }
1410}
1411
534e1b83
VK
1412/**
1413 * Respond to client's keepalive message
1414 */
967893bb 1415void ClientSession::respondToKeepalive(UINT32 dwRqId)
5039dede 1416{
b368969c 1417 NXCPMessage msg;
5039dede 1418
b368969c
VK
1419 msg.setCode(CMD_REQUEST_COMPLETED);
1420 msg.setId(dwRqId);
1421 msg.setField(VID_RCC, RCC_SUCCESS);
e05b1945 1422 sendMessage(&msg);
5039dede
AK
1423}
1424
534e1b83 1425/**
6fd6de0a
VK
1426 * Send message to client
1427 */
a07511b5 1428bool ClientSession::sendMessage(NXCPMessage *msg)
d3a7cf4c 1429{
134c3d00 1430 if (isTerminated())
a07511b5 1431 return false;
134c3d00 1432
198745dd 1433 NXCP_MESSAGE *rawMsg = msg->serialize((m_dwFlags & CSF_COMPRESSION_ENABLED) != 0);
8ec102ac 1434
4970ef34 1435 if ((nxlog_get_debug_level() >= 6) && (msg->getCode() != CMD_ADM_MESSAGE))
934f53da 1436 {
4970ef34
VK
1437 TCHAR buffer[128];
1438 debugPrintf(6, _T("Sending%s message %s (%d bytes)"),
1439 (ntohs(rawMsg->flags) & MF_COMPRESSED) ? _T(" compressed") : _T(""), NXCPMessageCodeName(msg->getCode(), buffer), ntohl(rawMsg->size));
1440 if (nxlog_get_debug_level() >= 8)
1441 {
1442 String msgDump = NXCPMessage::dump(rawMsg, NXCP_VERSION);
1443 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR *)msgDump);
1444 }
934f53da 1445 }
6be0a20b
VK
1446
1447 bool result;
d3a7cf4c
VK
1448 if (m_pCtx != NULL)
1449 {
b368969c 1450 NXCP_ENCRYPTED_MESSAGE *enMsg = m_pCtx->encryptMessage(rawMsg);
6be0a20b 1451 if (enMsg != NULL)
d3a7cf4c 1452 {
b368969c 1453 result = (SendEx(m_hSocket, (char *)enMsg, ntohl(enMsg->size), 0, m_mutexSocketWrite) == (int)ntohl(enMsg->size));
6be0a20b 1454 free(enMsg);
d3a7cf4c
VK
1455 }
1456 else
1457 {
6be0a20b 1458 result = false;
d3a7cf4c
VK
1459 }
1460 }
1461 else
1462 {
b368969c 1463 result = (SendEx(m_hSocket, (const char *)rawMsg, ntohl(rawMsg->size), 0, m_mutexSocketWrite) == (int)ntohl(rawMsg->size));
d3a7cf4c 1464 }
6be0a20b 1465 free(rawMsg);
d3a7cf4c 1466
6be0a20b 1467 if (!result)
d3a7cf4c
VK
1468 {
1469 closesocket(m_hSocket);
1470 m_hSocket = -1;
1471 }
a07511b5 1472 return result;
d3a7cf4c
VK
1473}
1474
534e1b83
VK
1475/**
1476 * Send raw message to client
1477 */
b368969c 1478void ClientSession::sendRawMessage(NXCP_MESSAGE *msg)
92c51b1d 1479{
134c3d00
VK
1480 if (isTerminated())
1481 return;
1482
1483 UINT16 code = htons(msg->code);
4970ef34 1484 if ((code != CMD_ADM_MESSAGE) && (nxlog_get_debug_level() >= 6))
134c3d00
VK
1485 {
1486 TCHAR buffer[128];
4970ef34
VK
1487 debugPrintf(6, _T("Sending%s message %s (%d bytes)"),
1488 (ntohs(msg->flags) & MF_COMPRESSED) ? _T(" compressed") : _T(""), NXCPMessageCodeName(ntohs(msg->code), buffer), ntohl(msg->size));
1489 if (nxlog_get_debug_level() >= 8)
1490 {
1491 String msgDump = NXCPMessage::dump(msg, NXCP_VERSION);
1492 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR *)msgDump);
1493 }
134c3d00 1494 }
92c51b1d 1495
6be0a20b 1496 bool result;
92c51b1d
VK
1497 if (m_pCtx != NULL)
1498 {
b368969c 1499 NXCP_ENCRYPTED_MESSAGE *enMsg = m_pCtx->encryptMessage(msg);
6be0a20b 1500 if (enMsg != NULL)
92c51b1d 1501 {
b368969c 1502 result = (SendEx(m_hSocket, (char *)enMsg, ntohl(enMsg->size), 0, m_mutexSocketWrite) == (int)ntohl(enMsg->size));
6be0a20b 1503 free(enMsg);
92c51b1d
VK
1504 }
1505 else
1506 {
6be0a20b 1507 result = false;
92c51b1d
VK
1508 }
1509 }
1510 else
1511 {
b368969c 1512 result = (SendEx(m_hSocket, (const char *)msg, ntohl(msg->size), 0, m_mutexSocketWrite) == (int)ntohl(msg->size));
92c51b1d
VK
1513 }
1514
6be0a20b 1515 if (!result)
92c51b1d
VK
1516 {
1517 closesocket(m_hSocket);
1518 m_hSocket = -1;
1519 }
1520}
1521
534e1b83
VK
1522/**
1523 * Send file to client
1524 */
cc022855 1525BOOL ClientSession::sendFile(const TCHAR *file, UINT32 dwRqId, long ofset)
a0e3917e 1526{
09008413
VK
1527 return !isTerminated() ? SendFileOverNXCP(m_hSocket, dwRqId, file, m_pCtx,
1528 ofset, NULL, NULL, m_mutexSocketWrite, isCompressionEnabled() ? NXCP_STREAM_COMPRESSION_DEFLATE : NXCP_STREAM_COMPRESSION_NONE) : FALSE;
a0e3917e
VK
1529}
1530
534e1b83
VK
1531/**
1532 * Send server information to client
1533 */
967893bb 1534void ClientSession::sendServerInfo(UINT32 dwRqId)
5039dede 1535{
e5390fb5
VK
1536 static UINT32 protocolVersions[] = {
1537 CLIENT_PROTOCOL_VERSION_BASE,
1538 CLIENT_PROTOCOL_VERSION_ALARMS,
1539 CLIENT_PROTOCOL_VERSION_PUSH,
1540 CLIENT_PROTOCOL_VERSION_TRAP,
1541 CLIENT_PROTOCOL_VERSION_MOBILE,
1542 CLIENT_PROTOCOL_VERSION_FULL
1543 };
b368969c 1544 NXCPMessage msg;
2589cc10 1545 TCHAR szBuffer[MAX_CONFIG_VALUE];
5039dede
AK
1546 String strURL;
1547
1548 // Prepare response message
b368969c
VK
1549 msg.setCode(CMD_REQUEST_COMPLETED);
1550 msg.setId(dwRqId);
5039dede
AK
1551
1552 // Generate challenge for certificate authentication
1553#ifdef _WITH_ENCRYPTION
1554 RAND_bytes(m_challenge, CLIENT_CHALLENGE_SIZE);
1555#else
1556 memset(m_challenge, 0, CLIENT_CHALLENGE_SIZE);
1557#endif
1558
1559 // Fill message with server info
b368969c
VK
1560 msg.setField(VID_RCC, RCC_SUCCESS);
1561 msg.setField(VID_SERVER_VERSION, NETXMS_VERSION_STRING);
e9902466 1562 msg.setField(VID_SERVER_ID, g_serverId);
b368969c 1563 msg.setField(VID_SUPPORTED_ENCRYPTION, (UINT32)0);
e5390fb5
VK
1564 msg.setField(VID_PROTOCOL_VERSION, (UINT32)CLIENT_PROTOCOL_VERSION_BASE);
1565 msg.setFieldFromInt32Array(VID_PROTOCOL_VERSION_EX, sizeof(protocolVersions) / sizeof(UINT32), protocolVersions);
b368969c
VK
1566 msg.setField(VID_CHALLENGE, m_challenge, CLIENT_CHALLENGE_SIZE);
1567 msg.setField(VID_TIMESTAMP, (UINT32)time(NULL));
5039dede
AK
1568
1569#if defined(_WIN32)
1570 TIME_ZONE_INFORMATION tz;
1571 WCHAR wst[4], wdt[8], *curr;
1572 int i;
1573
44dac3da 1574 DWORD tzType = GetTimeZoneInformation(&tz);
5039dede
AK
1575
1576 // Create 3 letter abbreviation for standard name
1577 for(i = 0, curr = tz.StandardName; (*curr != 0) && (i < 3); curr++)
1578 if (iswupper(*curr))
1579 wst[i++] = *curr;
1580 while(i < 3)
1581 wst[i++] = L'X';
1582 wst[i] = 0;
1583
1584 // Create abbreviation for DST name
1585 for(i = 0, curr = tz.DaylightName; (*curr != 0) && (i < 7); curr++)
1586 if (iswupper(*curr))
1587 wdt[i++] = *curr;
1588 while(i < 3)
1589 wdt[i++] = L'X';
1590 wdt[i] = 0;
1591
44dac3da
VK
1592 LONG effectiveBias;
1593 switch(tzType)
1594 {
1595 case TIME_ZONE_ID_STANDARD:
1596 effectiveBias = tz.Bias + tz.StandardBias;
1597 break;
1598 case TIME_ZONE_ID_DAYLIGHT:
1599 effectiveBias = tz.Bias + tz.DaylightBias;
1600 break;
1601 case TIME_ZONE_ID_UNKNOWN:
1602 effectiveBias = tz.Bias;
1603 break;
1604 default: // error
1605 effectiveBias = 0;
1606 debugPrintf(4, _T("GetTimeZoneInformation() call failed"));
1607 break;
1608 }
1609
5039dede 1610#ifdef UNICODE
44dac3da
VK
1611 swprintf(szBuffer, 1024, L"%s%c%02d%s", wst, (effectiveBias > 0) ? '-' : '+',
1612 abs(effectiveBias) / 60, (tz.DaylightBias != 0) ? wdt : L"");
5039dede 1613#else
44dac3da
VK
1614 sprintf(szBuffer, "%S%c%02d%S", wst, (effectiveBias > 0) ? '-' : '+',
1615 abs(effectiveBias) / 60, (tz.DaylightBias != 0) ? wdt : L"");
5039dede 1616#endif
d2b34835
VK
1617
1618#elif HAVE_TM_GMTOFF /* not Windows but have tm_gmtoff */
1619
1620 time_t t = time(NULL);
5039dede
AK
1621 int gmtOffset;
1622#if HAVE_LOCALTIME_R
1623 struct tm tmbuff;
d2b34835 1624 struct tm *loc = localtime_r(&t, &tmbuff);
5039dede 1625#else
d2b34835 1626 struct tm *loc = localtime(&t);
5039dede 1627#endif
2aa5fe1d 1628 gmtOffset = loc->tm_gmtoff / 3600;
dda7c270
VK
1629#ifdef UNICODE
1630 swprintf(szBuffer, 1024, L"%hs%hc%02d%hs", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1631 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
1632#else
5039dede
AK
1633 sprintf(szBuffer, "%s%c%02d%s", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1634 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
dda7c270 1635#endif
d2b34835
VK
1636
1637#else /* not Windows and no tm_gmtoff */
1638
1639 time_t t = time(NULL);
1640#if HAVE_GMTIME_R
b7e064e7
VK
1641 struct tm tmbuff;
1642 struct tm *gmt = gmtime_r(&t, &tmbuff);
d2b34835 1643#else
b7e064e7 1644 struct tm *gmt = gmtime(&t);
d2b34835
VK
1645#endif
1646 gmt->tm_isdst = -1;
1647 int gmtOffset = (int)((t - mktime(gmt)) / 3600);
1648#ifdef UNICODE
1649 swprintf(szBuffer, 1024, L"%hs%hc%02d%hs", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1650 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
5039dede 1651#else
d2b34835
VK
1652 sprintf(szBuffer, "%s%c%02d%s", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1653 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
1654#endif
1655
5039dede 1656#endif
d2b34835 1657
b368969c 1658 msg.setField(VID_TIMEZONE, szBuffer);
534e1b83 1659 debugPrintf(2, _T("Server time zone: %s"), szBuffer);
5039dede 1660
2589cc10 1661 ConfigReadStr(_T("TileServerURL"), szBuffer, MAX_CONFIG_VALUE, _T("http://tile.openstreetmap.org/"));
b368969c 1662 msg.setField(VID_TILE_SERVER_URL, szBuffer);
fceea457 1663
2589cc10 1664 ConfigReadStr(_T("DefaultConsoleDateFormat"), szBuffer, MAX_CONFIG_VALUE, _T("dd.MM.yyyy"));
b368969c 1665 msg.setField(VID_DATE_FORMAT, szBuffer);
aabe5b72 1666
2589cc10 1667 ConfigReadStr(_T("DefaultConsoleTimeFormat"), szBuffer, MAX_CONFIG_VALUE, _T("HH:mm:ss"));
b368969c 1668 msg.setField(VID_TIME_FORMAT, szBuffer);
aabe5b72 1669
2589cc10 1670 ConfigReadStr(_T("DefaultConsoleShortTimeFormat"), szBuffer, MAX_CONFIG_VALUE, _T("HH:mm"));
b368969c 1671 msg.setField(VID_SHORT_TIME_FORMAT, szBuffer);
bc969eaf 1672
4fd0b7ca
VK
1673 FillComponentsMessage(&msg);
1674
5039dede 1675 // Send response
e05b1945 1676 sendMessage(&msg);
5039dede
AK
1677}
1678
534e1b83
VK
1679/**
1680 * Authenticate client
1681 */
b368969c 1682void ClientSession::login(NXCPMessage *pRequest)
5039dede 1683{
b368969c 1684 NXCPMessage msg;
60557d06 1685 TCHAR szLogin[MAX_USER_NAME], szPassword[1024];
5039dede 1686 int nAuthType;
ab185583 1687 bool changePasswd = false, intruderLockout = false;
967893bb 1688 UINT32 dwResult;
5039dede
AK
1689#ifdef _WITH_ENCRYPTION
1690 X509 *pCert;
1691#endif
1692
1693 // Prepare response message
b368969c
VK
1694 msg.setCode(CMD_LOGIN_RESP);
1695 msg.setId(pRequest->getId());
5039dede
AK
1696
1697 // Get client info string
5c44534b 1698 if (pRequest->isFieldExist(VID_CLIENT_INFO))
5039dede
AK
1699 {
1700 TCHAR szClientInfo[32], szOSInfo[32], szLibVersion[16];
7a4c94ee 1701
b368969c
VK
1702 pRequest->getFieldAsString(VID_CLIENT_INFO, szClientInfo, 32);
1703 pRequest->getFieldAsString(VID_OS_INFO, szOSInfo, 32);
1704 pRequest->getFieldAsString(VID_LIBNXCL_VERSION, szLibVersion, 16);
77a08c86 1705 _sntprintf(m_clientInfo, 96, _T("%s (%s; libnxcl %s)"), szClientInfo, szOSInfo, szLibVersion);
5039dede
AK
1706 }
1707
b368969c 1708 m_clientType = pRequest->getFieldAsUInt16(VID_CLIENT_TYPE);
f8c6f10f
VK
1709 if ((m_clientType < 0) || (m_clientType > CLIENT_TYPE_APPLICATION))
1710 m_clientType = CLIENT_TYPE_DESKTOP;
1711
91f6b72c
VK
1712 if (m_clientType == CLIENT_TYPE_WEB)
1713 {
1714 _tcscpy(m_webServerAddress, m_workstation);
5c44534b 1715 if (pRequest->isFieldExist(VID_CLIENT_ADDRESS))
91f6b72c 1716 {
b368969c 1717 pRequest->getFieldAsString(VID_CLIENT_ADDRESS, m_workstation, 256);
91f6b72c
VK
1718 debugPrintf(5, _T("Real web client address is %s"), m_workstation);
1719 }
1720 }
1721
2a964810
VK
1722 if (pRequest->isFieldExist(VID_LANGUAGE))
1723 {
b368969c 1724 pRequest->getFieldAsString(VID_LANGUAGE, m_language, 8);
2a964810
VK
1725 }
1726
5039dede
AK
1727 if (!(m_dwFlags & CSF_AUTHENTICATED))
1728 {
d888bc1c 1729 UINT32 graceLogins = 0;
27858eaa 1730 bool closeOtherSessions = false;
b368969c
VK
1731 pRequest->getFieldAsString(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
1732 nAuthType = (int)pRequest->getFieldAsUInt16(VID_AUTH_TYPE);
958a9397 1733 debugPrintf(6, _T("authentication type %d"), nAuthType);
5039dede
AK
1734 switch(nAuthType)
1735 {
1736 case NETXMS_AUTH_TYPE_PASSWORD:
5ad55ecb 1737#ifdef UNICODE
b368969c 1738 pRequest->getFieldAsString(VID_PASSWORD, szPassword, 256);
5ad55ecb 1739#else
036d27a7 1740 pRequest->getFieldAsUtf8String(VID_PASSWORD, szPassword, 1024);
5ad55ecb 1741#endif
5039dede 1742 dwResult = AuthenticateUser(szLogin, szPassword, 0, NULL, NULL, &m_dwUserId,
27858eaa 1743 &m_dwSystemAccess, &changePasswd, &intruderLockout,
d888bc1c 1744 &closeOtherSessions, false, &graceLogins);
5039dede
AK
1745 break;
1746 case NETXMS_AUTH_TYPE_CERTIFICATE:
1747#ifdef _WITH_ENCRYPTION
1748 pCert = CertificateFromLoginMessage(pRequest);
1749 if (pCert != NULL)
1750 {
b95f153a
VK
1751 size_t sigLen;
1752 const BYTE *signature = pRequest->getBinaryFieldPtr(VID_SIGNATURE, &sigLen);
1753 if (signature != NULL)
1754 {
1755 dwResult = AuthenticateUser(szLogin, reinterpret_cast<const TCHAR*>(signature), sigLen,
1756 pCert, m_challenge, &m_dwUserId, &m_dwSystemAccess, &changePasswd, &intruderLockout,
1757 &closeOtherSessions, false, &graceLogins);
1758 }
1759 else
1760 {
1761 dwResult = RCC_INVALID_REQUEST;
1762 }
5039dede
AK
1763 X509_free(pCert);
1764 }
1765 else
1766 {
1767 dwResult = RCC_BAD_CERTIFICATE;
1768 }
1769#else
1770 dwResult = RCC_NOT_IMPLEMENTED;
1771#endif
1772 break;
958a9397
VK
1773 case NETXMS_AUTH_TYPE_SSO_TICKET:
1774 char ticket[1024];
b368969c 1775 pRequest->getFieldAsMBString(VID_PASSWORD, ticket, 1024);
958a9397
VK
1776 if (CASAuthenticate(ticket, szLogin))
1777 {
1778 debugPrintf(5, _T("SSO ticket %hs is valid, login name %s"), ticket, szLogin);
1779 dwResult = AuthenticateUser(szLogin, NULL, 0, NULL, NULL, &m_dwUserId,
27858eaa 1780 &m_dwSystemAccess, &changePasswd, &intruderLockout,
d888bc1c 1781 &closeOtherSessions, true, &graceLogins);
958a9397
VK
1782 }
1783 else
1784 {
1785 debugPrintf(5, _T("SSO ticket %hs is invalid"), ticket);
1786 dwResult = RCC_ACCESS_DENIED;
1787 }
1788 break;
5039dede
AK
1789 default:
1790 dwResult = RCC_UNSUPPORTED_AUTH_TYPE;
1791 break;
1792 }
1793
1a1d02af
VK
1794 // Additional validation by loaded modules
1795 if (dwResult == RCC_SUCCESS)
1796 {
1797 for(UINT32 i = 0; i < g_dwNumModules; i++)
1798 {
1799 if (g_pModuleList[i].pfAdditionalLoginCheck != NULL)
1800 {
1801 dwResult = g_pModuleList[i].pfAdditionalLoginCheck(m_dwUserId, pRequest);
1802 if (dwResult != RCC_SUCCESS)
1803 {
1804 debugPrintf(4, _T("Login blocked by module %s (rcc=%d)"), g_pModuleList[i].szName, dwResult);
1805 break;
1806 }
1807 }
1808 }
1809 }
1810
5039dede
AK
1811 if (dwResult == RCC_SUCCESS)
1812 {
1813 m_dwFlags |= CSF_AUTHENTICATED;
77a08c86
VK
1814 nx_strncpy(m_loginName, szLogin, MAX_USER_NAME);
1815 _sntprintf(m_sessionName, MAX_SESSION_NAME, _T("%s@%s"), szLogin, m_workstation);
a51628e2 1816 m_loginTime = time(NULL);
b368969c
VK
1817 msg.setField(VID_RCC, RCC_SUCCESS);
1818 msg.setField(VID_USER_SYS_RIGHTS, m_dwSystemAccess);
1819 msg.setField(VID_USER_ID, m_dwUserId);
1820 msg.setField(VID_SESSION_ID, (UINT32)m_id);
1821 msg.setField(VID_CHANGE_PASSWD_FLAG, (WORD)changePasswd);
1822 msg.setField(VID_DBCONN_STATUS, (UINT16)((g_flags & AF_DB_CONNECTION_LOST) ? 0 : 1));
1823 msg.setField(VID_ZONING_ENABLED, (UINT16)((g_flags & AF_ENABLE_ZONING) ? 1 : 0));
90e3031f
VK
1824 msg.setField(VID_POLLING_INTERVAL, (INT32)DCObject::m_defaultPollingInterval);
1825 msg.setField(VID_RETENTION_TIME, (INT32)DCObject::m_defaultRetentionTime);
b368969c
VK
1826 msg.setField(VID_ALARM_STATUS_FLOW_STATE, (UINT16)ConfigReadInt(_T("StrictAlarmStatusFlow"), 0));
1827 msg.setField(VID_TIMED_ALARM_ACK_ENABLED, (UINT16)ConfigReadInt(_T("EnableTimedAlarmAck"), 0));
1828 msg.setField(VID_VIEW_REFRESH_INTERVAL, (UINT16)ConfigReadInt(_T("MinViewRefreshInterval"), 200));
1829 msg.setField(VID_HELPDESK_LINK_ACTIVE, (UINT16)((g_flags & AF_HELPDESK_LINK_ACTIVE) ? 1 : 0));
1830 msg.setField(VID_ALARM_LIST_DISP_LIMIT, ConfigReadULong(_T("AlarmListDisplayLimit"), 4096));
88072662 1831 msg.setField(VID_SERVER_COMMAND_TIMEOUT, ConfigReadULong(_T("ServerCommandOutputTimeout"), 60));
d888bc1c 1832 msg.setField(VID_GRACE_LOGINS, graceLogins);
88072662 1833
4970ef34
VK
1834 if (pRequest->getFieldAsBoolean(VID_ENABLE_COMPRESSION))
1835 {
1836 debugPrintf(3, _T("Protocol level compression is supported by client"));
1837 m_dwFlags |= CSF_COMPRESSION_ENABLED;
1838 msg.setField(VID_ENABLE_COMPRESSION, true);
1839 }
1840 else
1841 {
1842 debugPrintf(3, _T("Protocol level compression is not supported by client"));
1843 }
1844
88072662
VK
1845 TCHAR buffer[MAX_DB_STRING];
1846 ConfigReadStr(_T("ServerName"), buffer, MAX_DB_STRING, _T(""));
1847 msg.setField(VID_SERVER_NAME, buffer);
1848
1849 ConfigReadStr(_T("ServerColor"), buffer, MAX_DB_STRING, _T(""));
1850 msg.setField(VID_SERVER_COLOR, buffer);
1851
8b75662b
EJ
1852 ConfigReadStr(_T("MessageOfTheDay"), buffer, MAX_DB_STRING, _T(""));
1853 msg.setField(VID_MESSAGE_OF_THE_DAY, buffer);
1854
77a08c86 1855 debugPrintf(3, _T("User %s authenticated (language=%s clientInfo=\"%s\")"), m_sessionName, m_language, m_clientInfo);
0d402aa8 1856 writeAuditLog(AUDIT_SECURITY, true, 0, _T("User \"%s\" logged in (language: %s; client info: %s)"), szLogin, m_language, m_clientInfo);
27858eaa
VK
1857
1858 if (closeOtherSessions)
1859 {
1860 debugPrintf(5, _T("Closing other sessions for user %s"), m_loginName);
1861 CloseOtherSessions(m_dwUserId, m_id);
1862 }
5039dede
AK
1863 }
1864 else
1865 {
b368969c 1866 msg.setField(VID_RCC, dwResult);
0d402aa8 1867 writeAuditLog(AUDIT_SECURITY, false, 0,
5039dede 1868 _T("User \"%s\" login failed with error code %d (client info: %s)"),
77a08c86 1869 szLogin, dwResult, m_clientInfo);
ab185583
VK
1870 if (intruderLockout)
1871 {
0d402aa8 1872 writeAuditLog(AUDIT_SECURITY, false, 0,
ab185583
VK
1873 _T("User account \"%s\" temporary disabled due to excess count of failed authentication attempts"), szLogin);
1874 }
ea887770 1875 m_dwUserId = INVALID_INDEX; // reset user ID to avoid incorrect count of logged in sessions for that user
5039dede
AK
1876 }
1877 }
1878 else
1879 {
b368969c 1880 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
5039dede
AK
1881 }
1882
1883 // Send response
e05b1945 1884 sendMessage(&msg);
5039dede
AK
1885}
1886
534e1b83 1887/**
6a6b96c0
EJ
1888 * Send alarm categories to client
1889*/
a881eafa 1890void ClientSession::getAlarmCategories(UINT32 requestId)
6a6b96c0
EJ
1891{
1892 NXCPMessage msg;
1893
1894 // Prepare response message
1895 msg.setCode(CMD_REQUEST_COMPLETED);
a881eafa 1896 msg.setId(requestId);
6a6b96c0
EJ
1897
1898 // Check access rights
1899 if (checkSysAccessRights(SYSTEM_ACCESS_EPP))
1900 {
a881eafa
VK
1901 GetAlarmCategories(&msg);
1902 msg.setField(VID_RCC, RCC_SUCCESS);
6a6b96c0
EJ
1903 }
1904 else
1905 {
1906 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
1907 }
1908 sendMessage(&msg);
1909}
1910
1911/**
1912* Update alarm category
1913*/
1914void ClientSession::modifyAlarmCategory(NXCPMessage *pRequest)
1915{
1916 NXCPMessage msg;
6a6b96c0
EJ
1917 msg.setCode(CMD_REQUEST_COMPLETED);
1918 msg.setId(pRequest->getId());
1919
1920 // Check access rights
1921 if (checkSysAccessRights(SYSTEM_ACCESS_EPP))
1922 {
f5050daf
EJ
1923 UINT32 id = 0;
1924 msg.setField(VID_RCC, UpdateAlarmCategory(pRequest, &id));
1925 msg.setField(VID_CATEGORY_ID, id);
6a6b96c0
EJ
1926 }
1927 else
1928 {
1929 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
1930 }
1931
1932 // Send response
1933 sendMessage(&msg);
1934}
1935
1936/**
1937* Delete alarm category
1938*/
a881eafa 1939void ClientSession::deleteAlarmCategory(NXCPMessage *request)
6a6b96c0
EJ
1940{
1941 NXCPMessage msg;
6a6b96c0 1942 msg.setCode(CMD_REQUEST_COMPLETED);
a881eafa 1943 msg.setId(request->getId());
6a6b96c0
EJ
1944
1945 // Check access rights
1946 if (checkSysAccessRights(SYSTEM_ACCESS_EPP))
1947 {
a881eafa
VK
1948 UINT32 categoryId = request->getFieldAsInt32(VID_CATEGORY_ID);
1949 if (!g_pEventPolicy->isCategoryInUse(categoryId))
6a6b96c0 1950 {
a881eafa 1951 msg.setField(VID_RCC, DeleteAlarmCategory(categoryId));
6a6b96c0
EJ
1952 }
1953 else
1954 {
1955 msg.setField(VID_RCC, RCC_CATEGORY_IN_USE);
1956 }
1957 }
1958 else
1959 {
1960 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
1961 }
1962
1963 // Send response
1964 sendMessage(&msg);
1965}
1966
1967/**
534e1b83
VK
1968 * Send event configuration to client
1969 */
1b281c3e 1970void ClientSession::sendEventDB(NXCPMessage *pRequest)
5039dede 1971{
b368969c 1972 NXCPMessage msg;
480e036b 1973 TCHAR szBuffer[4096];
5039dede
AK
1974
1975 // Prepare response message
b368969c 1976 msg.setCode(CMD_REQUEST_COMPLETED);
1b281c3e 1977 msg.setId(pRequest->getId());
5039dede 1978
fcb03e65 1979 if (checkSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB) || checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) || checkSysAccessRights(SYSTEM_ACCESS_EPP))
5039dede 1980 {
c8076b19 1981 if (!(g_flags & AF_DB_CONNECTION_LOST))
5039dede 1982 {
b368969c 1983 msg.setField(VID_RCC, RCC_SUCCESS);
1b281c3e 1984 GetEventConfiguration(&msg);
5039dede
AK
1985 }
1986 }
1987 else
b368969c 1988 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
e05b1945 1989 sendMessage(&msg);
5039dede
AK
1990}
1991
480e036b 1992/**
480e036b
VK
1993 * Update event template
1994 */
b368969c 1995void ClientSession::modifyEventTemplate(NXCPMessage *pRequest)
5039dede 1996{
b368969c 1997 NXCPMessage msg;
5039dede
AK
1998
1999 // Prepare reply message
b368969c
VK
2000 msg.setCode(CMD_REQUEST_COMPLETED);
2001 msg.setId(pRequest->getId());
8eb2d92b
VK
2002 // Check access rights
2003 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
5039dede 2004 {
1b281c3e
EJ
2005 json_t *oldValue, *newValue;
2006 UINT32 rcc = UpdateEventObject(pRequest, &msg, &oldValue, &newValue);
2007 if (rcc == RCC_SUCCESS)
8eb2d92b 2008 {
305c4f0f
VK
2009 TCHAR name[MAX_EVENT_NAME];
2010 pRequest->getFieldAsString(VID_NAME, name, MAX_EVENT_NAME);
1b281c3e
EJ
2011 writeAuditLogWithValues(AUDIT_SYSCFG, true, 0, oldValue, newValue, _T("Event template %s [%d] modified"), name, pRequest->getFieldAsUInt32(VID_EVENT_CODE));
2012 json_decref(oldValue);
2013 json_decref(newValue);
5039dede 2014 }
1b281c3e 2015 msg.setField(VID_RCC, rcc);
5039dede 2016 }
8eb2d92b
VK
2017 else
2018 {
b368969c 2019 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
1b281c3e 2020 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on modify event template [%d]"), pRequest->getFieldAsUInt32(VID_EVENT_CODE)); // TODO change message
8eb2d92b 2021 }
5039dede
AK
2022
2023 // Send response
e05b1945 2024 sendMessage(&msg);
5039dede
AK
2025}
2026
480e036b
VK
2027/**
2028 * Delete event template
2029 */
b368969c 2030void ClientSession::deleteEventTemplate(NXCPMessage *pRequest)
5039dede 2031{
b368969c 2032 NXCPMessage msg;
967893bb 2033 UINT32 dwEventCode;
5039dede
AK
2034
2035 // Prepare reply message
b368969c
VK
2036 msg.setCode(CMD_REQUEST_COMPLETED);
2037 msg.setId(pRequest->getId());
5039dede 2038
b368969c 2039 dwEventCode = pRequest->getFieldAsUInt32(VID_EVENT_CODE);
8eb2d92b
VK
2040
2041 // Check access rights
2042 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) && (dwEventCode >= FIRST_USER_EVENT_ID))
5039dede 2043 {
1b281c3e
EJ
2044 UINT32 rcc = DeleteEventObject(dwEventCode);
2045 if (rcc == RCC_SUCCESS)
fbf8ec29 2046 writeAuditLog(AUDIT_SYSCFG, true, 0, _T("Event template [%d] deleted"), dwEventCode);
1b281c3e
EJ
2047
2048 msg.setField(VID_RCC, rcc);
5039dede 2049 }
8eb2d92b
VK
2050 else
2051 {
b368969c 2052 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
0d402aa8 2053 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on delete event template [%d]"), dwEventCode);
8eb2d92b 2054 }
5039dede
AK
2055
2056 // Send response
e05b1945 2057 sendMessage(&msg);
5039dede
AK
2058}
2059
480e036b
VK
2060/**
2061 * Generate event code for new event template
2062 */
967893bb 2063void ClientSession::generateEventCode(UINT32 dwRqId)
5039dede 2064{
b368969c 2065 NXCPMessage msg;
5039dede
AK
2066
2067 // Prepare reply message
b368969c
VK
2068 msg.setCode(CMD_REQUEST_COMPLETED);
2069 msg.setId(dwRqId);
5039dede 2070
8eb2d92b
VK
2071 // Check access rights
2072 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
5039dede 2073 {
b368969c 2074 msg.setField(VID_EVENT_CODE, CreateUniqueId(IDG_EVENT));
5039dede
AK
2075 }
2076 else
2077 {
b368969c 2078 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2079 }
2080
2081 // Send response
e05b1945 2082 sendMessage(&msg);
5039dede
AK
2083}
2084
6b8e9f96 2085/**
22f38627
VK
2086 * Data for session object filter
2087 */
2088struct SessionObjectFilterData
2089{
2090 ClientSession *session;
2091 time_t baseTimeStamp;
2092};
2093
2094/**
2095 * Object filter for ClientSession::sendAllObjects
2096 */
2097static bool SessionObjectFilter(NetObj *object, void *data)
2098{
2099 return !object->isHidden() && !object->isSystem() && !object->isDeleted() &&
2100 (object->getTimeStamp() >= ((SessionObjectFilterData *)data)->baseTimeStamp) &&
2101 object->checkAccessRights(((SessionObjectFilterData *)data)->session->getUserId(), OBJECT_ACCESS_READ);
2102}
2103
2104/**
6b8e9f96
VK
2105 * Send all objects to client
2106 */
b368969c 2107void ClientSession::sendAllObjects(NXCPMessage *pRequest)
5039dede 2108{
b368969c 2109 NXCPMessage msg;
5039dede
AK
2110
2111 // Send confirmation message
b368969c
VK
2112 msg.setCode(CMD_REQUEST_COMPLETED);
2113 msg.setId(pRequest->getId());
2114 msg.setField(VID_RCC, RCC_SUCCESS);
e05b1945 2115 sendMessage(&msg);
b368969c 2116 msg.deleteAllFields();
5039dede 2117
62768df3 2118 // Change "sync comments" flag
b368969c 2119 if (pRequest->getFieldAsUInt16(VID_SYNC_COMMENTS))
5039dede
AK
2120 m_dwFlags |= CSF_SYNC_OBJECT_COMMENTS;
2121 else
2122 m_dwFlags &= ~CSF_SYNC_OBJECT_COMMENTS;
2123
5039dede 2124 // Prepare message
b368969c 2125 msg.setCode(CMD_OBJECT);
5039dede
AK
2126
2127 // Send objects, one per message
22f38627
VK
2128 SessionObjectFilterData data;
2129 data.session = this;
2130 data.baseTimeStamp = pRequest->getFieldAsTime(VID_TIMESTAMP);
2131 ObjectArray<NetObj> *objects = g_idxObjectById.getObjects(true, SessionObjectFilter, &data);
c17f6cbc 2132 MutexLock(m_mutexSendObjects);
6aba3998
VK
2133 for(int i = 0; i < objects->size(); i++)
2134 {
2135 NetObj *object = objects->get(i);
22f38627
VK
2136 object->fillMessage(&msg);
2137 if (m_dwFlags & CSF_SYNC_OBJECT_COMMENTS)
2138 object->commentsToMessage(&msg);
2139 if (!object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
5039dede 2140 {
22f38627
VK
2141 // mask passwords
2142 msg.setField(VID_SHARED_SECRET, _T("********"));
2143 msg.setField(VID_SNMP_AUTH_PASSWORD, _T("********"));
2144 msg.setField(VID_SNMP_PRIV_PASSWORD, _T("********"));
5039dede 2145 }
22f38627
VK
2146 sendMessage(&msg);
2147 msg.deleteAllFields();
b16935d5 2148 object->decRefCount();
6aba3998
VK
2149 }
2150 delete objects;
5039dede
AK
2151
2152 // Send end of list notification
b368969c 2153 msg.setCode(CMD_OBJECT_LIST_END);
e05b1945 2154 sendMessage(&msg);
5039dede
AK
2155
2156 MutexUnlock(m_mutexSendObjects);
2157}
2158
6b8e9f96
VK
2159/**
2160 * Send selected objects to client
2161 */
b368969c 2162void ClientSession::sendSelectedObjects(NXCPMessage *pRequest)
62768df3 2163{
b368969c 2164 NXCPMessage msg;
62768df3
VK
2165
2166 // Send confirmation message
b368969c
VK
2167 msg.setCode(CMD_REQUEST_COMPLETED);
2168 msg.setId(pRequest->getId());
2169 msg.setField(VID_RCC, RCC_SUCCESS);
62768df3 2170 sendMessage(&msg);
b368969c 2171 msg.deleteAllFields();
62768df3
VK
2172
2173 // Change "sync comments" flag
0cd0d4af 2174 if (pRequest->getFieldAsBoolean(VID_SYNC_COMMENTS))
62768df3
VK
2175 m_dwFlags |= CSF_SYNC_OBJECT_COMMENTS;
2176 else
2177 m_dwFlags &= ~CSF_SYNC_OBJECT_COMMENTS;
2178
b368969c
VK
2179 UINT32 dwTimeStamp = pRequest->getFieldAsUInt32(VID_TIMESTAMP);
2180 UINT32 numObjects = pRequest->getFieldAsUInt32(VID_NUM_OBJECTS);
967893bb 2181 UINT32 *objects = (UINT32 *)malloc(sizeof(UINT32) * numObjects);
9a68ca24 2182 pRequest->getFieldAsInt32Array(VID_OBJECT_LIST, numObjects, objects);
b368969c 2183 UINT32 options = pRequest->getFieldAsUInt16(VID_FLAGS);
62768df3 2184
c17f6cbc 2185 MutexLock(m_mutexSendObjects);
62768df3
VK
2186
2187 // Prepare message
b368969c 2188 msg.setCode((options & OBJECT_SYNC_SEND_UPDATES) ? CMD_OBJECT_UPDATE : CMD_OBJECT);
62768df3
VK
2189
2190 // Send objects, one per message
967893bb 2191 for(UINT32 i = 0; i < numObjects; i++)
62768df3
VK
2192 {
2193 NetObj *object = FindObjectById(objects[i]);
7a4c94ee 2194 if ((object != NULL) &&
6b8e9f96
VK
2195 object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ) &&
2196 (object->getTimeStamp() >= dwTimeStamp) &&
01152a54 2197 !object->isHidden() && !object->isSystem())
62768df3 2198 {
c42b4551 2199 object->fillMessage(&msg);
62768df3 2200 if (m_dwFlags & CSF_SYNC_OBJECT_COMMENTS)
6b8e9f96 2201 object->commentsToMessage(&msg);
456cb762
AK
2202 if (!object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2203 {
2204 // mask passwords
b368969c
VK
2205 msg.setField(VID_SHARED_SECRET, _T("********"));
2206 msg.setField(VID_SNMP_AUTH_PASSWORD, _T("********"));
2207 msg.setField(VID_SNMP_PRIV_PASSWORD, _T("********"));
456cb762 2208 }
62768df3 2209 sendMessage(&msg);
b368969c 2210 msg.deleteAllFields();
62768df3
VK
2211 }
2212 }
2213
2214 MutexUnlock(m_mutexSendObjects);
2215 safe_free(objects);
9fc8ff38
VK
2216
2217 if (options & OBJECT_SYNC_DUAL_CONFIRM)
2218 {
b368969c
VK
2219 msg.setCode(CMD_REQUEST_COMPLETED);
2220 msg.setField(VID_RCC, RCC_SUCCESS);
9fc8ff38
VK
2221 sendMessage(&msg);
2222 }
62768df3
VK
2223}
2224
b1e9b6b3 2225/**
b1e9b6b3
VK
2226 * Send all configuration variables to client
2227 */
c85c8ef2 2228void ClientSession::getConfigurationVariables(UINT32 dwRqId)
5039dede 2229{
967893bb 2230 UINT32 i, dwId, dwNumRecords;
b368969c 2231 NXCPMessage msg;
2589cc10 2232 TCHAR szBuffer[MAX_CONFIG_VALUE];
5039dede
AK
2233
2234 // Prepare message
b368969c
VK
2235 msg.setCode(CMD_REQUEST_COMPLETED);
2236 msg.setId(dwRqId);
5039dede
AK
2237
2238 // Check user rights
2239 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
2240 {
9bd1bace
VK
2241 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
2242
5039dede 2243 // Retrieve configuration variables from database
c7aa788e 2244 DB_RESULT hResult = DBSelect(hdb, _T("SELECT var_name,var_value,need_server_restart,data_type,description,default_value FROM config WHERE is_visible=1"));
5039dede
AK
2245 if (hResult != NULL)
2246 {
2247 // Send events, one per message
2248 dwNumRecords = DBGetNumRows(hResult);
b368969c 2249 msg.setField(VID_NUM_VARIABLES, dwNumRecords);
c7aa788e 2250 for(i = 0, dwId = VID_VARLIST_BASE; i < dwNumRecords; i++, dwId += 10)
5039dede 2251 {
c7aa788e
EJ
2252 msg.setField(dwId, DBGetField(hResult, i, 0, szBuffer, MAX_DB_STRING));
2253 msg.setField(dwId + 1, DBGetField(hResult, i, 1, szBuffer, MAX_CONFIG_VALUE));
2254 msg.setField(dwId + 2, (WORD)DBGetFieldLong(hResult, i, 2));
2255 msg.setField(dwId + 3, DBGetField(hResult, i, 3, szBuffer, MAX_CONFIG_VALUE));
2256 msg.setField(dwId + 4, DBGetField(hResult, i, 4, szBuffer, MAX_CONFIG_VALUE));
2257 msg.setField(dwId + 5, DBGetField(hResult, i, 5, szBuffer, MAX_CONFIG_VALUE));
e11eade2
EJ
2258 }
2259 DBFreeResult(hResult);
d6fec35c
VK
2260
2261 hResult = DBSelect(hdb, _T("SELECT var_name,var_value,var_description FROM config_values"));
2262 if (hResult != NULL)
e11eade2 2263 {
d6fec35c
VK
2264 dwNumRecords = DBGetNumRows(hResult);
2265 msg.setField(VID_NUM_VALUES, dwNumRecords);
2266 for(i = 0; i < dwNumRecords; i++)
2267 {
2268 msg.setField(dwId++, DBGetField(hResult, i, 0, szBuffer, MAX_DB_STRING));
2269 msg.setField(dwId++, DBGetField(hResult, i, 1, szBuffer, MAX_CONFIG_VALUE));
2270 msg.setField(dwId++, DBGetField(hResult, i, 2, szBuffer, MAX_DB_STRING));
2271 }
2272 DBFreeResult(hResult);
2273
2274 msg.setField(VID_RCC, RCC_SUCCESS);
2275 }
2276 else
2277 {
2278 msg.setField(VID_RCC, RCC_DB_FAILURE);
5039dede 2279 }
d6fec35c
VK
2280 }
2281 else
2282 {
2283 msg.setField(VID_RCC, RCC_DB_FAILURE);
5039dede 2284 }
9bd1bace 2285 DBConnectionPoolReleaseConnection(hdb);
5039dede
AK
2286 }
2287 else
2288 {
b368969c 2289 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2290 }
2291
2292 // Send response
e05b1945 2293 sendMessage(&msg);
5039dede
AK
2294}
2295
b1e9b6b3 2296/**
c85c8ef2
VK
2297 * Get public configuration variable by name
2298 */
2299void ClientSession::getPublicConfigurationVariable(NXCPMessage *request)
2300{
2301 NXCPMessage msg;
2302 msg.setCode(CMD_REQUEST_COMPLETED);
2303 msg.setId(request->getId());
2304
2305 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
2306
2307 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=? AND is_public='Y'"));
2308 if (hStmt != NULL)
2309 {
2310 TCHAR name[64];
2311 request->getFieldAsString(VID_NAME, name, 64);
2312 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, name, DB_BIND_STATIC);
2313
2314 DB_RESULT hResult = DBSelectPrepared(hStmt);
2315 if (hResult != NULL)
2316 {
2317 if (DBGetNumRows(hResult) > 0)
2318 {
2589cc10 2319 TCHAR value[MAX_CONFIG_VALUE];
2320 msg.setField(VID_VALUE, DBGetField(hResult, 0, 0, value, MAX_CONFIG_VALUE));
c85c8ef2
VK
2321 msg.setField(VID_RCC, RCC_SUCCESS);
2322 }
2323 else
2324 {
2325 msg.setField(VID_RCC, RCC_UNKNOWN_CONFIG_VARIABLE);
2326 }
2327 DBFreeResult(hResult);
2328 }
2329 else
2330 {
2331 msg.setField(VID_RCC, RCC_DB_FAILURE);
2332 }
2333 DBFreeStatement(hStmt);
2334 }
2335 else
2336 {
2337 msg.setField(VID_RCC, RCC_DB_FAILURE);
2338 }
2d8d8ea2 2339
c85c8ef2
VK
2340 sendMessage(&msg);
2341}
2342
2343/**
b1e9b6b3
VK
2344 * Set configuration variable's value
2345 */
c85c8ef2 2346void ClientSession::setConfigurationVariable(NXCPMessage *pRequest)
5039dede 2347{
dbb49f94 2348 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
5039dede 2349
dbb49f94
VK
2350 TCHAR name[MAX_OBJECT_NAME];
2351 pRequest->getFieldAsString(VID_NAME, name, MAX_OBJECT_NAME);
5039dede 2352
5039dede
AK
2353 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
2354 {
dbb49f94
VK
2355 TCHAR oldValue[MAX_CONFIG_VALUE], newValue[MAX_CONFIG_VALUE];
2356 pRequest->getFieldAsString(VID_VALUE, newValue, MAX_CONFIG_VALUE);
2357 ConfigReadStr(name, oldValue, MAX_CONFIG_VALUE, _T(""));
2358 if (ConfigWriteStr(name, newValue, true))
c7aa788e 2359 {
b368969c 2360 msg.setField(VID_RCC, RCC_SUCCESS);
c7aa788e
EJ
2361 writeAuditLogWithValues(AUDIT_SYSCFG, true, 0, oldValue, newValue,
2362 _T("Server configuration variable \"%s\" changed from \"%s\" to \"%s\""), name, oldValue, newValue);
2363 }
5039dede 2364 else
c7aa788e 2365 {
b368969c 2366 msg.setField(VID_RCC, RCC_DB_FAILURE);
c7aa788e 2367 }
5039dede
AK
2368 }
2369 else
2370 {
dbb49f94 2371 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on setting server configuration variable \"%s\""), name);
b368969c 2372 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2373 }
2374
2375 // Send response
e05b1945 2376 sendMessage(&msg);
5039dede
AK
2377}
2378
b1e9b6b3 2379/**
c7aa788e
EJ
2380 * Set configuration variable's values to default
2381 */
2382void ClientSession::setDefaultConfigurationVariableValues(NXCPMessage *pRequest)
2383{
2384 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
2385 UINT32 rcc = RCC_SUCCESS;
2386
2387 if (checkSysAccessRights(SYSTEM_ACCESS_SERVER_CONFIG))
2388 {
2389 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
2390 DB_STATEMENT stmt = DBPrepare(hdb, _T("SELECT default_value FROM config WHERE var_name=?"));
2391 if (stmt != NULL)
2392 {
d390e5a8
VK
2393 int numVars = pRequest->getFieldAsInt32(VID_NUM_VARIABLES);
2394 UINT32 fieldId = VID_VARLIST_BASE;
c7aa788e
EJ
2395 TCHAR varName[64], defValue[MAX_CONFIG_VALUE];
2396 for(int i = 0; i < numVars; i++)
2397 {
d390e5a8 2398 pRequest->getFieldAsString(fieldId++, varName, 64);
c7aa788e
EJ
2399 DBBind(stmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
2400
2401 DB_RESULT result = DBSelectPrepared(stmt);
2402 if (result != NULL)
2403 {
2404 DBGetField(result, 0, 0, defValue, MAX_CONFIG_VALUE);
2405 ConfigWriteStr(varName, defValue, false);
2406 }
2407 else
d390e5a8 2408 {
c7aa788e 2409 rcc = RCC_DB_FAILURE;
d390e5a8
VK
2410 break;
2411 }
c7aa788e
EJ
2412 }
2413 DBFreeStatement(stmt);
2414 }
2415 else
d390e5a8 2416 {
c7aa788e 2417 rcc = RCC_DB_FAILURE;
d390e5a8 2418 }
c7aa788e
EJ
2419 DBConnectionPoolReleaseConnection(hdb);
2420 }
2421 else
2422 {
2423 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied for setting server configuration variables to default"));
2424 rcc = RCC_ACCESS_DENIED;
2425 }
2426 // Send response
2427 msg.setField(VID_RCC, rcc);
2428 sendMessage(&msg);
2429
2430}
2431
2432/**
b1e9b6b3
VK
2433 * Delete configuration variable
2434 */
c85c8ef2 2435void ClientSession::deleteConfigurationVariable(NXCPMessage *pRequest)
5039dede 2436{
dbb49f94 2437 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
5039dede 2438
dbb49f94
VK
2439 TCHAR name[MAX_OBJECT_NAME];
2440 pRequest->getFieldAsString(VID_NAME, name, MAX_OBJECT_NAME);
5039dede 2441
5039dede
AK
2442 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
2443 {
35959841 2444 if (ConfigDelete(name))
5039dede 2445 {
b368969c 2446 msg.setField(VID_RCC, RCC_SUCCESS);
dbb49f94 2447 writeAuditLog(AUDIT_SYSCFG, true, 0, _T("Server configuration variable \"%s\" deleted"), name);
5039dede
AK
2448 }
2449 else
2450 {
b368969c 2451 msg.setField(VID_RCC, RCC_DB_FAILURE);
5039dede
AK
2452 }
2453 }
2454 else
2455 {
dbb49f94 2456 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on delete server configuration variable \"%s\""), name);
b368969c 2457 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2458 }
2459
2460 // Send response
e05b1945 2461 sendMessage(&msg);
5039dede
AK
2462}
2463
28229715
VK
2464/**
2465 * Set configuration clob
2466 */
b368969c 2467void ClientSession::setConfigCLOB(NXCPMessage *pRequest)
5039dede 2468{
dbb49f94 2469 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
7a4c94ee 2470
dbb49f94
VK
2471 TCHAR name[MAX_OBJECT_NAME];
2472 pRequest->getFieldAsString(VID_NAME, name, MAX_OBJECT_NAME);
5039dede
AK
2473 if (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG)
2474 {
dbb49f94
VK
2475 TCHAR *newValue = pRequest->getFieldAsString(VID_VALUE);
2476 if (newValue != NULL)
5039dede 2477 {
dbb49f94
VK
2478 TCHAR *oldValue = ConfigReadCLOB(name, _T(""));
2479 if (ConfigWriteCLOB(name, newValue, TRUE))
4d0c32f3 2480 {
b368969c 2481 msg.setField(VID_RCC, RCC_SUCCESS);
dbb49f94
VK
2482 writeAuditLogWithValues(AUDIT_SYSCFG, true, 0, oldValue, newValue,
2483 _T("Server configuration variable (long) \"%s\" changed"), name);
4d0c32f3
VK
2484 }
2485 else
2486 {
b368969c 2487 msg.setField(VID_RCC, RCC_DB_FAILURE);
4d0c32f3 2488 }
dbb49f94
VK
2489 free(oldValue);
2490 free(newValue);
5039dede
AK
2491 }
2492 else
2493 {
b368969c 2494 msg.setField(VID_RCC, RCC_INVALID_REQUEST);
5039dede
AK
2495 }
2496 }
2497 else
2498 {
dbb49f94 2499 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on setting server configuration variable \"%s\""), name);
b368969c 2500 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede 2501 }
7a4c94ee 2502
e05b1945 2503 sendMessage(&msg);
5039dede
AK
2504}
2505
b3eb058b
VK
2506/**
2507 * Get value of configuration clob
2508 */
b368969c 2509void ClientSession::getConfigCLOB(NXCPMessage *pRequest)
5039dede 2510{
b368969c 2511 NXCPMessage msg;
5039dede 2512 TCHAR name[MAX_OBJECT_NAME], *value;
7a4c94ee 2513
b368969c
VK
2514 msg.setId(pRequest->getId());
2515 msg.setCode(CMD_REQUEST_COMPLETED);
7a4c94ee 2516
5039dede
AK
2517 if (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG)
2518 {
b368969c 2519 pRequest->getFieldAsString(VID_NAME, name, MAX_OBJECT_NAME);
5039dede
AK
2520 value = ConfigReadCLOB(name, NULL);
2521 if (value != NULL)
2522 {
b368969c
VK
2523 msg.setField(VID_VALUE, value);
2524 msg.setField(VID_RCC, RCC_SUCCESS);
5039dede
AK
2525 free(value);
2526 }
2527 else
2528 {
b368969c 2529 msg.setField(VID_RCC, RCC_UNKNOWN_VARIABLE);
5039dede
AK
2530 }
2531 }
2532 else
2533 {
b368969c 2534 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede 2535 }
7a4c94ee 2536
e05b1945 2537 sendMessage(&msg);
5039dede
AK
2538}
2539
b3eb058b
VK
2540/**
2541 * Close session
2542 */
1da08bc6 2543void ClientSession::kill()
5039dede 2544{
5d9a9c84
VK
2545 notify(NX_NOTIFY_SESSION_KILLED);
2546
5039dede
AK
2547 // We shutdown socket connection, which will cause
2548 // read thread to stop, and other threads will follow
dbb49f94 2549 shutdown(m_hSocket, SHUT_RDWR);
5039dede
AK
2550}
2551
49fbe41f
VK
2552/**
2553 * Handler for new events
2554 */
e05b1945 2555void ClientSession::onNewEvent(Event *pEvent)
5039dede 2556{
c044d4f3 2557 if (isAuthenticated() && isSubscribedTo(NXC_CHANNEL_EVENTS) && (m_dwSystemAccess & SYSTEM_ACCESS_VIEW_EVENT_LOG))
5039dede 2558 {
1ff4448e 2559 NetObj *object = FindObjectById(pEvent->getSourceId());
2de8de66
VK
2560 // If can't find object - just send to all events, if object found send to thous who have rights
2561 if ((object == NULL) || object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1ff4448e 2562 {
2de8de66
VK
2563 NXCPMessage msg(CMD_EVENTLOG_RECORDS, 0);
2564 pEvent->prepareMessage(&msg);
2565 postMessage(&msg);
1ff4448e 2566 }
5039dede
AK
2567 }
2568}
2569
49fbe41f 2570/**
b784f8ac
VK
2571 * Send object update (executed in thread pool)
2572 */
2573void ClientSession::sendObjectUpdate(NetObj *object)
2574{
2575 NXCPMessage msg(CMD_OBJECT_UPDATE, 0);
2576 if (!object->isDeleted())
2577 {
2578 object->fillMessage(&msg);
2579 if (m_dwFlags & CSF_SYNC_OBJECT_COMMENTS)
2580 object->commentsToMessage(&msg);
2581 }
2582 else
2583 {
2584 msg.setField(VID_OBJECT_ID, object->getId());
2585 msg.setField(VID_IS_DELETED, (UINT16)1);
2586 }
2587 MutexLock(m_mutexSendObjects);
2588 sendMessage(&msg);
2589 MutexUnlock(m_mutexSendObjects);
2590 object->decRefCount();
f55de0a9 2591 decRefCount();
b784f8ac
VK
2592}
2593
2594/**
49fbe41f
VK
2595 * Handler for object changes
2596 */
fffcff95 2597void ClientSession::onObjectChange(NetObj *object)
5039dede 2598{
b784f8ac
VK
2599 if (isAuthenticated() && isSubscribedTo(NXC_CHANNEL_OBJECTS) &&
2600 (object->isDeleted() || object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ)))
2601 {
2602 object->incRefCount();
f55de0a9 2603 incRefCount();
b784f8ac
VK
2604 ThreadPoolExecute(g_mainThreadPool, this, &ClientSession::sendObjectUpdate, object);
2605 }
5039dede
AK
2606}
2607
b1e9b6b3
VK
2608/**
2609 * Send notification message to server
2610 */
967893bb 2611void ClientSession::notify(UINT32 dwCode, UINT32 dwData)
5039dede 2612{
b368969c 2613 NXCPMessage msg;
5039dede 2614
b368969c
VK
2615 msg.setCode(CMD_NOTIFY);
2616 msg.setField(VID_NOTIFICATION_CODE, dwCode);
2617 msg.setField(VID_NOTIFICATION_DATA, dwData);
d8fa3917 2618 postMessage(&msg);
5039dede
AK
2619}
2620
d8fa3917
VK
2621/**
2622 * Set information about conflicting nodes to VID_VALUE field
2623 */
a191c634 2624static void SetNodesConflictString(NXCPMessage *msg, UINT32 zoneUIN, InetAddress ipAddr)
b69af14b 2625{
d8fa3917
VK
2626 if (!ipAddr.isValid())
2627 return;
b69af14b 2628
a191c634
VK
2629 Node *sameNode = FindNodeByIP(zoneUIN, ipAddr);
2630 Subnet *sameSubnet = FindSubnetByIP(zoneUIN, ipAddr);
d8fa3917
VK
2631 if (sameNode != NULL)
2632 {
2633 msg->setField(VID_VALUE, sameNode->getName());
2634 }
2635 else if (sameSubnet != NULL)
2636 {
2637 msg->setField(VID_VALUE, sameSubnet->getName());
2638 }
2639 else
2640 {
2641 msg->setField(VID_VALUE, _T(""));
b69af14b 2642 }
2643}
2644
b1e9b6b3
VK
2645/**
2646 * Modify object
2647 */
b368969c 2648void ClientSession::modifyObject(NXCPMessage *pRequest)
5039dede 2649{
967893bb 2650 UINT32 dwObjectId, dwResult = RCC_SUCCESS;
fffcff95 2651 NetObj *object;
b368969c 2652 NXCPMessage msg;
5039dede
AK
2653
2654 // Prepare reply message
b368969c
VK
2655 msg.setCode(CMD_REQUEST_COMPLETED);
2656 msg.setId(pRequest->getId());
5039dede 2657
b368969c 2658 dwObjectId = pRequest->getFieldAsUInt32(VID_OBJECT_ID);
fffcff95
VK
2659 object = FindObjectById(dwObjectId);
2660 if (object != NULL)
5039dede 2661 {
fffcff95 2662 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
5039dede 2663 {
6336bba3
VK
2664 json_t *oldValue = object->toJson();
2665
5039dede
AK
2666 // If user attempts to change object's ACL, check
2667 // if he has OBJECT_ACCESS_ACL permission
5c44534b 2668 if (pRequest->isFieldExist(VID_ACL_SIZE))
fffcff95 2669 if (!object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_ACL))
5039dede
AK
2670 dwResult = RCC_ACCESS_DENIED;
2671
5d7681cc 2672 // If user attempts to rename object, check object's name
5c44534b 2673 if (pRequest->isFieldExist(VID_OBJECT_NAME))
5d7681cc
VK
2674 {
2675 TCHAR name[256];
b368969c 2676 pRequest->getFieldAsString(VID_OBJECT_NAME, name, 256);
5d7681cc
VK
2677 if (!IsValidObjectName(name, TRUE))
2678 dwResult = RCC_INVALID_OBJECT_NAME;
2679 }
2680
5039dede 2681 // If allowed, change object and set completion code
5d7681cc 2682 if (dwResult == RCC_SUCCESS)
6ff21d27 2683 {
c42b4551 2684 dwResult = object->modifyFromMessage(pRequest);
6ff21d27
VK
2685 if (dwResult == RCC_SUCCESS)
2686 {
fffcff95 2687 object->postModify();
6ff21d27 2688 }
b69af14b 2689 else if (dwResult == RCC_ALREADY_EXIST)
2690 {
d8fa3917 2691 // Add information about conflicting nodes
b69af14b 2692 InetAddress ipAddr;
2693
2694 if (pRequest->isFieldExist(VID_IP_ADDRESS))
2695 {
2696 ipAddr = pRequest->getFieldAsInetAddress(VID_IP_ADDRESS);
2697 } else if (pRequest->isFieldExist(VID_PRIMARY_NAME))
2698 {
2699 TCHAR primaryName[MAX_DNS_NAME];
2700 pRequest->getFieldAsString(VID_PRIMARY_NAME, primaryName, MAX_DNS_NAME);
2701 ipAddr = InetAddress::resolveHostName(primaryName);
2702 }
a191c634 2703 SetNodesConflictString(&msg, ((Node*)object)->getZoneUIN(), ipAddr);
b69af14b 2704 }
6ff21d27 2705 }
b368969c 2706 msg.setField(VID_RCC, dwResult);
5039dede
AK
2707
2708 if (dwResult == RCC_SUCCESS)
2709 {
6336bba3
VK
2710 json_t *newValue = object->toJson();
2711 writeAuditLogWithValues(AUDIT_OBJECTS, true, dwObjectId, oldValue, newValue,
2712 _T("Object %s modified from client"), object->getName());
2713 json_decref(newValue);
5039dede 2714 }
6336bba3 2715 json_decref(oldValue);
5039dede
AK
2716 }
2717 else
2718 {
b368969c 2719 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
6336bba3 2720 writeAuditLog(AUDIT_OBJECTS, false, dwObjectId, _T("Access denied on object modification"));
5039dede
AK
2721 }
2722 }
2723 else
2724 {
b368969c 2725 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
5039dede
AK
2726 }
2727
2728 // Send response
e05b1945 2729 sendMessage(&msg);
5039dede
AK
2730}
2731
b1e9b6b3
VK
2732/**
2733 * Send users database to client
2734 */
967893bb 2735void ClientSession::sendUserDB(UINT32 dwRqId)
5039dede 2736{
b368969c 2737 NXCPMessage msg;
b368969c
VK
2738 msg.setCode(CMD_REQUEST_COMPLETED);
2739 msg.setId(dwRqId);
2740 msg.setField(VID_RCC, RCC_SUCCESS);
e05b1945 2741 sendMessage(&msg);
b368969c 2742 msg.deleteAllFields();
5039dede 2743
a50eaebe 2744 // Send user database
e2579e2e
VK
2745 Iterator<UserDatabaseObject> *users = OpenUserDatabase();
2746 while(users->hasNext())
5039dede 2747 {
e2579e2e
VK
2748 UserDatabaseObject *object = users->next();
2749 msg.setCode(object->isGroup() ? CMD_GROUP_DATA : CMD_USER_DATA);
2750 object->fillMessage(&msg);
e05b1945 2751 sendMessage(&msg);
b368969c 2752 msg.deleteAllFields();
5039dede 2753 }
e2579e2e 2754 CloseUserDatabase(users);
5039dede
AK
2755
2756 // Send end-of-database notification
b368969c 2757 msg.setCode(CMD_USER_DB_EOF);
e05b1945 2758 sendMessage(&msg);
5039dede
AK
2759}
2760
b1e9b6b3
VK
2761/**
2762 * Create new user
2763 */
b368969c 2764void ClientSession::createUser(NXCPMessage *pRequest)
5039dede 2765{
b368969c 2766 NXCPMessage msg;
5039dede
AK
2767
2768 // Prepare response message
b368969c
VK
2769 msg.setCode(CMD_REQUEST_COMPLETED);
2770 msg.setId(pRequest->getId());
5039dede
AK
2771
2772 // Check user rights
2773 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2774 {
b368969c 2775 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2776 }
2777 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2778 {
2779 // User database have to be locked before any
2780 // changes to user database can be made
b368969c 2781 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
5039dede
AK
2782 }
2783 else
2784 {
967893bb 2785 UINT32 dwResult, dwUserId;
35f836fe 2786 TCHAR szUserName[MAX_USER_NAME];
5039dede 2787
b368969c 2788 pRequest->getFieldAsString(VID_USER_NAME, szUserName, MAX_USER_NAME);
5039dede
AK
2789 if (IsValidObjectName(szUserName))
2790 {
84ea7692
VK
2791 bool isGroup = pRequest->getFieldAsBoolean(VID_IS_GROUP);
2792 dwResult = CreateNewUser(szUserName, isGroup, &dwUserId);
b368969c 2793 msg.setField(VID_RCC, dwResult);
5039dede 2794 if (dwResult == RCC_SUCCESS)
0a710f23 2795 {
b368969c 2796 msg.setField(VID_USER_ID, dwUserId); // Send id of new user to client
88e14cac 2797 writeAuditLog(AUDIT_SECURITY, true, 0, _T("%s %s created"), isGroup ? _T("Group") : _T("User"), szUserName);
0a710f23 2798 }
5039dede
AK
2799 }
2800 else
2801 {
b368969c 2802 msg.setField(VID_RCC, RCC_INVALID_OBJECT_NAME);
5039dede
AK
2803 }
2804 }
2805
2806 // Send response
e05b1945 2807 sendMessage(&msg);
5039dede
AK
2808}
2809
b1e9b6b3
VK
2810/**
2811 * Update existing user's data
2812 */
b368969c 2813void ClientSession::updateUser(NXCPMessage *pRequest)
5039dede 2814{
b368969c 2815 NXCPMessage msg;
5039dede
AK
2816
2817 // Prepare response message
b368969c
VK
2818 msg.setCode(CMD_REQUEST_COMPLETED);
2819 msg.setId(pRequest->getId());
5039dede
AK
2820
2821 // Check user rights
2822 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2823 {
b368969c 2824 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2825 }
2826 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2827 {
2828 // User database have to be locked before any
2829 // changes to user database can be made
b368969c 2830 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
5039dede
AK
2831 }
2832 else
2833 {
0f42cad1
VK
2834 json_t *oldData = NULL, *newData = NULL;
2835 UINT32 result = ModifyUserDatabaseObject(pRequest, &oldData, &newData);
0a710f23
VK
2836 if (result == RCC_SUCCESS)
2837 {
2838 TCHAR name[MAX_DB_STRING];
b368969c 2839 UINT32 id = pRequest->getFieldAsUInt32(VID_USER_ID);
0a710f23 2840 ResolveUserId(id, name, MAX_DB_STRING);
0f42cad1 2841 writeAuditLogWithValues(AUDIT_SECURITY, true, 0, oldData, newData,
0a710f23
VK
2842 _T("%s %s modified"), (id & GROUP_FLAG) ? _T("Group") : _T("User"), name);
2843 }
b368969c 2844 msg.setField(VID_RCC, result);
0f42cad1
VK
2845 json_decref(oldData);
2846 json_decref(newData);
5039dede
AK
2847 }
2848
2849 // Send response
e05b1945 2850 sendMessage(&msg);
5039dede
AK
2851}
2852
b1e9b6b3
VK
2853/**
2854 * Delete user
2855 */
2d8d8ea2 2856void ClientSession::detachLdapUser(NXCPMessage *pRequest)
2857{
2858 NXCPMessage msg;
2859
2860 // Prepare response message
2861 msg.setCode(CMD_REQUEST_COMPLETED);
2862 msg.setId(pRequest->getId());
2863 UINT32 id = pRequest->getFieldAsUInt32(VID_USER_ID);
2864
2865 // Check user rights
2866 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2867 {
2868 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2869 }
2870 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2871 {
2872 // User database have to be locked before any
2873 // changes to user database can be made
2874 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2875 }
2876 else
2877 {
2878 UINT32 result = DetachLdapUser(id);
2879 if (result == RCC_SUCCESS)
2880 {
2881 TCHAR name[MAX_DB_STRING];
2882 ResolveUserId(id, name, MAX_DB_STRING);
88e14cac
VK
2883 writeAuditLog(AUDIT_SECURITY, true, 0,
2884 _T("%s %s detached from LDAP account"), (id & GROUP_FLAG) ? _T("Group") : _T("User"), name);
2d8d8ea2 2885 }
2886 msg.setField(VID_RCC, result);
2887 }
2888
2889 // Send response
2890 sendMessage(&msg);
2891}
2892
2893/**
2894 * Delete user
2895 */
b368969c 2896void ClientSession::deleteUser(NXCPMessage *pRequest)
5039dede 2897{
b368969c 2898 NXCPMessage msg;
967893bb 2899 UINT32 dwUserId;
5039dede
AK
2900
2901 // Prepare response message
b368969c
VK
2902 msg.setCode(CMD_REQUEST_COMPLETED);
2903 msg.setId(pRequest->getId());
5039dede
AK
2904
2905 // Check user rights
2906 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2907 {
b368969c 2908 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2909 }
2910 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2911 {
2912 // User database have to be locked before any
2913 // changes to user database can be made
b368969c 2914 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
5039dede
AK
2915 }
2916 else
2917 {
2918 // Get Id of user to be deleted
b368969c 2919 dwUserId = pRequest->getFieldAsUInt32(VID_USER_ID);
5039dede 2920
afc725a8 2921 if ((dwUserId != 0) && (dwUserId != GROUP_EVERYONE))
5039dede 2922 {
06492844
VK
2923 if (!IsLoggedIn(dwUserId))
2924 {
d8a4610c
VK
2925 TCHAR name[MAX_DB_STRING];
2926 ResolveUserId(dwUserId, name, MAX_DB_STRING);
2927 UINT32 rcc = DeleteUserDatabaseObject(dwUserId);
b368969c 2928 msg.setField(VID_RCC, rcc);
d8a4610c
VK
2929 if(rcc == RCC_SUCCESS)
2930 {
88e14cac 2931 writeAuditLog(AUDIT_SECURITY, true, 0,
d8a4610c 2932 _T("%s %s [%d] deleted"), (dwUserId & GROUP_FLAG) ? _T("Group") : _T("User"), name, dwUserId);
88f2990c 2933 }
06492844
VK
2934 }
2935 else
2936 {
2937 // logger in users cannot be deleted
b368969c 2938 msg.setField(VID_RCC, RCC_USER_LOGGED_IN);
06492844 2939 }
5039dede
AK
2940 }
2941 else
2942 {
06492844 2943 // System administrator account and everyone group cannot be deleted
b368969c 2944 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2945 }
2946 }
2947
2948 // Send response
e05b1945 2949 sendMessage(&msg);
5039dede
AK
2950}
2951
b1e9b6b3
VK
2952/**
2953 * Lock/unlock user database
2954 */
967893bb 2955void ClientSession::lockUserDB(UINT32 dwRqId, BOOL bLock)
5039dede 2956{
b368969c 2957 NXCPMessage msg;
35f836fe 2958 TCHAR szBuffer[256];
5039dede
AK
2959
2960 // Prepare response message
b368969c
VK
2961 msg.setCode(CMD_REQUEST_COMPLETED);
2962 msg.setId(dwRqId);
5039dede
AK
2963
2964 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
2965 {
2966 if (bLock)
2967 {
77a08c86 2968 if (!LockComponent(CID_USER_DB, m_id, m_sessionName, NULL, szBuffer))
5039dede 2969 {
b368969c
VK
2970 msg.setField(VID_RCC, RCC_COMPONENT_LOCKED);
2971 msg.setField(VID_LOCKED_BY, szBuffer);
5039dede
AK
2972 }
2973 else
2974 {
2975 m_dwFlags |= CSF_USER_DB_LOCKED;
b368969c 2976 msg.setField(VID_RCC, RCC_SUCCESS);
5039dede
AK
2977 }
2978 }
2979 else
2980 {
2981 if (m_dwFlags & CSF_USER_DB_LOCKED)
2982 {
2983 UnlockComponent(CID_USER_DB);
2984 m_dwFlags &= ~CSF_USER_DB_LOCKED;
2985 }
b368969c 2986 msg.setField(VID_RCC, RCC_SUCCESS);
5039dede
AK
2987 }
2988 }
2989 else
2990 {
2991 // Current user has no rights for user account management
b368969c 2992 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
5039dede
AK
2993 }
2994
2995 // Send response
e05b1945 2996 sendMessage(&msg);
5039dede
AK
2997}
2998
10e1e9b5 2999/**
10e1e9b5
VK
3000 * Change management status for the object
3001 */
b368969c 3002void ClientSession::changeObjectMgmtStatus(NXCPMessage *pRequest)
5039dede 3003{
b368969c 3004 NXCPMessage msg