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