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