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