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