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