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