schema-related information (like schema version, DB syntax, etc.) moved from "config...
[public/netxms.git] / src / server / core / session.cpp
CommitLineData
5039dede
AK
1/* $Id$ */
2/*
3** NetXMS - Network Management System
4** Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Victor Kirhenshtein
5**
6** This program is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2 of the License, or
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19**
20** File: session.cpp
21**
22**/
23
24#include "nxcore.h"
25#include "nxmp_parser.h"
26
27#ifdef _WIN32
28#include <psapi.h>
d717b69c
VK
29#define write _write
30#define close _close
5039dede
AK
31#else
32#include <dirent.h>
33#endif
34
35#ifndef min
36#define min(a,b) ((a) < (b) ? (a) : (b))
37#endif
38
39
40// WARNING! this hack works only for d2i_X509(); be carefull when adding new code
41#ifdef OPENSSL_CONST
42# undef OPENSSL_CONST
43#endif
44#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
45# define OPENSSL_CONST const
46#else
47# define OPENSSL_CONST
48#endif
49
50
51//
52// Constants
53//
54
55#define TRAP_CREATE 1
56#define TRAP_UPDATE 2
57#define TRAP_DELETE 3
58
59#define RAW_MSG_SIZE 262144
60
61
62//
63// Externals
64//
65
66extern Queue g_statusPollQueue;
67extern Queue g_configPollQueue;
68extern Queue g_routePollQueue;
69extern Queue g_discoveryPollQueue;
70extern Queue g_nodePollerQueue;
71extern Queue g_conditionPollerQueue;
72extern Queue *g_pItemQueue;
73
74void UnregisterSession(DWORD dwIndex);
75void ResetDiscoveryPoller(void);
76
77
78//
79// Node poller start data
80//
81
82typedef struct
83{
84 ClientSession *pSession;
85 Node *pNode;
86 int iPollType;
87 DWORD dwRqId;
88} POLLER_START_DATA;
89
90
91//
92// Additional processing thread strt data
93//
94
95typedef struct
96{
97 ClientSession *pSession;
98 CSCPMessage *pMsg;
99} PROCTHREAD_START_DATA;
100
101
102//
103// Object tool acl entry
104//
105
106typedef struct
107{
108 DWORD dwToolId;
109 DWORD dwUserId;
110} OBJECT_TOOL_ACL;
111
112
113//
114// Graph ACL entry
115//
116
117struct GRAPH_ACL_ENTRY
118{
119 DWORD dwGraphId;
120 DWORD dwUserId;
121 DWORD dwAccess;
122};
123
124
125//
126// Additional message processing thread starters
127//
128
129#define CALL_IN_NEW_THREAD(func, msg) \
130{ \
131 PROCTHREAD_START_DATA *pData = (PROCTHREAD_START_DATA *)malloc(sizeof(PROCTHREAD_START_DATA)); \
132 pData->pSession = this; \
133 pData->pMsg = msg; \
134 msg = NULL; /* prevent deletion by main processing thread*/ \
135 m_dwRefCount++; \
136 ThreadCreate(ThreadStarter_##func, 0, pData); \
137}
138
139#define DEFINE_THREAD_STARTER(func) \
140THREAD_RESULT THREAD_CALL ClientSession::ThreadStarter_##func(void *pArg) \
141{ \
142 ((PROCTHREAD_START_DATA *)pArg)->pSession->func(((PROCTHREAD_START_DATA *)pArg)->pMsg); \
143 ((PROCTHREAD_START_DATA *)pArg)->pSession->m_dwRefCount--; \
144 delete ((PROCTHREAD_START_DATA *)pArg)->pMsg; \
145 free(pArg); \
146 return THREAD_OK; \
147}
148
149DEFINE_THREAD_STARTER(GetCollectedData)
150DEFINE_THREAD_STARTER(ClearDCIData)
151DEFINE_THREAD_STARTER(QueryL2Topology)
152DEFINE_THREAD_STARTER(SendEventLog)
153DEFINE_THREAD_STARTER(SendSyslog)
154DEFINE_THREAD_STARTER(CreateObject)
155DEFINE_THREAD_STARTER(GetServerFile)
156
157
158//
159// Fill CSCP message with user data
160//
161
162static void FillUserInfoMessage(CSCPMessage *pMsg, NETXMS_USER *pUser)
163{
164 pMsg->SetVariable(VID_USER_ID, pUser->dwId);
165 pMsg->SetVariable(VID_USER_NAME, pUser->szName);
166 pMsg->SetVariable(VID_USER_FLAGS, pUser->wFlags);
167 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pUser->dwSystemRights);
168 pMsg->SetVariable(VID_USER_FULL_NAME, pUser->szFullName);
169 pMsg->SetVariable(VID_USER_DESCRIPTION, pUser->szDescription);
170 pMsg->SetVariable(VID_GUID, pUser->guid, UUID_LENGTH);
171 pMsg->SetVariable(VID_AUTH_METHOD, (WORD)pUser->nAuthMethod);
172 pMsg->SetVariable(VID_CERT_MAPPING_METHOD, (WORD)pUser->nCertMappingMethod);
173 pMsg->SetVariable(VID_CERT_MAPPING_DATA, CHECK_NULL_EX(pUser->pszCertMappingData));
174}
175
176
177//
178// Fill CSCP message with user group data
179//
180
181static void FillGroupInfoMessage(CSCPMessage *pMsg, NETXMS_USER_GROUP *pGroup)
182{
183 DWORD i, dwId;
184
185 pMsg->SetVariable(VID_USER_ID, pGroup->dwId);
186 pMsg->SetVariable(VID_USER_NAME, pGroup->szName);
187 pMsg->SetVariable(VID_USER_FLAGS, pGroup->wFlags);
188 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pGroup->dwSystemRights);
189 pMsg->SetVariable(VID_USER_DESCRIPTION, pGroup->szDescription);
190 pMsg->SetVariable(VID_NUM_MEMBERS, pGroup->dwNumMembers);
191 pMsg->SetVariable(VID_GUID, pGroup->guid, UUID_LENGTH);
192 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < pGroup->dwNumMembers; i++, dwId++)
193 pMsg->SetVariable(dwId, pGroup->pMembers[i]);
194}
195
196
197//
198// Client communication read thread starter
199//
200
201THREAD_RESULT THREAD_CALL ClientSession::ReadThreadStarter(void *pArg)
202{
203 ((ClientSession *)pArg)->ReadThread();
204
205 // When ClientSession::ReadThread exits, all other session
206 // threads are already stopped, so we can safely destroy
207 // session object
208 UnregisterSession(((ClientSession *)pArg)->GetIndex());
209 delete (ClientSession *)pArg;
210 return THREAD_OK;
211}
212
213
214//
215// Client communication write thread starter
216//
217
218THREAD_RESULT THREAD_CALL ClientSession::WriteThreadStarter(void *pArg)
219{
220 ((ClientSession *)pArg)->WriteThread();
221 return THREAD_OK;
222}
223
224
225//
226// Received message processing thread starter
227//
228
229THREAD_RESULT THREAD_CALL ClientSession::ProcessingThreadStarter(void *pArg)
230{
231 ((ClientSession *)pArg)->ProcessingThread();
232 return THREAD_OK;
233}
234
235
236//
237// Information update processing thread starter
238//
239
240THREAD_RESULT THREAD_CALL ClientSession::UpdateThreadStarter(void *pArg)
241{
242 ((ClientSession *)pArg)->UpdateThread();
243 return THREAD_OK;
244}
245
246
247//
248// Forced node poll thread starter
249//
250
251THREAD_RESULT THREAD_CALL ClientSession::PollerThreadStarter(void *pArg)
252{
253 ((POLLER_START_DATA *)pArg)->pSession->PollerThread(
254 ((POLLER_START_DATA *)pArg)->pNode,
255 ((POLLER_START_DATA *)pArg)->iPollType,
256 ((POLLER_START_DATA *)pArg)->dwRqId);
257 ((POLLER_START_DATA *)pArg)->pSession->DecRefCount();
258 free(pArg);
259 return THREAD_OK;
260}
261
262
263//
264// Client session class constructor
265//
266
267ClientSession::ClientSession(SOCKET hSocket, DWORD dwHostAddr)
268{
269 m_pSendQueue = new Queue;
270 m_pMessageQueue = new Queue;
271 m_pUpdateQueue = new Queue;
272 m_hSocket = hSocket;
273 m_dwIndex = INVALID_INDEX;
274 m_iState = SESSION_STATE_INIT;
275 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
276 m_pCtx = NULL;
277 m_hWriteThread = INVALID_THREAD_HANDLE;
278 m_hProcessingThread = INVALID_THREAD_HANDLE;
279 m_hUpdateThread = INVALID_THREAD_HANDLE;
280 m_mutexSendEvents = MutexCreate();
281 m_mutexSendSyslog = MutexCreate();
282 m_mutexSendTrapLog = MutexCreate();
283 m_mutexSendObjects = MutexCreate();
284 m_mutexSendAlarms = MutexCreate();
285 m_mutexSendActions = MutexCreate();
286 m_mutexSendAuditLog = MutexCreate();
287 m_mutexSendSituations = MutexCreate();
288 m_mutexPollerInit = MutexCreate();
289 m_dwFlags = 0;
290 m_dwHostAddr = dwHostAddr;
291 IpToStr(dwHostAddr, m_szWorkstation);
292 strcpy(m_szUserName, "<not logged in>");
293 m_dwUserId = INVALID_INDEX;
294 m_dwOpenDCIListSize = 0;
295 m_pOpenDCIList = NULL;
296 m_ppEPPRuleList = NULL;
297 m_hCurrFile = -1;
298 m_dwFileRqId = 0;
299 m_dwRefCount = 0;
300 m_dwEncryptionRqId = 0;
301 m_condEncryptionSetup = INVALID_CONDITION_HANDLE;
302 m_dwActiveChannels = 0;
303}
304
305
306//
307// Destructor
308//
309
310ClientSession::~ClientSession()
311{
312 if (m_hSocket != -1)
313 closesocket(m_hSocket);
314 delete m_pSendQueue;
315 delete m_pMessageQueue;
316 delete m_pUpdateQueue;
317 safe_free(m_pMsgBuffer);
318 MutexDestroy(m_mutexSendEvents);
319 MutexDestroy(m_mutexSendSyslog);
320 MutexDestroy(m_mutexSendTrapLog);
321 MutexDestroy(m_mutexSendObjects);
322 MutexDestroy(m_mutexSendAlarms);
323 MutexDestroy(m_mutexSendActions);
324 MutexDestroy(m_mutexSendAuditLog);
325 MutexDestroy(m_mutexSendSituations);
326 MutexDestroy(m_mutexPollerInit);
327 safe_free(m_pOpenDCIList);
328 if (m_ppEPPRuleList != NULL)
329 {
330 DWORD i;
331
332 if (m_dwFlags & CSF_EPP_UPLOAD) // Aborted in the middle of EPP transfer
333 for(i = 0; i < m_dwRecordsUploaded; i++)
334 delete m_ppEPPRuleList[i];
335 free(m_ppEPPRuleList);
336 }
337 DestroyEncryptionContext(m_pCtx);
338 if (m_condEncryptionSetup != INVALID_CONDITION_HANDLE)
339 ConditionDestroy(m_condEncryptionSetup);
340}
341
342
343//
344// Start all threads
345//
346
347void ClientSession::Run(void)
348{
349 m_hWriteThread = ThreadCreateEx(WriteThreadStarter, 0, this);
350 m_hProcessingThread = ThreadCreateEx(ProcessingThreadStarter, 0, this);
351 m_hUpdateThread = ThreadCreateEx(UpdateThreadStarter, 0, this);
352 ThreadCreate(ReadThreadStarter, 0, this);
353}
354
355
356//
357// Print debug information
358//
359
360void ClientSession::DebugPrintf(int level, const TCHAR *format, ...)
361{
362 if (level <= g_nDebugLevel)
363 {
364 va_list args;
365 TCHAR buffer[4096];
366
367 va_start(args, format);
368 _vsntprintf(buffer, 4096, format, args);
369 va_end(args);
370 DbgPrintf(level, _T("[CLSN-%d] %s"), m_dwIndex, buffer);
371 }
372}
373
374
375//
376// ReadThread()
377//
378
379void ClientSession::ReadThread(void)
380{
381 CSCP_MESSAGE *pRawMsg;
382 CSCPMessage *pMsg;
383 BYTE *pDecryptionBuffer = NULL;
384 TCHAR szBuffer[256];
385 int iErr;
386 DWORD i;
387 NetObj *pObject;
388 WORD wFlags;
389
390 // Initialize raw message receiving function
391 RecvNXCPMessage(0, NULL, m_pMsgBuffer, 0, NULL, NULL, 0);
392
393 pRawMsg = (CSCP_MESSAGE *)malloc(RAW_MSG_SIZE);
394#ifdef _WITH_ENCRYPTION
395 pDecryptionBuffer = (BYTE *)malloc(RAW_MSG_SIZE);
396#endif
397 while(1)
398 {
399 if ((iErr = RecvNXCPMessage(m_hSocket, pRawMsg,
400 m_pMsgBuffer, RAW_MSG_SIZE,
401 &m_pCtx, pDecryptionBuffer, INFINITE)) <= 0)
402 break;
403
404 // Check if message is too large
405 if (iErr == 1)
406 {
407 DebugPrintf(4, "Received message %s is too large (%d bytes)",
408 NXCPMessageCodeName(ntohs(pRawMsg->wCode), szBuffer),
409 ntohl(pRawMsg->dwSize));
410 continue;
411 }
412
413 // Check for decryption error
414 if (iErr == 2)
415 {
416 DebugPrintf(4, "Unable to decrypt received message");
417 continue;
418 }
419
420 // Check that actual received packet size is equal to encoded in packet
421 if ((int)ntohl(pRawMsg->dwSize) != iErr)
422 {
423 DebugPrintf(4, "Actual message size doesn't match wSize value (%d,%d)", iErr, ntohl(pRawMsg->dwSize));
424 continue; // Bad packet, wait for next
425 }
426
427 // Special handling for raw messages
428 wFlags = ntohs(pRawMsg->wFlags);
429 if (wFlags & MF_BINARY)
430 {
431 // Convert message header to host format
432 pRawMsg->dwId = ntohl(pRawMsg->dwId);
433 pRawMsg->wCode = ntohs(pRawMsg->wCode);
434 pRawMsg->dwNumVars = ntohl(pRawMsg->dwNumVars);
435 DebugPrintf(6, "Received raw message %s", NXCPMessageCodeName(pRawMsg->wCode, szBuffer));
436
437 if ((pRawMsg->wCode == CMD_FILE_DATA) ||
438 (pRawMsg->wCode == CMD_ABORT_FILE_TRANSFER))
439 {
440 if ((m_hCurrFile != -1) && (m_dwFileRqId == pRawMsg->dwId))
441 {
442 if (pRawMsg->wCode == CMD_FILE_DATA)
443 {
444 if (write(m_hCurrFile, pRawMsg->df, pRawMsg->dwNumVars) == (int)pRawMsg->dwNumVars)
445 {
446 if (wFlags & MF_END_OF_FILE)
447 {
448 CSCPMessage msg;
449
450 close(m_hCurrFile);
451 m_hCurrFile = -1;
452
453 msg.SetCode(CMD_REQUEST_COMPLETED);
454 msg.SetId(pRawMsg->dwId);
455 msg.SetVariable(VID_RCC, RCC_SUCCESS);
456 SendMessage(&msg);
457
458 OnFileUpload(TRUE);
459 }
460 }
461 else
462 {
463 // I/O error
464 CSCPMessage msg;
465
466 close(m_hCurrFile);
467 m_hCurrFile = -1;
468
469 msg.SetCode(CMD_REQUEST_COMPLETED);
470 msg.SetId(pRawMsg->dwId);
471 msg.SetVariable(VID_RCC, RCC_IO_ERROR);
472 SendMessage(&msg);
473
474 OnFileUpload(FALSE);
475 }
476 }
477 else
478 {
479 // Abort current file transfer because of client's problem
480 close(m_hCurrFile);
481 m_hCurrFile = -1;
482
483 OnFileUpload(FALSE);
484 }
485 }
486 else
487 {
488 DebugPrintf(4, "Out of state message (ID: %d)", pRawMsg->dwId);
489 }
490 }
491 }
492 else
493 {
494 // Create message object from raw message
495 pMsg = new CSCPMessage(pRawMsg);
496 if ((pMsg->GetCode() == CMD_SESSION_KEY) && (pMsg->GetId() == m_dwEncryptionRqId))
497 {
498 m_dwEncryptionResult = SetupEncryptionContext(pMsg, &m_pCtx, NULL, g_pServerKey, NXCP_VERSION);
499 ConditionSet(m_condEncryptionSetup);
500 m_dwEncryptionRqId = 0;
501 delete pMsg;
502 }
503 else if (pMsg->GetCode() == CMD_KEEPALIVE)
504 {
505 DebugPrintf(6, "Received message %s", NXCPMessageCodeName(pMsg->GetCode(), szBuffer));
506 RespondToKeepalive(pMsg->GetId());
507 delete pMsg;
508 }
509 else
510 {
511 m_pMessageQueue->Put(pMsg);
512 }
513 }
514 }
515 if (iErr < 0)
516 nxlog_write(MSG_SESSION_CLOSED, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
517 free(pRawMsg);
518#ifdef _WITH_ENCRYPTION
519 free(pDecryptionBuffer);
520#endif
521
522 // Notify other threads to exit
523 m_pSendQueue->Clear();
524 m_pSendQueue->Put(INVALID_POINTER_VALUE);
525 m_pMessageQueue->Clear();
526 m_pMessageQueue->Put(INVALID_POINTER_VALUE);
527 m_pUpdateQueue->Clear();
528 m_pUpdateQueue->Put(INVALID_POINTER_VALUE);
529
530 // Wait for other threads to finish
531 ThreadJoin(m_hWriteThread);
532 ThreadJoin(m_hProcessingThread);
533 ThreadJoin(m_hUpdateThread);
534
535 // Abort current file upload operation, if any
536 if (m_hCurrFile != -1)
537 {
538 close(m_hCurrFile);
539 m_hCurrFile = -1;
540 OnFileUpload(FALSE);
541 }
542
543 // Remove all locks created by this session
544 RemoveAllSessionLocks(m_dwIndex);
545 for(i = 0; i < m_dwOpenDCIListSize; i++)
546 {
547 pObject = FindObjectById(m_pOpenDCIList[i]);
548 if (pObject != NULL)
549 if ((pObject->Type() == OBJECT_NODE) ||
550 (pObject->Type() == OBJECT_CLUSTER) ||
551 (pObject->Type() == OBJECT_TEMPLATE))
552 ((Template *)pObject)->UnlockDCIList(m_dwIndex);
553 }
554
555 // Waiting while reference count becomes 0
556 if (m_dwRefCount > 0)
557 {
558 DebugPrintf(3, "Waiting for pending requests...");
559 do
560 {
561 ThreadSleep(1);
562 } while(m_dwRefCount > 0);
563 }
564
565 WriteAuditLog(AUDIT_SECURITY, TRUE, m_dwUserId, m_szWorkstation, 0, _T("User logged out (client: %s)"), m_szClientInfo);
566 DebugPrintf(3, "Session closed");
567}
568
569
570//
571// WriteThread()
572//
573
574void ClientSession::WriteThread(void)
575{
576 CSCP_MESSAGE *pRawMsg;
577 CSCP_ENCRYPTED_MESSAGE *pEnMsg;
578 char szBuffer[128];
579 BOOL bResult;
580
581 while(1)
582 {
583 pRawMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
584 if (pRawMsg == INVALID_POINTER_VALUE) // Session termination indicator
585 break;
586
587 DebugPrintf(6, "Sending message %s", NXCPMessageCodeName(ntohs(pRawMsg->wCode), szBuffer));
588 if (m_pCtx != NULL)
589 {
590 pEnMsg = CSCPEncryptMessage(m_pCtx, pRawMsg);
591 if (pEnMsg != NULL)
592 {
593 bResult = (SendEx(m_hSocket, (char *)pEnMsg, ntohl(pEnMsg->dwSize), 0) == (int)ntohl(pEnMsg->dwSize));
594 free(pEnMsg);
595 }
596 else
597 {
598 bResult = FALSE;
599 }
600 }
601 else
602 {
603 bResult = (SendEx(m_hSocket, (const char *)pRawMsg, ntohl(pRawMsg->dwSize), 0) == (int)ntohl(pRawMsg->dwSize));
604 }
605 free(pRawMsg);
606
607 if (!bResult)
608 {
609 closesocket(m_hSocket);
610 m_hSocket = -1;
611 break;
612 }
613 }
614}
615
616
617//
618// Update processing thread
619//
620
621void ClientSession::UpdateThread(void)
622{
623 UPDATE_INFO *pUpdate;
624 CSCPMessage msg;
625
626 while(1)
627 {
628 pUpdate = (UPDATE_INFO *)m_pUpdateQueue->GetOrBlock();
629 if (pUpdate == INVALID_POINTER_VALUE) // Session termination indicator
630 break;
631
632 switch(pUpdate->dwCategory)
633 {
634 case INFO_CAT_EVENT:
635 MutexLock(m_mutexSendEvents, INFINITE);
636 SendMessage((CSCPMessage *)pUpdate->pData);
637 MutexUnlock(m_mutexSendEvents);
638 delete (CSCPMessage *)pUpdate->pData;
639 break;
640 case INFO_CAT_SYSLOG_MSG:
641 MutexLock(m_mutexSendSyslog, INFINITE);
642 msg.SetCode(CMD_SYSLOG_RECORDS);
643 CreateMessageFromSyslogMsg(&msg, (NX_LOG_RECORD *)pUpdate->pData);
644 SendMessage(&msg);
645 MutexUnlock(m_mutexSendSyslog);
646 free(pUpdate->pData);
647 break;
648 case INFO_CAT_SNMP_TRAP:
649 MutexLock(m_mutexSendTrapLog, INFINITE);
650 SendMessage((CSCPMessage *)pUpdate->pData);
651 MutexUnlock(m_mutexSendTrapLog);
652 delete (CSCPMessage *)pUpdate->pData;
653 break;
654 case INFO_CAT_AUDIT_RECORD:
655 MutexLock(m_mutexSendAuditLog, INFINITE);
656 SendMessage((CSCPMessage *)pUpdate->pData);
657 MutexUnlock(m_mutexSendAuditLog);
658 delete (CSCPMessage *)pUpdate->pData;
659 break;
660 case INFO_CAT_OBJECT_CHANGE:
661 MutexLock(m_mutexSendObjects, INFINITE);
662 msg.SetCode(CMD_OBJECT_UPDATE);
663 ((NetObj *)pUpdate->pData)->CreateMessage(&msg);
664 if (m_dwFlags & CSF_SYNC_OBJECT_COMMENTS)
665 ((NetObj *)pUpdate->pData)->CommentsToMessage(&msg);
666 SendMessage(&msg);
667 MutexUnlock(m_mutexSendObjects);
668 msg.DeleteAllVariables();
669 ((NetObj *)pUpdate->pData)->DecRefCount();
670 break;
671 case INFO_CAT_ALARM:
672 MutexLock(m_mutexSendAlarms, INFINITE);
673 msg.SetCode(CMD_ALARM_UPDATE);
674 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
675 FillAlarmInfoMessage(&msg, (NXC_ALARM *)pUpdate->pData);
676 SendMessage(&msg);
677 MutexUnlock(m_mutexSendAlarms);
678 msg.DeleteAllVariables();
679 free(pUpdate->pData);
680 break;
681 case INFO_CAT_ACTION:
682 MutexLock(m_mutexSendActions, INFINITE);
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);
688 SendMessage(&msg);
689 MutexUnlock(m_mutexSendActions);
690 msg.DeleteAllVariables();
691 free(pUpdate->pData);
692 break;
693 case INFO_CAT_SITUATION:
694 MutexLock(m_mutexSendSituations, INFINITE);
695 SendMessage((CSCPMessage *)pUpdate->pData);
696 MutexUnlock(m_mutexSendSituations);
697 delete (CSCPMessage *)pUpdate->pData;
698 break;
699 default:
700 break;
701 }
702
703 free(pUpdate);
704 }
705}
706
707
708//
709// Message processing thread
710//
711
712void ClientSession::ProcessingThread(void)
713{
714 CSCPMessage *pMsg;
715 char szBuffer[128];
716 DWORD i;
717 int status;
718
719 while(1)
720 {
721 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
722 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
723 break;
724
725 m_wCurrentCmd = pMsg->GetCode();
726 DebugPrintf(6, "Received message %s", NXCPMessageCodeName(m_wCurrentCmd, szBuffer));
727 if (!(m_dwFlags & CSF_AUTHENTICATED) &&
728 (m_wCurrentCmd != CMD_LOGIN) &&
729 (m_wCurrentCmd != CMD_GET_SERVER_INFO) &&
730 (m_wCurrentCmd != CMD_REQUEST_ENCRYPTION) &&
731 (m_wCurrentCmd != CMD_GET_MY_CONFIG))
732 {
733 delete pMsg;
734 continue;
735 }
736
737 m_iState = SESSION_STATE_PROCESSING;
738 switch(m_wCurrentCmd)
739 {
740 case CMD_LOGIN:
741 Login(pMsg);
742 break;
743 case CMD_GET_SERVER_INFO:
744 SendServerInfo(pMsg->GetId());
745 break;
746 case CMD_KEEPALIVE:
747 RespondToKeepalive(pMsg->GetId());
748 break;
749 case CMD_GET_MY_CONFIG:
750 SendConfigForAgent(pMsg);
751 break;
752 case CMD_GET_OBJECTS:
753 SendAllObjects(pMsg);
754 break;
755 case CMD_GET_EVENTS:
756 CALL_IN_NEW_THREAD(SendEventLog, pMsg);
757 break;
758 case CMD_GET_CONFIG_VARLIST:
759 SendAllConfigVars(pMsg->GetId());
760 break;
761 case CMD_SET_CONFIG_VARIABLE:
762 SetConfigVariable(pMsg);
763 break;
764 case CMD_DELETE_CONFIG_VARIABLE:
765 DeleteConfigVariable(pMsg);
766 break;
767 case CMD_CONFIG_GET_CLOB:
768 GetConfigCLOB(pMsg);
769 break;
770 case CMD_CONFIG_SET_CLOB:
771 SetConfigCLOB(pMsg);
772 break;
773 case CMD_LOAD_EVENT_DB:
774 SendEventDB(pMsg->GetId());
775 break;
776 case CMD_LOCK_EVENT_DB:
777 LockEventDB(pMsg->GetId());
778 break;
779 case CMD_UNLOCK_EVENT_DB:
780 UnlockEventDB(pMsg->GetId());
781 break;
782 case CMD_SET_EVENT_INFO:
783 SetEventInfo(pMsg);
784 break;
785 case CMD_DELETE_EVENT_TEMPLATE:
786 DeleteEventTemplate(pMsg);
787 break;
788 case CMD_GENERATE_EVENT_CODE:
789 GenerateEventCode(pMsg->GetId());
790 break;
791 case CMD_MODIFY_OBJECT:
792 ModifyObject(pMsg);
793 break;
794 case CMD_SET_OBJECT_MGMT_STATUS:
795 ChangeObjectMgmtStatus(pMsg);
796 break;
797 case CMD_LOAD_USER_DB:
798 SendUserDB(pMsg->GetId());
799 break;
800 case CMD_CREATE_USER:
801 CreateUser(pMsg);
802 break;
803 case CMD_UPDATE_USER:
804 UpdateUser(pMsg);
805 break;
806 case CMD_DELETE_USER:
807 DeleteUser(pMsg);
808 break;
809 case CMD_LOCK_USER_DB:
810 LockUserDB(pMsg->GetId(), TRUE);
811 break;
812 case CMD_UNLOCK_USER_DB:
813 LockUserDB(pMsg->GetId(), FALSE);
814 break;
815 case CMD_SET_PASSWORD:
816 SetPassword(pMsg);
817 break;
818 case CMD_GET_NODE_DCI_LIST:
819 OpenNodeDCIList(pMsg);
820 break;
821 case CMD_UNLOCK_NODE_DCI_LIST:
822 CloseNodeDCIList(pMsg);
823 break;
824 case CMD_CREATE_NEW_DCI:
825 case CMD_MODIFY_NODE_DCI:
826 case CMD_DELETE_NODE_DCI:
827 ModifyNodeDCI(pMsg);
828 break;
829 case CMD_SET_DCI_STATUS:
830 ChangeDCIStatus(pMsg);
831 break;
832 case CMD_COPY_DCI:
833 CopyDCI(pMsg);
834 break;
835 case CMD_APPLY_TEMPLATE:
836 ApplyTemplate(pMsg);
837 break;
838 case CMD_GET_DCI_DATA:
839 CALL_IN_NEW_THREAD(GetCollectedData, pMsg);
840 break;
841 case CMD_CLEAR_DCI_DATA:
842 CALL_IN_NEW_THREAD(ClearDCIData, pMsg);
843 break;
844 case CMD_OPEN_EPP:
845 OpenEPP(pMsg->GetId());
846 break;
847 case CMD_CLOSE_EPP:
848 CloseEPP(pMsg->GetId());
849 break;
850 case CMD_SAVE_EPP:
851 SaveEPP(pMsg);
852 break;
853 case CMD_EPP_RECORD:
854 ProcessEPPRecord(pMsg);
855 break;
856 case CMD_GET_MIB_TIMESTAMP:
857 SendMIBTimestamp(pMsg->GetId());
858 break;
859 case CMD_GET_MIB:
860 SendMIB(pMsg->GetId());
861 break;
862 case CMD_CREATE_OBJECT:
863 CALL_IN_NEW_THREAD(CreateObject, pMsg);
864 break;
865 case CMD_BIND_OBJECT:
866 ChangeObjectBinding(pMsg, TRUE);
867 break;
868 case CMD_UNBIND_OBJECT:
869 ChangeObjectBinding(pMsg, FALSE);
870 break;
871 case CMD_GET_IMAGE_LIST:
872 SendImageCatalogue(this, pMsg->GetId(), pMsg->GetVariableShort(VID_IMAGE_FORMAT));
873 break;
874 case CMD_LOAD_IMAGE_FILE:
875 SendImageFile(this, pMsg->GetId(), pMsg->GetVariableLong(VID_IMAGE_ID),
876 pMsg->GetVariableShort(VID_IMAGE_FORMAT));
877 break;
878 case CMD_GET_DEFAULT_IMAGE_LIST:
879 SendDefaultImageList(this, pMsg->GetId());
880 break;
881 case CMD_GET_ALL_ALARMS:
882 SendAllAlarms(pMsg->GetId(), pMsg->GetVariableShort(VID_IS_ACK));
883 break;
884 case CMD_GET_ALARM:
885 break;
886 case CMD_ACK_ALARM:
887 AcknowledgeAlarm(pMsg);
888 break;
889 case CMD_TERMINATE_ALARM:
890 TerminateAlarm(pMsg);
891 break;
892 case CMD_DELETE_ALARM:
893 DeleteAlarm(pMsg);
894 break;
895 case CMD_LOCK_ACTION_DB:
896 LockActionDB(pMsg->GetId(), TRUE);
897 break;
898 case CMD_UNLOCK_ACTION_DB:
899 LockActionDB(pMsg->GetId(), FALSE);
900 break;
901 case CMD_CREATE_ACTION:
902 CreateAction(pMsg);
903 break;
904 case CMD_MODIFY_ACTION:
905 UpdateAction(pMsg);
906 break;
907 case CMD_DELETE_ACTION:
908 DeleteAction(pMsg);
909 break;
910 case CMD_LOAD_ACTIONS:
911 SendAllActions(pMsg->GetId());
912 break;
913 case CMD_GET_CONTAINER_CAT_LIST:
914 SendContainerCategories(pMsg->GetId());
915 break;
916 case CMD_DELETE_OBJECT:
917 DeleteObject(pMsg);
918 break;
919 case CMD_POLL_NODE:
920 ForcedNodePoll(pMsg);
921 break;
922 case CMD_TRAP:
923 OnTrap(pMsg);
924 break;
925 case CMD_WAKEUP_NODE:
926 OnWakeUpNode(pMsg);
927 break;
928 case CMD_LOCK_TRAP_CFG:
929 LockTrapCfg(pMsg->GetId(), TRUE);
930 break;
931 case CMD_UNLOCK_TRAP_CFG:
932 LockTrapCfg(pMsg->GetId(), FALSE);
933 break;
934 case CMD_CREATE_TRAP:
935 EditTrap(TRAP_CREATE, pMsg);
936 break;
937 case CMD_MODIFY_TRAP:
938 EditTrap(TRAP_UPDATE, pMsg);
939 break;
940 case CMD_DELETE_TRAP:
941 EditTrap(TRAP_DELETE, pMsg);
942 break;
943 case CMD_LOAD_TRAP_CFG:
944 SendAllTraps(pMsg->GetId());
945 break;
946 case CMD_GET_TRAP_CFG_RO:
947 SendAllTraps2(pMsg->GetId());
948 break;
949 case CMD_QUERY_PARAMETER:
950 QueryParameter(pMsg);
951 break;
952 case CMD_LOCK_PACKAGE_DB:
953 LockPackageDB(pMsg->GetId(), TRUE);
954 break;
955 case CMD_UNLOCK_PACKAGE_DB:
956 LockPackageDB(pMsg->GetId(), FALSE);
957 break;
958 case CMD_GET_PACKAGE_LIST:
959 SendAllPackages(pMsg->GetId());
960 break;
961 case CMD_INSTALL_PACKAGE:
962 InstallPackage(pMsg);
963 break;
964 case CMD_REMOVE_PACKAGE:
965 RemovePackage(pMsg);
966 break;
967 case CMD_GET_PARAMETER_LIST:
968 SendParametersList(pMsg);
969 break;
970 case CMD_DEPLOY_PACKAGE:
971 DeployPackage(pMsg);
972 break;
973 case CMD_GET_LAST_VALUES:
974 SendLastValues(pMsg);
975 break;
976 case CMD_GET_USER_VARIABLE:
977 GetUserVariable(pMsg);
978 break;
979 case CMD_SET_USER_VARIABLE:
980 SetUserVariable(pMsg);
981 break;
982 case CMD_DELETE_USER_VARIABLE:
983 DeleteUserVariable(pMsg);
984 break;
985 case CMD_ENUM_USER_VARIABLES:
986 EnumUserVariables(pMsg);
987 break;
988 case CMD_COPY_USER_VARIABLE:
989 CopyUserVariable(pMsg);
990 break;
991 case CMD_CHANGE_IP_ADDR:
992 ChangeObjectIP(pMsg);
993 break;
994 case CMD_REQUEST_ENCRYPTION:
995 SetupEncryption(pMsg->GetId());
996 break;
997 case CMD_GET_AGENT_CONFIG:
998 GetAgentConfig(pMsg);
999 break;
1000 case CMD_UPDATE_AGENT_CONFIG:
1001 UpdateAgentConfig(pMsg);
1002 break;
1003 case CMD_EXECUTE_ACTION:
1004 ExecuteAction(pMsg);
1005 break;
1006 case CMD_GET_OBJECT_TOOLS:
1007 SendObjectTools(pMsg->GetId());
1008 break;
1009 case CMD_EXEC_TABLE_TOOL:
1010 ExecTableTool(pMsg);
1011 break;
1012 case CMD_LOCK_OBJECT_TOOLS:
1013 LockObjectTools(pMsg->GetId(), TRUE);
1014 break;
1015 case CMD_UNLOCK_OBJECT_TOOLS:
1016 LockObjectTools(pMsg->GetId(), FALSE);
1017 break;
1018 case CMD_GET_OBJECT_TOOL_DETAILS:
1019 SendObjectToolDetails(pMsg);
1020 break;
1021 case CMD_UPDATE_OBJECT_TOOL:
1022 UpdateObjectTool(pMsg);
1023 break;
1024 case CMD_DELETE_OBJECT_TOOL:
1025 DeleteObjectTool(pMsg);
1026 break;
1027 case CMD_GENERATE_OBJECT_TOOL_ID:
1028 GenerateObjectToolId(pMsg->GetId());
1029 break;
1030 case CMD_CHANGE_SUBSCRIPTION:
1031 ChangeSubscription(pMsg);
1032 break;
1033 case CMD_GET_SYSLOG:
1034 CALL_IN_NEW_THREAD(SendSyslog, pMsg);
1035 break;
5039dede
AK
1036 case CMD_GET_SERVER_STATS:
1037 SendServerStats(pMsg->GetId());
1038 break;
1039 case CMD_GET_SCRIPT_LIST:
1040 SendScriptList(pMsg->GetId());
1041 break;
1042 case CMD_GET_SCRIPT:
1043 SendScript(pMsg);
1044 break;
1045 case CMD_UPDATE_SCRIPT:
1046 UpdateScript(pMsg);
1047 break;
1048 case CMD_RENAME_SCRIPT:
1049 RenameScript(pMsg);
1050 break;
1051 case CMD_DELETE_SCRIPT:
1052 DeleteScript(pMsg);
1053 break;
1054 case CMD_GET_SESSION_LIST:
1055 SendSessionList(pMsg->GetId());
1056 break;
1057 case CMD_KILL_SESSION:
1058 KillSession(pMsg);
1059 break;
1060 case CMD_GET_TRAP_LOG:
1061 SendTrapLog(pMsg);
1062 break;
1063 case CMD_START_SNMP_WALK:
1064 StartSnmpWalk(pMsg);
1065 break;
1066 case CMD_GET_MAP_LIST:
1067 SendMapList(pMsg->GetId());
1068 break;
1069 case CMD_RESOLVE_MAP_NAME:
1070 ResolveMapName(pMsg);
1071 break;
1072 case CMD_CREATE_MAP:
1073 CreateMap(pMsg);
1074 break;
1075 case CMD_RENAME_MAP:
1076 RenameMap(pMsg);
1077 break;
1078 case CMD_SAVE_MAP:
1079 SaveMap(pMsg);
1080 break;
0b514e86
VK
1081 case CMD_DELETE_MAP:
1082 DeleteMap(pMsg);
1083 break;
5039dede
AK
1084 case CMD_SUBMAP_DATA:
1085 ProcessSubmapData(pMsg);
1086 break;
1087 case CMD_LOAD_MAP:
1088 LoadMap(pMsg);
1089 break;
1090 case CMD_UPLOAD_SUBMAP_BK_IMAGE:
1091 RecvSubmapBkImage(pMsg);
1092 break;
1093 case CMD_GET_SUBMAP_BK_IMAGE:
1094 SendSubmapBkImage(pMsg);
1095 break;
1096 case CMD_RESOLVE_DCI_NAMES:
1097 ResolveDCINames(pMsg);
1098 break;
1099 case CMD_GET_DCI_INFO:
1100 SendDCIInfo(pMsg);
1101 break;
1102 case CMD_GET_DCI_EVENTS_LIST:
1103 SendDCIEventList(pMsg);
1104 break;
1105 case CMD_GET_SYSTEM_DCI_LIST:
1106 SendSystemDCIList(pMsg);
1107 break;
1108 case CMD_PUSH_DCI_DATA:
1109 PushDCIData(pMsg);
1110 break;
1111 case CMD_GET_AGENT_CFG_LIST:
1112 SendAgentCfgList(pMsg->GetId());
1113 break;
1114 case CMD_OPEN_AGENT_CONFIG:
1115 OpenAgentConfig(pMsg);
1116 break;
1117 case CMD_SAVE_AGENT_CONFIG:
1118 SaveAgentConfig(pMsg);
1119 break;
1120 case CMD_DELETE_AGENT_CONFIG:
1121 DeleteAgentConfig(pMsg);
1122 break;
1123 case CMD_SWAP_AGENT_CONFIGS:
1124 SwapAgentConfigs(pMsg);
1125 break;
1126 case CMD_GET_OBJECT_COMMENTS:
1127 SendObjectComments(pMsg);
1128 break;
1129 case CMD_UPDATE_OBJECT_COMMENTS:
1130 UpdateObjectComments(pMsg);
1131 break;
1132 case CMD_GET_ADDR_LIST:
1133 GetAddrList(pMsg);
1134 break;
1135 case CMD_SET_ADDR_LIST:
1136 SetAddrList(pMsg);
1137 break;
1138 case CMD_RESET_COMPONENT:
1139 ResetComponent(pMsg);
1140 break;
1141 case CMD_CREATE_MGMT_PACK:
1142 CreateManagementPack(pMsg);
1143 break;
1144 case CMD_INSTALL_MGMT_PACK:
1145 InstallManagementPack(pMsg);
1146 break;
1147 case CMD_GET_GRAPH_LIST:
1148 SendGraphList(pMsg->GetId());
1149 break;
1150 case CMD_DEFINE_GRAPH:
1151 DefineGraph(pMsg);
1152 break;
1153 case CMD_DELETE_GRAPH:
1154 DeleteGraph(pMsg);
1155 break;
1156 case CMD_ADD_CA_CERTIFICATE:
1157 AddCACertificate(pMsg);
1158 break;
1159 case CMD_DELETE_CERTIFICATE:
1160 DeleteCertificate(pMsg);
1161 break;
1162 case CMD_UPDATE_CERT_COMMENTS:
1163 UpdateCertificateComments(pMsg);
1164 break;
1165 case CMD_GET_CERT_LIST:
1166 SendCertificateList(pMsg->GetId());
1167 break;
1168 case CMD_QUERY_L2_TOPOLOGY:
1169 CALL_IN_NEW_THREAD(QueryL2Topology, pMsg);
1170 break;
1171 case CMD_SEND_SMS:
1172 SendSMS(pMsg);
1173 break;
1174 case CMD_GET_COMMUNITY_LIST:
1175 SendCommunityList(pMsg->GetId());
1176 break;
1177 case CMD_UPDATE_COMMUNITY_LIST:
1178 UpdateCommunityList(pMsg);
1179 break;
1180 case CMD_GET_SITUATION_LIST:
1181 SendSituationList(pMsg->GetId());
1182 break;
1183 case CMD_CREATE_SITUATION:
1184 CreateSituation(pMsg);
1185 break;
1186 case CMD_UPDATE_SITUATION:
1187 UpdateSituation(pMsg);
1188 break;
1189 case CMD_DELETE_SITUATION:
1190 DeleteSituation(pMsg);
1191 break;
1192 case CMD_DEL_SITUATION_INSTANCE:
1193 DeleteSituationInstance(pMsg);
1194 break;
1195 case CMD_WEBMAP_ADD:
1196 WebMapAdd(pMsg);
1197 break;
1198 case CMD_WEBMAP_UPDATE_PROPS:
1199 WebMapUpdateProps(pMsg);
1200 break;
1201 case CMD_WEBMAP_UPDATE_DATA:
1202 WebMapUpdateData(pMsg);
1203 break;
1204 case CMD_WEBMAP_DELETE:
1205 WebMapDelete(pMsg);
1206 break;
1207 case CMD_WEBMAP_GET_DATA:
1208 WebMapGetData(pMsg);
1209 break;
1210 case CMD_WEBMAP_GET_LIST:
1211 WebMapGetList(pMsg->GetId());
1212 break;
1213 case CMD_REGISTER_AGENT:
1214 RegisterAgent(pMsg);
1215 break;
1216 case CMD_GET_SERVER_FILE:
1217 CALL_IN_NEW_THREAD(GetServerFile, pMsg);
1218 break;
1219 default:
1220 // Pass message to loaded modules
1221 for(i = 0; i < g_dwNumModules; i++)
1222 {
1223 if (g_pModuleList[i].pfCommandHandler != NULL)
1224 {
1225 status = g_pModuleList[i].pfCommandHandler(m_wCurrentCmd, pMsg, this);
1226 if (status != NXMOD_COMMAND_IGNORED)
1227 {
1228 if (status == NXMOD_COMMAND_ACCEPTED_ASYNC)
1229 {
1230 pMsg = NULL; // Prevent deletion
1231 m_dwRefCount++;
1232 }
1233 break; // Message was processed by the module
1234 }
1235 }
1236 }
1237 if (i == g_dwNumModules)
1238 {
1239 CSCPMessage response;
1240
1241 response.SetId(pMsg->GetId());
1242 response.SetCode(CMD_REQUEST_COMPLETED);
1243 response.SetVariable(VID_RCC, RCC_NOT_IMPLEMENTED);
1244 SendMessage(&response);
1245 }
1246 break;
1247 }
1248 delete pMsg;
1249 m_iState = (m_dwFlags & CSF_AUTHENTICATED) ? SESSION_STATE_IDLE : SESSION_STATE_INIT;
1250 }
1251}
1252
1253
1254//
1255// Respond to client's keepalive message
1256//
1257
1258void ClientSession::RespondToKeepalive(DWORD dwRqId)
1259{
1260 CSCPMessage msg;
1261
1262 msg.SetCode(CMD_REQUEST_COMPLETED);
1263 msg.SetId(dwRqId);
1264 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1265 SendMessage(&msg);
1266}
1267
1268
1269//
1270// Process received file
1271//
1272
1273void ClientSession::OnFileUpload(BOOL bSuccess)
1274{
1275 // Do processing specific to command initiated file upload
1276 switch(m_dwUploadCommand)
1277 {
1278 case CMD_INSTALL_PACKAGE:
1279 if (!bSuccess)
1280 {
1281 TCHAR szQuery[256];
1282
1283 _sntprintf(szQuery, 256, _T("DELETE FROM agent_pkg WHERE pkg_id=%d"), m_dwUploadData);
1284 DBQuery(g_hCoreDB, szQuery);
1285 }
1286 break;
1287 default:
1288 break;
1289 }
1290
1291 // Remove received file in case of failure
1292 if (!bSuccess)
1293 _tunlink(m_szCurrFileName);
1294}
1295
1296
1297//
1298// Send server information to client
1299//
1300
1301void ClientSession::SendServerInfo(DWORD dwRqId)
1302{
1303 CSCPMessage msg;
1304 TCHAR szBuffer[1024];
1305 String strURL;
1306
1307 // Prepare response message
1308 msg.SetCode(CMD_REQUEST_COMPLETED);
1309 msg.SetId(dwRqId);
1310
1311 // Generate challenge for certificate authentication
1312#ifdef _WITH_ENCRYPTION
1313 RAND_bytes(m_challenge, CLIENT_CHALLENGE_SIZE);
1314#else
1315 memset(m_challenge, 0, CLIENT_CHALLENGE_SIZE);
1316#endif
1317
1318 // Fill message with server info
1319 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1320 msg.SetVariable(VID_SERVER_VERSION, NETXMS_VERSION_STRING);
1321 msg.SetVariable(VID_SERVER_ID, (BYTE *)&g_qwServerId, sizeof(QWORD));
1322 msg.SetVariable(VID_SUPPORTED_ENCRYPTION, (DWORD)0);
1323 msg.SetVariable(VID_PROTOCOL_VERSION, (DWORD)CLIENT_PROTOCOL_VERSION);
1324 msg.SetVariable(VID_CHALLENGE, m_challenge, CLIENT_CHALLENGE_SIZE);
1325
1326#if defined(_WIN32)
1327 TIME_ZONE_INFORMATION tz;
1328 WCHAR wst[4], wdt[8], *curr;
1329 int i;
1330
1331 GetTimeZoneInformation(&tz);
1332
1333 // Create 3 letter abbreviation for standard name
1334 for(i = 0, curr = tz.StandardName; (*curr != 0) && (i < 3); curr++)
1335 if (iswupper(*curr))
1336 wst[i++] = *curr;
1337 while(i < 3)
1338 wst[i++] = L'X';
1339 wst[i] = 0;
1340
1341 // Create abbreviation for DST name
1342 for(i = 0, curr = tz.DaylightName; (*curr != 0) && (i < 7); curr++)
1343 if (iswupper(*curr))
1344 wdt[i++] = *curr;
1345 while(i < 3)
1346 wdt[i++] = L'X';
1347 wdt[i] = 0;
1348
1349#ifdef UNICODE
1350 swprintf(szBuffer, L"%s%c%02d%s", wst, (tz.Bias >= 0) ? '+' : '-',
1351 abs(tz.Bias) / 60, (tz.DaylightBias != 0) ? wdt : L"");
1352#else
1353 sprintf(szBuffer, "%S%c%02d%S", wst, (tz.Bias >= 0) ? '+' : '-',
1354 abs(tz.Bias) / 60, (tz.DaylightBias != 0) ? wdt : L"");
1355#endif
1356#elif HAVE_DECL_TIMEZONE
1357 sprintf(szBuffer, "%s%c%02d%s", tzname[0], (timezone >= 0) ? '+' : '-',
1358 abs(timezone) / 3600, (tzname[1] != NULL) ? tzname[1] : "");
1359#elif HAVE_TM_GMTOFF
1360 time_t t;
1361 struct tm *loc;
1362 int gmtOffset;
1363#if HAVE_LOCALTIME_R
1364 struct tm tmbuff;
1365#endif
1366
1367 t = time(NULL);
1368#if HAVE_LOCALTIME_R
1369 loc = localtime_r(&t, &tmbuff);
1370#else
1371 loc = localtime(&t);
1372#endif
1373 gmtOffset = -loc->tm_gmtoff / 3600;
1374 if (loc->tm_isdst)
1375 gmtOffset++;
1376 sprintf(szBuffer, "%s%c%02d%s", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1377 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
1378#else
1379 szBuffer[0] = 0;
1380#endif
1381 msg.SetVariable(VID_TIMEZONE, szBuffer);
1382 DebugPrintf(2, "Server time zone: %s", szBuffer);
1383
1384 ConfigReadStr(_T("WindowsConsoleUpgradeURL"), szBuffer, 1024,
1385 _T("http://www.netxms.org/download/netxms-%version%.exe"));
1386 strURL = szBuffer;
1387 strURL.Translate(_T("%version%"), NETXMS_VERSION_STRING);
1388 msg.SetVariable(VID_CONSOLE_UPGRADE_URL, (TCHAR *)strURL);
1389
1390 // Send response
1391 SendMessage(&msg);
1392}
1393
1394
1395//
1396// Authenticate client
1397//
1398
1399void ClientSession::Login(CSCPMessage *pRequest)
1400{
1401 CSCPMessage msg;
1402 TCHAR szLogin[MAX_USER_NAME], szPassword[MAX_DB_STRING], szBuffer[32];
1403 int nAuthType;
1404 BOOL bChangePasswd;
1405 DWORD dwResult;
1406#ifdef _WITH_ENCRYPTION
1407 X509 *pCert;
1408#endif
1409
1410 // Prepare response message
1411 msg.SetCode(CMD_LOGIN_RESP);
1412 msg.SetId(pRequest->GetId());
1413
1414 // Get client info string
1415 if (pRequest->IsVariableExist(VID_CLIENT_INFO))
1416 {
1417 TCHAR szClientInfo[32], szOSInfo[32], szLibVersion[16];
1418
1419 pRequest->GetVariableStr(VID_CLIENT_INFO, szClientInfo, 32);
1420 pRequest->GetVariableStr(VID_OS_INFO, szOSInfo, 32);
1421 pRequest->GetVariableStr(VID_LIBNXCL_VERSION, szLibVersion, 16);
1422 _sntprintf(m_szClientInfo, 96, _T("%s (%s; libnxcl %s)"),
1423 szClientInfo, szOSInfo, szLibVersion);
1424 }
1425
1426 if (!(m_dwFlags & CSF_AUTHENTICATED))
1427 {
1428 pRequest->GetVariableStr(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
1429 nAuthType = (int)pRequest->GetVariableShort(VID_AUTH_TYPE);
1430 switch(nAuthType)
1431 {
1432 case NETXMS_AUTH_TYPE_PASSWORD:
1433 pRequest->GetVariableStr(VID_PASSWORD, szPassword, MAX_DB_STRING);
1434 dwResult = AuthenticateUser(szLogin, szPassword, 0, NULL, NULL, &m_dwUserId,
1435 &m_dwSystemAccess, &bChangePasswd);
1436 break;
1437 case NETXMS_AUTH_TYPE_CERTIFICATE:
1438#ifdef _WITH_ENCRYPTION
1439 pCert = CertificateFromLoginMessage(pRequest);
1440 if (pCert != NULL)
1441 {
1442 BYTE signature[256];
1443 DWORD dwSigLen;
1444
1445 dwSigLen = pRequest->GetVariableBinary(VID_SIGNATURE, signature, 256);
1446 dwResult = AuthenticateUser(szLogin, (TCHAR *)signature, dwSigLen, pCert,
1447 m_challenge, &m_dwUserId, &m_dwSystemAccess, &bChangePasswd);
1448 X509_free(pCert);
1449 }
1450 else
1451 {
1452 dwResult = RCC_BAD_CERTIFICATE;
1453 }
1454#else
1455 dwResult = RCC_NOT_IMPLEMENTED;
1456#endif
1457 break;
1458 default:
1459 dwResult = RCC_UNSUPPORTED_AUTH_TYPE;
1460 break;
1461 }
1462
1463 if (dwResult == RCC_SUCCESS)
1464 {
1465 m_dwFlags |= CSF_AUTHENTICATED;
1466 sprintf(m_szUserName, "%s@%s", szLogin, IpToStr(m_dwHostAddr, szBuffer));
1467 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1468 msg.SetVariable(VID_USER_SYS_RIGHTS, m_dwSystemAccess);
1469 msg.SetVariable(VID_USER_ID, m_dwUserId);
1470 msg.SetVariable(VID_CHANGE_PASSWD_FLAG, (WORD)bChangePasswd);
1471 msg.SetVariable(VID_DBCONN_STATUS, (WORD)((g_dwFlags & AF_DB_CONNECTION_LOST) ? FALSE : TRUE));
1472 DebugPrintf(3, "User %s authenticated", m_szUserName);
1473 WriteAuditLog(AUDIT_SECURITY, TRUE, m_dwUserId, m_szWorkstation, 0,
1474 _T("User \"%s\" logged in (client info: %s)"), szLogin, m_szClientInfo);
1475 }
1476 else
1477 {
1478 msg.SetVariable(VID_RCC, dwResult);
1479 WriteAuditLog(AUDIT_SECURITY, FALSE, m_dwUserId, m_szWorkstation, 0,
1480 _T("User \"%s\" login failed with error code %d (client info: %s)"),
1481 szLogin, dwResult, m_szClientInfo);
1482 }
1483 }
1484 else
1485 {
1486 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1487 }
1488
1489 // Send response
1490 SendMessage(&msg);
1491}
1492
1493
1494//
1495// Send event configuration to client
1496//
1497
1498void ClientSession::SendEventDB(DWORD dwRqId)
1499{
1500 DB_ASYNC_RESULT hResult;
1501 CSCPMessage msg;
1502 char szBuffer[1024];
1503
1504 // Prepare response message
1505 msg.SetCode(CMD_REQUEST_COMPLETED);
1506 msg.SetId(dwRqId);
1507
1508 if (CheckSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB))
1509 {
1510 if (!(g_dwFlags & AF_DB_CONNECTION_LOST))
1511 {
1512 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1513 SendMessage(&msg);
1514 msg.DeleteAllVariables();
1515
1516 // Prepare data message
1517 msg.SetCode(CMD_EVENT_DB_RECORD);
1518 msg.SetId(dwRqId);
1519
1520 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_code,event_name,severity,flags,message,description FROM event_cfg");
1521 if (hResult != NULL)
1522 {
1523 while(DBFetch(hResult))
1524 {
1525 msg.SetVariable(VID_EVENT_CODE, DBGetFieldAsyncULong(hResult, 0));
1526 msg.SetVariable(VID_NAME, DBGetFieldAsync(hResult, 1, szBuffer, 1024));
1527 msg.SetVariable(VID_SEVERITY, DBGetFieldAsyncULong(hResult, 2));
1528 msg.SetVariable(VID_FLAGS, DBGetFieldAsyncULong(hResult, 3));
1529
1530 DBGetFieldAsync(hResult, 4, szBuffer, 1024);
1531 DecodeSQLString(szBuffer);
1532 msg.SetVariable(VID_MESSAGE, szBuffer);
1533
1534 DBGetFieldAsync(hResult, 5, szBuffer, 1024);
1535 DecodeSQLString(szBuffer);
1536 msg.SetVariable(VID_DESCRIPTION, szBuffer);
1537
1538 SendMessage(&msg);
1539 msg.DeleteAllVariables();
1540 }
1541 DBFreeAsyncResult(g_hCoreDB, hResult);
1542 }
1543
1544 // End-of-list indicator
1545 msg.SetVariable(VID_EVENT_CODE, (DWORD)0);
1546 }
1547 else
1548 {
1549 msg.SetVariable(VID_RCC, RCC_DB_CONNECTION_LOST);
1550 }
1551 }
1552 else
1553 {
1554 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1555 }
1556 SendMessage(&msg);
1557}
1558
1559
1560//
1561// Lock event configuration database
1562//
1563
1564void ClientSession::LockEventDB(DWORD dwRqId)
1565{
1566 CSCPMessage msg;
1567 char szBuffer[1024];
1568
1569 // Prepare response message
1570 msg.SetCode(CMD_REQUEST_COMPLETED);
1571 msg.SetId(dwRqId);
1572
1573 if (!CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
1574 {
1575 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1576 }
1577 else if (!LockComponent(CID_EVENT_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
1578 {
1579 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1580 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1581 }
1582 else
1583 {
1584 m_dwFlags |= CSF_EVENT_DB_LOCKED;
1585 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1586 WriteAuditLog(AUDIT_SYSCFG, TRUE, m_dwUserId, m_szWorkstation, 0,
1587 _T("Event configuration database locked"));
1588 }
1589 SendMessage(&msg);
1590}
1591
1592
1593//
1594// Close event configuration database
1595//
1596
1597void ClientSession::UnlockEventDB(DWORD dwRqId)
1598{
1599 CSCPMessage msg;
1600
1601 msg.SetCode(CMD_REQUEST_COMPLETED);
1602 msg.SetId(dwRqId);
1603
1604 if (m_dwFlags & CSF_EVENT_DB_LOCKED)
1605 {
1606 UnlockComponent(CID_EVENT_DB);
1607 m_dwFlags &= ~CSF_EVENT_DB_LOCKED;
1608 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1609 WriteAuditLog(AUDIT_SYSCFG, TRUE, m_dwUserId, m_szWorkstation, 0,
1610 _T("Event configuration database unlocked"));
1611 }
1612 else
1613 {
1614 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1615 }
1616 SendMessage(&msg);
1617}
1618
1619
1620//
1621// Update event template
1622//
1623
1624void ClientSession::SetEventInfo(CSCPMessage *pRequest)
1625{
1626 CSCPMessage msg;
1627
1628 // Prepare reply message
1629 msg.SetCode(CMD_REQUEST_COMPLETED);
1630 msg.SetId(pRequest->GetId());
1631
1632 // Check if we have event configuration database opened
1633 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1634 {
1635 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1636 }
1637 else
1638 {
1639 // Check access rights
1640 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
1641 {
1642 char szQuery[4096], szName[MAX_EVENT_NAME];
1643 DWORD dwEventCode;
1644 BOOL bEventExist = FALSE;
1645 DB_RESULT hResult;
1646
1647 // Check if event with specific code exists
1648 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
1649 sprintf(szQuery, "SELECT event_code FROM event_cfg WHERE event_code=%d", dwEventCode);
1650 hResult = DBSelect(g_hCoreDB, szQuery);
1651 if (hResult != NULL)
1652 {
1653 if (DBGetNumRows(hResult) > 0)
1654 bEventExist = TRUE;
1655 DBFreeResult(hResult);
1656 }
1657
1658 // Check that we are not trying to create event below 100000
1659 if (bEventExist || (dwEventCode >= FIRST_USER_EVENT_ID))
1660 {
1661 // Prepare and execute SQL query
1662 pRequest->GetVariableStr(VID_NAME, szName, MAX_EVENT_NAME);
1663 if (IsValidObjectName(szName))
1664 {
1665 char szMessage[MAX_DB_STRING], *pszDescription, *pszEscMsg, *pszEscDescr;
1666
1667 pRequest->GetVariableStr(VID_MESSAGE, szMessage, MAX_DB_STRING);
1668 pszEscMsg = EncodeSQLString(szMessage);
1669
1670 pszDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
1671 pszEscDescr = EncodeSQLString(pszDescription);
1672 safe_free(pszDescription);
1673
1674 if (bEventExist)
1675 {
1676 sprintf(szQuery, "UPDATE event_cfg SET event_name='%s',severity=%d,flags=%d,message='%s',description='%s' WHERE event_code=%d",
1677 szName, pRequest->GetVariableLong(VID_SEVERITY), pRequest->GetVariableLong(VID_FLAGS),
1678 pszEscMsg, pszEscDescr, dwEventCode);
1679 }
1680 else
1681 {
1682 sprintf(szQuery, "INSERT INTO event_cfg (event_code,event_name,severity,flags,"
1683 "message,description) VALUES (%d,'%s',%d,%d,'%s','%s')",
1684 dwEventCode, szName, pRequest->GetVariableLong(VID_SEVERITY),
1685 pRequest->GetVariableLong(VID_FLAGS), pszEscMsg, pszEscDescr);
1686 }
1687
1688 free(pszEscMsg);
1689 free(pszEscDescr);
1690
1691 if (DBQuery(g_hCoreDB, szQuery))
1692 {
1693 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1694 ReloadEvents();
1695 NotifyClientSessions(NX_NOTIFY_EVENTDB_CHANGED, 0);
1696 }
1697 else
1698 {
1699 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1700 }
1701 }
1702 else
1703 {
1704 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1705 }
1706 }
1707 else
1708 {
1709 msg.SetVariable(VID_RCC, RCC_INVALID_EVENT_CODE);
1710 }
1711 }
1712 else
1713 {
1714 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1715 }
1716 }
1717
1718 // Send response
1719 SendMessage(&msg);
1720}
1721
1722
1723//
1724// Delete event template
1725//
1726
1727void ClientSession::DeleteEventTemplate(CSCPMessage *pRequest)
1728{
1729 CSCPMessage msg;
1730 DWORD dwEventCode;
1731
1732 // Prepare reply message
1733 msg.SetCode(CMD_REQUEST_COMPLETED);
1734 msg.SetId(pRequest->GetId());
1735
1736 // Check if we have event configuration database opened
1737 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1738 {
1739 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1740 }
1741 else
1742 {
1743 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
1744
1745 // Check access rights
1746 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) && (dwEventCode >= FIRST_USER_EVENT_ID))
1747 {
1748 TCHAR szQuery[256];
1749
1750 _stprintf(szQuery, _T("DELETE FROM event_cfg WHERE event_code=%d"), dwEventCode);
1751 if (DBQuery(g_hCoreDB, szQuery))
1752 {
1753 DeleteEventTemplateFromList(dwEventCode);
1754 NotifyClientSessions(NX_NOTIFY_EVENTDB_CHANGED, 0);
1755 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1756
1757 WriteAuditLog(AUDIT_SYSCFG, TRUE, m_dwUserId, m_szWorkstation, 0,
1758 _T("Event template %d deleted"), dwEventCode);
1759 }
1760 else
1761 {
1762 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1763 }
1764 }
1765 else
1766 {
1767 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1768 }
1769 }
1770
1771 // Send response
1772 SendMessage(&msg);
1773}
1774
1775
1776//
1777// Generate ID for new event template
1778//
1779
1780void ClientSession::GenerateEventCode(DWORD dwRqId)
1781{
1782 CSCPMessage msg;
1783
1784 // Prepare reply message
1785 msg.SetCode(CMD_REQUEST_COMPLETED);
1786 msg.SetId(dwRqId);
1787
1788 // Check if we have event configuration database opened
1789 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
1790 {
1791 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1792 }
1793 else
1794 {
1795 // Check access rights
1796 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
1797 {
1798 msg.SetVariable(VID_EVENT_CODE, CreateUniqueId(IDG_EVENT));
1799 }
1800 else
1801 {
1802 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1803 }
1804 }
1805
1806 // Send response
1807 SendMessage(&msg);
1808}
1809
1810
1811//
1812// Send all objects to client
1813//
1814
1815void ClientSession::SendAllObjects(CSCPMessage *pRequest)
1816{
1817 DWORD i, dwTimeStamp;
1818 CSCPMessage msg;
1819
1820 // Send confirmation message
1821 msg.SetCode(CMD_REQUEST_COMPLETED);
1822 msg.SetId(pRequest->GetId());
1823 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1824 SendMessage(&msg);
1825 msg.DeleteAllVariables();
1826
1827 // Change "sync comments" flag
1828 if (pRequest->GetVariableShort(VID_SYNC_COMMENTS))
1829 m_dwFlags |= CSF_SYNC_OBJECT_COMMENTS;
1830 else
1831 m_dwFlags &= ~CSF_SYNC_OBJECT_COMMENTS;
1832
1833 // Get client's last known time stamp
1834 dwTimeStamp = pRequest->GetVariableLong(VID_TIMESTAMP);
1835
1836 MutexLock(m_mutexSendObjects, INFINITE);
1837
1838 // Prepare message
1839 msg.SetCode(CMD_OBJECT);
1840
1841 // Send objects, one per message
1842 RWLockReadLock(g_rwlockIdIndex, INFINITE);
1843 for(i = 0; i < g_dwIdIndexSize; i++)
1844 if ((((NetObj *)g_pIndexById[i].pObject)->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ)) &&
1845 (((NetObj *)g_pIndexById[i].pObject)->TimeStamp() >= dwTimeStamp) &&
1846 (!(((NetObj *)g_pIndexById[i].pObject)->IsHidden())))
1847 {
1848 ((NetObj *)g_pIndexById[i].pObject)->CreateMessage(&msg);
1849 if (m_dwFlags & CSF_SYNC_OBJECT_COMMENTS)
1850 ((NetObj *)g_pIndexById[i].pObject)->CommentsToMessage(&msg);
1851 SendMessage(&msg);
1852 msg.DeleteAllVariables();
1853 }
1854 RWLockUnlock(g_rwlockIdIndex);
1855
1856 // Send end of list notification
1857 msg.SetCode(CMD_OBJECT_LIST_END);
1858 SendMessage(&msg);
1859
1860 MutexUnlock(m_mutexSendObjects);
1861}
1862
1863
1864//
1865// Send event log records to client
1866//
1867
1868void ClientSession::SendEventLog(CSCPMessage *pRequest)
1869{
1870 CSCPMessage msg;
1871 DB_ASYNC_RESULT hResult = NULL;
1872 DB_RESULT hTempResult;
1873 DWORD dwRqId, dwMaxRecords, dwNumRows, dwId;
1874 TCHAR szQuery[1024], szBuffer[1024];
1875 WORD wRecOrder;
1876
1877 dwRqId = pRequest->GetId();
1878 dwMaxRecords = pRequest->GetVariableLong(VID_MAX_RECORDS);
28f5b9a4 1879 wRecOrder = ((g_nDBSyntax == DB_SYNTAX_MSSQL) || (g_nDBSyntax == DB_SYNTAX_ORACLE)) ? RECORD_ORDER_REVERSED : RECORD_ORDER_NORMAL;
5039dede
AK
1880
1881 // Prepare confirmation message
1882 msg.SetCode(CMD_REQUEST_COMPLETED);
1883 msg.SetId(dwRqId);
1884
1885 MutexLock(m_mutexSendEvents, INFINITE);
1886
1887 // Retrieve events from database
28f5b9a4 1888 switch(g_nDBSyntax)
5039dede
AK
1889 {
1890 case DB_SYNTAX_MYSQL:
1891 case DB_SYNTAX_PGSQL:
1892 case DB_SYNTAX_SQLITE:
1893 hTempResult = DBSelect(g_hCoreDB, _T("SELECT count(*) FROM event_log"));
1894 if (hTempResult != NULL)
1895 {
1896 if (DBGetNumRows(hTempResult) > 0)
1897 {
1898 dwNumRows = DBGetFieldULong(hTempResult, 0, 0);
1899 }
1900 else
1901 {
1902 dwNumRows = 0;
1903 }
1904 DBFreeResult(hTempResult);
1905 }
1906 _sntprintf(szQuery, 1024,
1907 _T("SELECT event_id,event_code,event_timestamp,event_source,")
1908 _T("event_severity,event_message,user_tag FROM event_log ")
1909 _T("ORDER BY event_id LIMIT %u OFFSET %u"),
1910 dwMaxRecords, dwNumRows - min(dwNumRows, dwMaxRecords));
1911 break;
1912 case DB_SYNTAX_MSSQL:
1913 _sntprintf(szQuery, 1024,
1914 _T("SELECT TOP %u event_id,event_code,event_timestamp,event_source,")
1915 _T("event_severity,event_message,user_tag FROM event_log ")
1916 _T("ORDER BY event_id DESC"), dwMaxRecords);
1917 break;
1918 case DB_SYNTAX_ORACLE:
1919 _sntprintf(szQuery, 1024,
1920 _T("SELECT event_id,event_code,event_timestamp,event_source,")
1921 _T("event_severity,event_message,user_tag FROM event_log ")
1922 _T("WHERE ROWNUM <= %u ORDER BY event_id DESC"), dwMaxRecords);
1923 break;
1924 default:
1925 szQuery[0] = 0;
1926 break;
1927 }
1928 hResult = DBAsyncSelect(g_hCoreDB, szQuery);
1929 if (hResult != NULL)
1930 {
1931 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1932 SendMessage(&msg);
1933 msg.DeleteAllVariables();
1934 msg.SetCode(CMD_EVENTLOG_RECORDS);
1935
1936 for(dwId = VID_EVENTLOG_MSG_BASE, dwNumRows = 0; DBFetch(hResult); dwNumRows++)
1937 {
1938 if (dwNumRows == 10)
1939 {
1940 msg.SetVariable(VID_NUM_RECORDS, dwNumRows);
1941 msg.SetVariable(VID_RECORDS_ORDER, wRecOrder);
1942 SendMessage(&msg);
1943 msg.DeleteAllVariables();
1944 dwNumRows = 0;
1945 dwId = VID_EVENTLOG_MSG_BASE;
1946 }
1947 msg.SetVariable(dwId++, DBGetFieldAsyncUInt64(hResult, 0));
1948 msg.SetVariable(dwId++, DBGetFieldAsyncULong(hResult, 1));
1949 msg.SetVariable(dwId++, DBGetFieldAsyncULong(hResult, 2));
1950 msg.SetVariable(dwId++, DBGetFieldAsyncULong(hResult, 3));
1951 msg.SetVariable(dwId++, (WORD)DBGetFieldAsyncLong(hResult, 4));
1952 DBGetFieldAsync(hResult, 5, szBuffer, 1024);
1953 DecodeSQLString(szBuffer);
1954 msg.SetVariable(dwId++, szBuffer);
1955 DBGetFieldAsync(hResult, 6, szBuffer, 1024);
1956 DecodeSQLString(szBuffer);
1957 msg.SetVariable(dwId++, szBuffer);
1958 }
1959 DBFreeAsyncResult(g_hCoreDB, hResult);
1960
1961 // Send remaining records with End-Of-Sequence notification
1962 msg.SetVariable(VID_NUM_RECORDS, dwNumRows);
1963 msg.SetVariable(VID_RECORDS_ORDER, wRecOrder);
1964 msg.SetEndOfSequence();
1965 SendMessage(&msg);
1966 }
1967 else
1968 {
1969 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
1970 SendMessage(&msg);
1971 }
1972
1973 MutexUnlock(m_mutexSendEvents);
1974}
1975
1976
1977//
1978// Send all configuration variables to client
1979//
1980
1981void ClientSession::SendAllConfigVars(DWORD dwRqId)
1982{
1983 DWORD i, dwId, dwNumRecords;
1984 CSCPMessage msg;
1985 DB_RESULT hResult;
1986 TCHAR szBuffer[MAX_DB_STRING];
1987
1988 // Prepare message
1989 msg.SetCode(CMD_REQUEST_COMPLETED);
1990 msg.SetId(dwRqId);
1991
1992 // Check user rights
1993 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
1994 {
1995 // Retrieve configuration variables from database
1996 hResult = DBSelect(g_hCoreDB, "SELECT var_name,var_value,need_server_restart FROM config WHERE is_visible=1");
1997 if (hResult != NULL)
1998 {
1999 // Send events, one per message
2000 dwNumRecords = DBGetNumRows(hResult);
2001 msg.SetVariable(VID_NUM_VARIABLES, dwNumRecords);
2002 for(i = 0, dwId = VID_VARLIST_BASE; i < dwNumRecords; i++)
2003 {
2004 msg.SetVariable(dwId++, DBGetField(hResult, i, 0, szBuffer, MAX_DB_STRING));
2005 DBGetField(hResult, i, 1, szBuffer, MAX_DB_STRING);
2006 DecodeSQLString(szBuffer);
2007 msg.SetVariable(dwId++, szBuffer);
2008 msg.SetVariable(dwId++, (WORD)DBGetFieldLong(hResult, i, 2));
2009 }
2010 DBFreeResult(hResult);
2011 }
2012 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2013 }
2014 else
2015 {
2016 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2017 }
2018
2019 // Send response
2020 SendMessage(&msg);
2021}
2022
2023
2024//
2025// Set configuration variable's value
2026//
2027
2028void ClientSession::SetConfigVariable(CSCPMessage *pRequest)
2029{
2030 CSCPMessage msg;
2031 TCHAR szName[MAX_OBJECT_NAME], szValue[MAX_DB_STRING];
2032
2033 // Prepare response message
2034 msg.SetCode(CMD_REQUEST_COMPLETED);
2035 msg.SetId(pRequest->GetId());
2036
2037 // Check user rights
2038 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
2039 {
2040 pRequest->GetVariableStr(VID_NAME, szName, MAX_OBJECT_NAME);
2041 pRequest->GetVariableStr(VID_VALUE, szValue, MAX_DB_STRING);
2042 if (ConfigWriteStr(szName, szValue, TRUE))
2043 {
2044 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2045 WriteAuditLog(AUDIT_SYSCFG, TRUE, m_dwUserId, m_szWorkstation, 0,
2046 _T("Server configuration variable \"%s\" set to \"%s\""), szName, szValue);
2047 }
2048 else
2049 {
2050 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
2051 }
2052 }
2053 else
2054 {
2055 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2056 }
2057
2058 // Send response
2059 SendMessage(&msg);
2060}
2061
2062
2063//
2064// Delete configuration variable
2065//
2066
2067void ClientSession::DeleteConfigVariable(CSCPMessage *pRequest)
2068{
2069 CSCPMessage msg;
2070 TCHAR szName[MAX_OBJECT_NAME], szQuery[1024];
2071
2072 // Prepare response message
2073 msg.SetCode(CMD_REQUEST_COMPLETED);
2074 msg.SetId(pRequest->GetId());
2075
2076 // Check user rights
2077 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
2078 {
2079 pRequest->GetVariableStr(VID_NAME, szName, MAX_OBJECT_NAME);
2080 _sntprintf(szQuery, 1024, _T("DELETE FROM config WHERE var_name='%s'"), szName);
2081 if (DBQuery(g_hCoreDB, szQuery))
2082 {
2083 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2084 WriteAuditLog(AUDIT_SYSCFG, TRUE, m_dwUserId, m_szWorkstation, 0,
2085 _T("Server configuration variable \"%s\" deleted"), szName);
2086 }
2087 else
2088 {
2089 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
2090 }
2091 }
2092 else
2093 {
2094 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2095 }
2096
2097 // Send response
2098 SendMessage(&msg);
2099}
2100
2101
2102//
2103// Set configuration clob
2104//
2105
2106void ClientSession::SetConfigCLOB(CSCPMessage *pRequest)
2107{
2108 CSCPMessage msg;
2109 TCHAR name[MAX_OBJECT_NAME], *value;
2110
2111 msg.SetId(pRequest->GetId());
2112 msg.SetCode(CMD_REQUEST_COMPLETED);
2113
2114 if (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG)
2115 {
2116 pRequest->GetVariableStr(VID_NAME, name, MAX_OBJECT_NAME);
2117 value = pRequest->GetVariableStr(VID_VALUE);
2118 if (value != NULL)
2119 {
2120 msg.SetVariable(VID_RCC, ConfigWriteCLOB(name, value, TRUE) ? RCC_SUCCESS : RCC_DB_FAILURE);
2121 free(value);
2122 }
2123 else
2124 {
2125 msg.SetVariable(VID_RCC, RCC_INVALID_REQUEST);
2126 }
2127 }
2128 else
2129 {
2130 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2131 }
2132
2133 SendMessage(&msg);
2134}
2135
2136
2137//
2138// Get value of configuration clob
2139//
2140
2141void ClientSession::GetConfigCLOB(CSCPMessage *pRequest)
2142{
2143 CSCPMessage msg;
2144 TCHAR name[MAX_OBJECT_NAME], *value;
2145
2146 msg.SetId(pRequest->GetId());
2147 msg.SetCode(CMD_REQUEST_COMPLETED);
2148
2149 if (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG)
2150 {
2151 pRequest->GetVariableStr(VID_NAME, name, MAX_OBJECT_NAME);
2152 value = ConfigReadCLOB(name, NULL);
2153 if (value != NULL)
2154 {
2155 msg.SetVariable(VID_VALUE, value);
2156 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2157 free(value);
2158 }
2159 else
2160 {
2161 msg.SetVariable(VID_RCC, RCC_UNKNOWN_VARIABLE);
2162 }
2163 }
2164 else
2165 {
2166 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2167 }
2168
2169 SendMessage(&msg);
2170}
2171
2172
2173//
2174// Close session forcibly
2175//
2176
2177void ClientSession::Kill(void)
2178{
2179 // We shutdown socket connection, which will cause
2180 // read thread to stop, and other threads will follow
2181 shutdown(m_hSocket, 2);
2182}
2183
2184
2185//
2186// Handler for new events
2187//
2188
2189void ClientSession::OnNewEvent(Event *pEvent)
2190{
2191 UPDATE_INFO *pUpdate;
2192 CSCPMessage *msg;
2193
2194 if (IsAuthenticated() && (m_dwActiveChannels & NXC_CHANNEL_EVENTS))
2195 {
2196 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2197 pUpdate->dwCategory = INFO_CAT_EVENT;
2198 msg = new CSCPMessage;
2199 msg->SetCode(CMD_EVENTLOG_RECORDS);
2200 pEvent->PrepareMessage(msg);
2201 pUpdate->pData = msg;
2202 m_pUpdateQueue->Put(pUpdate);
2203 }
2204}
2205
2206
2207//
2208// Handler for object changes
2209//
2210
2211void ClientSession::OnObjectChange(NetObj *pObject)
2212{
2213 UPDATE_INFO *pUpdate;
2214
2215 if (IsAuthenticated() && (m_dwActiveChannels & NXC_CHANNEL_OBJECTS))
2216 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2217 {
2218 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2219 pUpdate->dwCategory = INFO_CAT_OBJECT_CHANGE;
2220 pUpdate->pData = pObject;
2221 pObject->IncRefCount();
2222 m_pUpdateQueue->Put(pUpdate);
2223 }
2224}
2225
2226
2227//
2228// Send notification message to server
2229//
2230
2231void ClientSession::Notify(DWORD dwCode, DWORD dwData)
2232{
2233 CSCPMessage msg;
2234
2235 msg.SetCode(CMD_NOTIFY);
2236 msg.SetVariable(VID_NOTIFICATION_CODE, dwCode);
2237 msg.SetVariable(VID_NOTIFICATION_DATA, dwData);
2238 SendMessage(&msg);
2239}
2240
2241
2242//
2243// Modify object
2244//
2245
2246void ClientSession::ModifyObject(CSCPMessage *pRequest)
2247{
2248 DWORD dwObjectId, dwResult = RCC_SUCCESS;
2249 NetObj *pObject;
2250 CSCPMessage msg;
2251
2252 // Prepare reply message
2253 msg.SetCode(CMD_REQUEST_COMPLETED);
2254 msg.SetId(pRequest->GetId());
2255
2256 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2257 pObject = FindObjectById(dwObjectId);
2258 if (pObject != NULL)
2259 {
2260 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2261 {
2262 // If user attempts to change object's ACL, check
2263 // if he has OBJECT_ACCESS_ACL permission
2264 if (pRequest->IsVariableExist(VID_ACL_SIZE))
2265 if (!pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACL))
2266 dwResult = RCC_ACCESS_DENIED;
2267
2268 // If allowed, change object and set completion code
2269 if (dwResult != RCC_ACCESS_DENIED)
2270 dwResult = pObject->ModifyFromMessage(pRequest);
2271 msg.SetVariable(VID_RCC, dwResult);
2272
2273 if (dwResult == RCC_SUCCESS)
2274 {
2275 WriteAuditLog(AUDIT_OBJECTS, TRUE, m_dwUserId, m_szWorkstation, dwObjectId,
2276 _T("Object modified from client"));
2277 }
2278 else
2279 {
2280 WriteAuditLog(AUDIT_OBJECTS, FALSE, m_dwUserId, m_szWorkstation, dwObjectId,
2281 _T("Failed to modify object from client - error %d"), dwResult);
2282 }
2283 }
2284 else
2285 {
2286 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2287 WriteAuditLog(AUDIT_OBJECTS, FALSE, m_dwUserId, m_szWorkstation, dwObjectId,
2288 _T("Failed to modify object from client - access denied"), dwResult);
2289 }
2290 }
2291 else
2292 {
2293 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2294 }
2295
2296 // Send response
2297 SendMessage(&msg);
2298}
2299
2300
2301//
2302// Send users database to client
2303//
2304
2305void ClientSession::SendUserDB(DWORD dwRqId)
2306{
2307 CSCPMessage msg;
2308 DWORD i;
2309
2310 // Prepare response message
2311 msg.SetCode(CMD_REQUEST_COMPLETED);
2312 msg.SetId(dwRqId);
2313 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2314 SendMessage(&msg);
2315
2316 // Send users
2317 msg.SetCode(CMD_USER_DATA);
2318 for(i = 0; i < g_dwNumUsers; i++)
2319 {
2320 FillUserInfoMessage(&msg, &g_pUserList[i]);
2321 SendMessage(&msg);
2322 msg.DeleteAllVariables();
2323 }
2324
2325 // Send groups
2326 msg.SetCode(CMD_GROUP_DATA);
2327 for(i = 0; i < g_dwNumGroups; i++)
2328 {
2329 FillGroupInfoMessage(&msg, &g_pGroupList[i]);
2330 SendMessage(&msg);
2331 msg.DeleteAllVariables();
2332 }
2333
2334 // Send end-of-database notification
2335 msg.SetCode(CMD_USER_DB_EOF);
2336 SendMessage(&msg);
2337}
2338
2339
2340//
2341// Create new user
2342//
2343
2344void ClientSession::CreateUser(CSCPMessage *pRequest)
2345{
2346 CSCPMessage msg;
2347
2348 // Prepare response message
2349 msg.SetCode(CMD_REQUEST_COMPLETED);
2350 msg.SetId(pRequest->GetId());
2351
2352 // Check user rights
2353 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2354 {
2355 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2356 }
2357 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2358 {
2359 // User database have to be locked before any
2360 // changes to user database can be made
2361 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2362 }
2363 else
2364 {
2365 DWORD dwResult, dwUserId;
2366 BOOL bIsGroup;
2367 char szUserName[MAX_USER_NAME];
2368
2369 pRequest->GetVariableStr(VID_USER_NAME, szUserName, MAX_USER_NAME);
2370 if (IsValidObjectName(szUserName))
2371 {
2372 bIsGroup = pRequest->GetVariableShort(VID_IS_GROUP);
2373 dwResult = CreateNewUser(szUserName, bIsGroup, &dwUserId);
2374 msg.SetVariable(VID_RCC, dwResult);
2375 if (dwResult == RCC_SUCCESS)
2376 msg.SetVariable(VID_USER_ID, dwUserId); // Send id of new user to client
2377 }
2378 else
2379 {
2380 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
2381 }
2382 }
2383
2384 // Send response
2385 SendMessage(&msg);
2386}
2387
2388
2389//
2390// Update existing user's data
2391//
2392
2393void ClientSession::UpdateUser(CSCPMessage *pRequest)
2394{
2395 CSCPMessage msg;
2396
2397 // Prepare response message
2398 msg.SetCode(CMD_REQUEST_COMPLETED);
2399 msg.SetId(pRequest->GetId());
2400
2401 // Check user rights
2402 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2403 {
2404 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2405 }
2406 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2407 {
2408 // User database have to be locked before any
2409 // changes to user database can be made
2410 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2411 }
2412 else
2413 {
2414 DWORD dwUserId, dwResult;
2415
2416 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
2417 if (dwUserId & GROUP_FLAG)
2418 {
2419 NETXMS_USER_GROUP group;
2420 DWORD i, dwId;
2421
2422 group.dwId = dwUserId;
2423 pRequest->GetVariableStr(VID_USER_DESCRIPTION, group.szDescription, MAX_USER_DESCR);
2424 pRequest->GetVariableStr(VID_USER_NAME, group.szName, MAX_USER_NAME);
2425 group.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
2426 group.dwSystemRights = pRequest->GetVariableLong(VID_USER_SYS_RIGHTS);
2427 group.dwNumMembers = pRequest->GetVariableLong(VID_NUM_MEMBERS);
2428 group.pMembers = (DWORD *)malloc(sizeof(DWORD) * group.dwNumMembers);
2429 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < group.dwNumMembers; i++, dwId++)
2430 group.pMembers[i] = pRequest->GetVariableLong(dwId);
2431 dwResult = ModifyGroup(&group);
2432 safe_free(group.pMembers);
2433 }
2434 else
2435 {
2436 NETXMS_USER user;
2437
2438 user.dwId = dwUserId;
2439 pRequest->GetVariableStr(VID_USER_DESCRIPTION, user.szDescription, MAX_USER_DESCR);
2440 pRequest->GetVariableStr(VID_USER_FULL_NAME, user.szFullName, MAX_USER_FULLNAME);
2441 pRequest->GetVariableStr(VID_USER_NAME, user.szName, MAX_USER_NAME);
2442 user.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
2443 user.dwSystemRights = pRequest->GetVariableLong(VID_USER_SYS_RIGHTS);
2444 user.nAuthMethod = pRequest->GetVariableShort(VID_AUTH_METHOD);
2445 user.nCertMappingMethod = pRequest->GetVariableShort(VID_CERT_MAPPING_METHOD);
2446 user.pszCertMappingData = pRequest->GetVariableStr(VID_CERT_MAPPING_DATA);
2447 dwResult = ModifyUser(&user);
2448 safe_free(user.pszCertMappingData);
2449 }
2450 msg.SetVariable(VID_RCC, dwResult);
2451 }
2452
2453 // Send response
2454 SendMessage(&msg);
2455}
2456
2457
2458//
2459// Delete user
2460//
2461
2462void ClientSession::DeleteUser(CSCPMessage *pRequest)
2463{
2464 CSCPMessage msg;
2465 DWORD dwUserId;
2466
2467 // Prepare response message
2468 msg.SetCode(CMD_REQUEST_COMPLETED);
2469 msg.SetId(pRequest->GetId());
2470
2471 // Check user rights
2472 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2473 {
2474 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2475 }
2476 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2477 {
2478 // User database have to be locked before any
2479 // changes to user database can be made
2480 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2481 }
2482 else
2483 {
2484 // Get Id of user to be deleted
2485 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
2486
2487 if (dwUserId != 0)
2488 {
2489 DWORD dwResult;
2490
2491 dwResult = DeleteUserFromDB(dwUserId);
2492 msg.SetVariable(VID_RCC, dwResult);
2493 }
2494 else
2495 {
2496 // Nobody can delete system administrator account
2497 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2498 }
2499 }
2500
2501 // Send response
2502 SendMessage(&msg);
2503}
2504
2505
2506//
2507// Lock/unlock user database
2508//
2509
2510void ClientSession::LockUserDB(DWORD dwRqId, BOOL bLock)
2511{
2512 CSCPMessage msg;
2513 char szBuffer[256];
2514
2515 // Prepare response message
2516 msg.SetCode(CMD_REQUEST_COMPLETED);
2517 msg.SetId(dwRqId);
2518
2519 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
2520 {
2521 if (bLock)
2522 {
2523 if (!LockComponent(CID_USER_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
2524 {
2525 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2526 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2527 }
2528 else
2529 {
2530 m_dwFlags |= CSF_USER_DB_LOCKED;
2531 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2532 }
2533 }
2534 else
2535 {
2536 if (m_dwFlags & CSF_USER_DB_LOCKED)
2537 {
2538 UnlockComponent(CID_USER_DB);
2539 m_dwFlags &= ~CSF_USER_DB_LOCKED;
2540 }
2541 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2542 }
2543 }
2544 else
2545 {
2546 // Current user has no rights for user account management
2547 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2548 }
2549
2550 // Send response
2551 SendMessage(&msg);
2552}
2553
2554
2555//
2556// Notify client on user database update
2557//
2558
2559void ClientSession::OnUserDBUpdate(int iCode, DWORD dwUserId, NETXMS_USER *pUser, NETXMS_USER_GROUP *pGroup)
2560{
2561 CSCPMessage msg;
2562
2563 if (IsAuthenticated())
2564 {
2565 msg.SetCode(CMD_USER_DB_UPDATE);
2566 msg.SetId(0);
2567 msg.SetVariable(VID_UPDATE_TYPE, (WORD)iCode);
2568
2569 switch(iCode)
2570 {
2571 case USER_DB_CREATE:
2572 msg.SetVariable(VID_USER_ID, dwUserId);
2573 if (dwUserId & GROUP_FLAG)
2574 msg.SetVariable(VID_USER_NAME, pGroup->szName);
2575 else
2576 msg.SetVariable(VID_USER_NAME, pUser->szName);
2577 break;
2578 case USER_DB_MODIFY:
2579 if (dwUserId & GROUP_FLAG)
2580 FillGroupInfoMessage(&msg, pGroup);
2581 else
2582 FillUserInfoMessage(&msg, pUser);
2583 break;
2584 default:
2585 msg.SetVariable(VID_USER_ID, dwUserId);
2586 break;
2587 }
2588
2589 SendMessage(&msg);
2590 }
2591}
2592
2593
2594//
2595// Change management status for the object
2596//
2597
2598void ClientSession::ChangeObjectMgmtStatus(CSCPMessage *pRequest)
2599{
2600 CSCPMessage msg;
2601 DWORD dwObjectId;
2602 NetObj *pObject;
2603
2604 // Prepare response message
2605 msg.SetCode(CMD_REQUEST_COMPLETED);
2606 msg.SetId(pRequest->GetId());
2607
2608 // Get object id and check access rights
2609 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2610 pObject = FindObjectById(dwObjectId);
2611 if (pObject != NULL)
2612 {
2613 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2614 {
2615 if ((pObject->Type() != OBJECT_TEMPLATE) &&
2616 (pObject->Type() != OBJECT_TEMPLATEGROUP) &&
2617 (pObject->Type() != OBJECT_TEMPLATEROOT))
2618 {
2619 BOOL bIsManaged;
2620
2621 bIsManaged = (BOOL)pRequest->GetVariableShort(VID_MGMT_STATUS);
2622 pObject->SetMgmtStatus(bIsManaged);
2623 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2624 }
2625 else
2626 {
2627 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2628 }
2629 }
2630 else
2631 {
2632 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2633 }
2634 }
2635 else
2636 {
2637 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2638 }
2639
2640 // Send response
2641 SendMessage(&msg);
2642}
2643
2644
2645//
2646// Set user's password
2647//
2648
2649void ClientSession::SetPassword(CSCPMessage *pRequest)
2650{
2651 CSCPMessage msg;
2652 DWORD dwUserId;
2653
2654 // Prepare response message
2655 msg.SetCode(CMD_REQUEST_COMPLETED);
2656 msg.SetId(pRequest->GetId());
2657
2658 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
2659
2660 if (((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS) &&
2661 !((dwUserId == 0) && (m_dwUserId != 0))) || // Only administrator can change password for UID 0
2662 (dwUserId == m_dwUserId)) // User can change password for itself
2663 {
2664 DWORD dwResult;
2665 BYTE szPassword[SHA1_DIGEST_SIZE];
2666
2667 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
2668 dwResult = SetUserPassword(dwUserId, szPassword, dwUserId == m_dwUserId);
2669 msg.SetVariable(VID_RCC, dwResult);
2670 }
2671 else
2672 {
2673 // Current user has no rights to change password for specific user
2674 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2675 }
2676
2677 // Send response
2678 SendMessage(&msg);
2679}
2680
2681
2682//
2683// Send node's DCIs to client and lock data collection settings
2684//
2685
2686void ClientSession::OpenNodeDCIList(CSCPMessage *pRequest)
2687{
2688 CSCPMessage msg;
2689 DWORD dwObjectId;
2690 NetObj *pObject;
2691 BOOL bSuccess = FALSE;
2692 TCHAR szLockInfo[MAX_SESSION_NAME];
2693
2694 // Prepare response message
2695 msg.SetCode(CMD_REQUEST_COMPLETED);
2696 msg.SetId(pRequest->GetId());
2697
2698 // Get node id and check object class and access rights
2699 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2700 pObject = FindObjectById(dwObjectId);
2701 if (pObject != NULL)
2702 {
2703 if ((pObject->Type() == OBJECT_NODE) ||
2704 (pObject->Type() == OBJECT_CLUSTER) ||
2705 (pObject->Type() == OBJECT_TEMPLATE))
2706 {
2707 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2708 {
2709 // Try to lock DCI list
2710 if (((Template *)pObject)->LockDCIList(m_dwIndex, m_szUserName, szLockInfo))
2711 {
2712 bSuccess = TRUE;
2713 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2714
2715 // Modify list of open nodes DCI lists
2716 m_pOpenDCIList = (DWORD *)realloc(m_pOpenDCIList, sizeof(DWORD) * (m_dwOpenDCIListSize + 1));
2717 m_pOpenDCIList[m_dwOpenDCIListSize] = dwObjectId;
2718 m_dwOpenDCIListSize++;
2719 }
2720 else
2721 {
2722 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2723 msg.SetVariable(VID_LOCKED_BY, szLockInfo);
2724 }
2725 }
2726 else
2727 {
2728 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2729 }
2730 }
2731 else
2732 {
2733 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2734 }
2735 }
2736 else
2737 {
2738 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2739 }
2740
2741 // Send response
2742 SendMessage(&msg);
2743
2744 // If DCI list was successfully locked, send it to client
2745 if (bSuccess)
2746 ((Template *)pObject)->SendItemsToClient(this, pRequest->GetId());
2747}
2748
2749
2750//
2751// Unlock node's data collection settings
2752//
2753
2754void ClientSession::CloseNodeDCIList(CSCPMessage *pRequest)
2755{
2756 CSCPMessage msg;
2757 DWORD dwObjectId;
2758 NetObj *pObject;
2759
2760 // Prepare response message
2761 msg.SetCode(CMD_REQUEST_COMPLETED);
2762 msg.SetId(pRequest->GetId());
2763
2764 // Get node id and check object class and access rights
2765 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2766 pObject = FindObjectById(dwObjectId);
2767 if (pObject != NULL)
2768 {
2769 if ((pObject->Type() == OBJECT_NODE) ||
2770 (pObject->Type() == OBJECT_CLUSTER) ||
2771 (pObject->Type() == OBJECT_TEMPLATE))
2772 {
2773 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2774 {
2775 BOOL bSuccess;
2776
2777 // Try to unlock DCI list
2778 bSuccess = ((Template *)pObject)->UnlockDCIList(m_dwIndex);
2779 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_OUT_OF_STATE_REQUEST);
2780
2781 // Modify list of open nodes DCI lists
2782 if (bSuccess)
2783 {
2784 DWORD i;
2785
2786 for(i = 0; i < m_dwOpenDCIListSize; i++)
2787 if (m_pOpenDCIList[i] == dwObjectId)
2788 {
2789 m_dwOpenDCIListSize--;
2790 memmove(&m_pOpenDCIList[i], &m_pOpenDCIList[i + 1],
2791 sizeof(DWORD) * (m_dwOpenDCIListSize - i));
2792 break;
2793 }
2794 }
2795
2796 // Queue template update
2797 if ((pObject->Type() == OBJECT_TEMPLATE) ||
2798 (pObject->Type() == OBJECT_CLUSTER))
2799 ((Template *)pObject)->QueueUpdate();
2800 }
2801 else
2802 {
2803 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2804 }
2805 }
2806 else
2807 {
2808 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2809 }
2810 }
2811 else
2812 {
2813 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2814 }
2815
2816 // Send response
2817 SendMessage(&msg);
2818}
2819
2820
2821//
2822// Create, modify, or delete data collection item for node
2823//
2824
2825void ClientSession::ModifyNodeDCI(CSCPMessage *pRequest)
2826{
2827 CSCPMessage msg;
2828 DWORD dwObjectId;
2829 NetObj *pObject;
2830
2831 // Prepare response message
2832 msg.SetCode(CMD_REQUEST_COMPLETED);
2833 msg.SetId(pRequest->GetId());
2834
2835 // Get node id and check object class and access rights
2836 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2837 pObject = FindObjectById(dwObjectId);
2838 if (pObject != NULL)
2839 {
2840 if ((pObject->Type() == OBJECT_NODE) ||
2841 (pObject->Type() == OBJECT_CLUSTER) ||
2842 (pObject->Type() == OBJECT_TEMPLATE))
2843 {
2844 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
2845 {
2846 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2847 {
2848 DWORD i, dwItemId, dwNumMaps, *pdwMapId, *pdwMapIndex;
2849 DCItem *pItem;
2850 BOOL bSuccess;
2851
2852 switch(pRequest->GetCode())
2853 {
2854 case CMD_CREATE_NEW_DCI:
2855 // Create dummy DCI
2856 pItem = new DCItem(CreateUniqueId(IDG_ITEM), "no name", DS_INTERNAL,
2857 DCI_DT_INT, 60, 30, (Node *)pObject);
2858 pItem->SetStatus(ITEM_STATUS_DISABLED);
2859 if (((Template *)pObject)->AddItem(pItem))
2860 {
2861 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2862 // Return new item id to client
2863 msg.SetVariable(VID_DCI_ID, pItem->Id());
2864 }
2865 else // Unable to add item to node
2866 {
2867 delete pItem;
2868 msg.SetVariable(VID_RCC, RCC_DUPLICATE_DCI);
2869 }
2870 break;
2871 case CMD_MODIFY_NODE_DCI:
2872 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
2873 bSuccess = ((Template *)pObject)->UpdateItem(dwItemId, pRequest, &dwNumMaps,
2874 &pdwMapIndex, &pdwMapId);
2875 if (bSuccess)
2876 {
2877 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2878
2879 // Send index to id mapping for newly created thresholds to client
2880 msg.SetVariable(VID_DCI_NUM_MAPS, dwNumMaps);
2881 for(i = 0; i < dwNumMaps; i++)
2882 {
2883 pdwMapId[i] = htonl(pdwMapId[i]);
2884 pdwMapIndex[i] = htonl(pdwMapIndex[i]);
2885 }
2886 msg.SetVariable(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
2887 msg.SetVariable(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
2888 safe_free(pdwMapId);
2889 safe_free(pdwMapIndex);
2890 }
2891 else
2892 {
2893 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
2894 }
2895 break;
2896 case CMD_DELETE_NODE_DCI:
2897 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
2898 bSuccess = ((Template *)pObject)->DeleteItem(dwItemId, TRUE);
2899 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_DCI_ID);
2900 break;
2901 }
2902 if (bSuccess)
2903 ((Template *)pObject)->SetDCIModificationFlag();
2904 }
2905 else // User doesn't have MODIFY rights on object
2906 {
2907 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2908 }
2909 }
2910 else // Nodes DCI list not locked by this session
2911 {
2912 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2913 }
2914 }
2915 else // Object is not a node
2916 {
2917 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2918 }
2919 }
2920 else // No object with given ID
2921 {
2922 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2923 }
2924
2925 // Send response
2926 SendMessage(&msg);
2927}
2928
2929
2930//
2931// Change status for one or more DCIs
2932//
2933
2934void ClientSession::ChangeDCIStatus(CSCPMessage *pRequest)
2935{
2936 CSCPMessage msg;
2937 NetObj *pObject;
2938
2939 // Prepare response message
2940 msg.SetCode(CMD_REQUEST_COMPLETED);
2941 msg.SetId(pRequest->GetId());
2942
2943 // Get node id and check object class and access rights
2944 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2945 if (pObject != NULL)
2946 {
2947 if ((pObject->Type() == OBJECT_NODE) ||
2948 (pObject->Type() == OBJECT_CLUSTER) ||
2949 (pObject->Type() == OBJECT_TEMPLATE))
2950 {
2951 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
2952 {
2953 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2954 {
2955 DWORD dwNumItems, *pdwItemList;
2956 int iStatus;
2957
2958 iStatus = pRequest->GetVariableShort(VID_DCI_STATUS);
2959 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
2960 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
2961 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
2962 if (((Template *)pObject)->SetItemStatus(dwNumItems, pdwItemList, iStatus))
2963 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2964 else
2965 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
2966 free(pdwItemList);
2967 }
2968 else // User doesn't have MODIFY rights on object
2969 {
2970 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2971 }
2972 }
2973 else // Nodes DCI list not locked by this session
2974 {
2975 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2976 }
2977 }
2978 else // Object is not a node
2979 {
2980 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2981 }
2982 }
2983 else // No object with given ID
2984 {
2985 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2986 }
2987
2988 // Send response
2989 SendMessage(&msg);
2990}
2991
2992
2993//
2994// Clear all collected data for DCI
2995//
2996
2997void ClientSession::ClearDCIData(CSCPMessage *pRequest)
2998{
2999 CSCPMessage msg;
3000 NetObj *pObject;
3001 DWORD dwItemId;
3002 DCItem *dci;
3003
3004 // Prepare response message
3005 msg.SetCode(CMD_REQUEST_COMPLETED);
3006 msg.SetId(pRequest->GetId());
3007
3008 // Get node id and check object class and access rights
3009 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3010 if (pObject != NULL)
3011 {
3012 if (pObject->Type() == OBJECT_NODE)
3013 {
3014 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
3015 {
3016 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
3017 DebugPrintf(4, _T("ClearDCIData: request for DCI %d at node %d"), dwItemId, pObject->Id());
3018 dci = ((Template *)pObject)->GetItemById(dwItemId);
3019 if (dci != NULL)
3020 {
3021 msg.SetVariable(VID_RCC, dci->DeleteAllData() ? RCC_SUCCESS : RCC_DB_FAILURE);
3022 DebugPrintf(4, _T("ClearDCIData: DCI %d at node %d"), dwItemId, pObject->Id());
3023 }
3024 else
3025 {
3026 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
3027 DebugPrintf(4, _T("ClearDCIData: DCI %d at node %d not found"), dwItemId, pObject->Id());
3028 }
3029 }
3030 else // User doesn't have DELETE rights on object
3031 {
3032 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3033 }
3034 }
3035 else // Object is not a node
3036 {
3037 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3038 }
3039 }
3040 else // No object with given ID
3041 {
3042 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3043 }
3044
3045 // Send response
3046 SendMessage(&msg);
3047}
3048
3049
3050//
3051// Copy or move DCI from one node or template to another
3052//
3053
3054void ClientSession::CopyDCI(CSCPMessage *pRequest)
3055{
3056 CSCPMessage msg;
3057 NetObj *pSource, *pDestination;
3058 TCHAR szLockInfo[MAX_SESSION_NAME];
3059 BOOL bMove;
3060
3061 // Prepare response message
3062 msg.SetCode(CMD_REQUEST_COMPLETED);
3063 msg.SetId(pRequest->GetId());
3064
3065 // Get source and destination
3066 pSource = FindObjectById(pRequest->GetVariableLong(VID_SOURCE_OBJECT_ID));
3067 pDestination = FindObjectById(pRequest->GetVariableLong(VID_DESTINATION_OBJECT_ID));
3068 if ((pSource != NULL) && (pDestination != NULL))
3069 {
3070 // Check object types
3071 if (((pSource->Type() == OBJECT_NODE) || (pSource->Type() == OBJECT_TEMPLATE) || (pSource->Type() == OBJECT_CLUSTER)) &&
3072 ((pDestination->Type() == OBJECT_NODE) || (pDestination->Type() == OBJECT_TEMPLATE) || (pDestination->Type() == OBJECT_CLUSTER)))
3073 {
3074 if (((Template *)pSource)->IsLockedBySession(m_dwIndex))
3075 {
3076 bMove = pRequest->GetVariableShort(VID_MOVE_FLAG);
3077 // Check access rights
3078 if ((pSource->CheckAccessRights(m_dwUserId, bMove ? (OBJECT_ACCESS_READ | OBJECT_ACCESS_MODIFY) : OBJECT_ACCESS_READ)) &&
3079 (pDestination->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
3080 {
3081 // Attempt to lock destination's DCI list
3082 if ((pDestination->Id() == pSource->Id()) ||
3083 (((Template *)pDestination)->LockDCIList(m_dwIndex, m_szUserName, szLockInfo)))
3084 {
3085 DWORD i, *pdwItemList, dwNumItems;
3086 const DCItem *pSrcItem;
3087 DCItem *pDstItem;
3088 int iErrors = 0;
3089
3090 // Get list of items to be copied/moved
3091 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
3092 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
3093 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
3094
3095 // Copy items
3096 for(i = 0; i < dwNumItems; i++)
3097 {
3098 pSrcItem = ((Template *)pSource)->GetItemById(pdwItemList[i]);
3099 if (pSrcItem != NULL)
3100 {
3101 pDstItem = new DCItem(pSrcItem);
3102 pDstItem->SetTemplateId(0, 0);
3103 pDstItem->ChangeBinding(CreateUniqueId(IDG_ITEM),
3104 (Template *)pDestination, FALSE);
3105 if (((Template *)pDestination)->AddItem(pDstItem))
3106 {
3107 if (bMove)
3108 {
3109 // Delete original item
3110 if (!((Template *)pSource)->DeleteItem(pdwItemList[i], TRUE))
3111 {
3112 iErrors++;
3113 }
3114 }
3115 }
3116 else
3117 {
3118 delete pDstItem;
3119 iErrors++;
3120 }
3121 }
3122 else
3123 {
3124 iErrors++;
3125 }
3126 }
3127
3128 // Cleanup
3129 free(pdwItemList);
3130 if (pDestination->Id() != pSource->Id())
3131 ((Template *)pDestination)->UnlockDCIList(m_dwIndex);
3132 msg.SetVariable(VID_RCC, (iErrors == 0) ? RCC_SUCCESS : RCC_DCI_COPY_ERRORS);
3133
3134 // Queue template update
3135 if (pDestination->Type() == OBJECT_TEMPLATE)
3136 ((Template *)pDestination)->QueueUpdate();
3137 }
3138 else // Destination's DCI list already locked by someone else
3139 {
3140 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3141 msg.SetVariable(VID_LOCKED_BY, szLockInfo);
3142 }
3143 }
3144 else // User doesn't have enough rights on object(s)
3145 {
3146 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3147 }
3148 }
3149 else // Source node DCI list not locked by this session
3150 {
3151 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3152 }
3153 }
3154 else // Object(s) is not a node
3155 {
3156 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3157 }
3158 }
3159 else // No object(s) with given ID
3160 {
3161 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3162 }
3163
3164 // Send response
3165 SendMessage(&msg);
3166}
3167
3168
3169//
3170// Get collected data
3171//
3172
3173void ClientSession::GetCollectedData(CSCPMessage *pRequest)
3174{
3175 CSCPMessage msg;
3176 DWORD dwObjectId;
3177 NetObj *pObject;
3178 BOOL bSuccess = FALSE;
3179 static DWORD m_dwRowSize[] = { 8, 8, 12, 12, 260, 12 };
3180#if !defined(UNICODE) || defined(UNICODE_UCS4)
3181 TCHAR szBuffer[MAX_DCI_STRING_VALUE];
3182#endif
3183
3184 // Prepare response message
3185 msg.SetCode(CMD_REQUEST_COMPLETED);
3186 msg.SetId(pRequest->GetId());
3187
3188 // Get node id and check object class and access rights
3189 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
3190 pObject = FindObjectById(dwObjectId);
3191 if (pObject != NULL)
3192 {
3193 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3194 {
3195 if (!(g_dwFlags & AF_DB_CONNECTION_LOST))
3196 {
3197 DB_ASYNC_RESULT hResult;
3198 DWORD i, dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo;
3199 DWORD dwNumRows = 0;
3200 TCHAR szQuery[512], szCond[256];
3201 int iPos = 0, iType;
3202 DCI_DATA_HEADER *pData = NULL;
3203 DCI_DATA_ROW *pCurr;
3204
3205 // Get request parameters
3206 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
3207 dwMaxRows = pRequest->GetVariableLong(VID_MAX_ROWS);
3208 dwTimeFrom = pRequest->GetVariableLong(VID_TIME_FROM);
3209 dwTimeTo = pRequest->GetVariableLong(VID_TIME_TO);
3210
3211 if ((dwMaxRows == 0) || (dwMaxRows > MAX_DCI_DATA_RECORDS))
3212 dwMaxRows = MAX_DCI_DATA_RECORDS;
3213
3214 szCond[0] = 0;
3215 if (dwTimeFrom != 0)
3216 {
3217 _stprintf(szCond, _T(" AND idata_timestamp>=%d"), dwTimeFrom);
3218 iPos = (int)_tcslen(szCond);
3219 }
3220 if (dwTimeTo != 0)
3221 {
3222 _stprintf(&szCond[iPos], _T(" AND idata_timestamp<=%d"), dwTimeTo);
3223 }
3224
3225 // Get item's data type to determine actual row size
3226 iType = ((Node *)pObject)->GetItemType(dwItemId);
3227//DWORD s=GetTickCount();
3228 // Create database-dependent query for fetching N rows
28f5b9a4 3229 switch(g_nDBSyntax)
5039dede
AK
3230 {
3231 case DB_SYNTAX_MSSQL:
3232 _stprintf(szQuery, _T("SELECT TOP %d idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC"),
3233 dwMaxRows, dwObjectId, dwItemId, szCond);
3234 break;
3235 case DB_SYNTAX_ORACLE:
3236 _stprintf(szQuery, _T("SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s AND ROWNUM <= %d ORDER BY idata_timestamp DESC"),
3237 dwObjectId, dwItemId, szCond, dwMaxRows);
3238 break;
3239 case DB_SYNTAX_MYSQL:
3240 case DB_SYNTAX_PGSQL:
3241 case DB_SYNTAX_SQLITE:
3242 _stprintf(szQuery, _T("SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC LIMIT %d"),
3243 dwObjectId, dwItemId, szCond, dwMaxRows);
3244 break;
3245 default:
3246 _stprintf(szQuery, _T("SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC LIMIT %d"),
3247 dwObjectId, dwItemId, szCond, dwMaxRows);
3248 break;
3249 }
3250 hResult = DBSelect(g_hCoreDB, szQuery);
3251//printf("[%d] **** QUERY DONE\n", GetTickCount() - s);
3252 if (hResult != NULL)
3253 {
3254 // Send CMD_REQUEST_COMPLETED message
3255 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3256 SendMessage(&msg);
3257
3258 dwNumRows = DBGetNumRows(hResult);
3259
3260 // Allocate memory for data and prepare data header
3261 pData = (DCI_DATA_HEADER *)malloc(dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
3262 pData->dwDataType = htonl((DWORD)iType);
3263 pData->dwItemId = htonl(dwItemId);
3264
3265 // Fill memory block with records
3266 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
3267 for(i = 0; i < dwNumRows; i++)
3268 {
3269 pCurr->dwTimeStamp = htonl(DBGetFieldULong(hResult, i, 0));
3270 switch(iType)
3271 {
3272 case DCI_DT_INT:
3273 case DCI_DT_UINT:
3274 pCurr->value.dwInteger = htonl(DBGetFieldULong(hResult, i, 1));
3275 break;
3276 case DCI_DT_INT64:
3277 case DCI_DT_UINT64:
3278 pCurr->value.qwInt64 = htonq(DBGetFieldUInt64(hResult, i, 1));
3279 break;
3280 case DCI_DT_FLOAT:
3281 pCurr->value.dFloat = htond(DBGetFieldDouble(hResult, i, 1));
3282 break;
3283 case DCI_DT_STRING:
3284#ifdef UNICODE
3285#ifdef UNICODE_UCS4
3286 DBGetField(hResult, i, 1, szBuffer, MAX_DCI_STRING_VALUE);
3287 ucs4_to_ucs2(szBuffer, -1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
3288#else
3289 DBGetField(hResult, i, 1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
3290#endif
3291#else
3292 DBGetField(hResult, i, 1, szBuffer, MAX_DCI_STRING_VALUE);
3293 mb_to_ucs2(szBuffer, -1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
3294#endif
3295 SwapWideString(pCurr->value.szString);
3296 break;
3297 }
3298 pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + m_dwRowSize[iType]);
3299 }
3300 DBFreeResult(hResult);
3301 pData->dwNumRows = htonl(dwNumRows);
3302//printf("[%d] **** %d ROWS\n", GetTickCount() - s, dwNumRows);
3303
3304 // Prepare and send raw message with fetched data
3305 m_pSendQueue->Put(
3306 CreateRawNXCPMessage(CMD_DCI_DATA, pRequest->GetId(), 0,
3307 dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER),
3308 pData, NULL));
3309 free(pData);
3310 bSuccess = TRUE;
3311 }
3312 else
3313 {
3314 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
3315 }
3316 }
3317 else
3318 {
3319 msg.SetVariable(VID_RCC, RCC_DB_CONNECTION_LOST);
3320 }
3321 }
3322 else
3323 {
3324 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3325 }
3326 }
3327 else // No object with given ID
3328 {
3329 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3330 }
3331
3332 // Send response
3333 if (!bSuccess)
3334 SendMessage(&msg);
3335}
3336
3337
3338//
3339// Send latest collected values for all DCIs of given node
3340//
3341
3342void ClientSession::SendLastValues(CSCPMessage *pRequest)
3343{
3344 CSCPMessage msg;
3345 NetObj *pObject;
3346
3347 // Prepare response message
3348 msg.SetCode(CMD_REQUEST_COMPLETED);
3349 msg.SetId(pRequest->GetId());
3350
3351 // Get node id and check object class and access rights
3352 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3353 if (pObject != NULL)
3354 {
3355 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3356 {
3357 if (pObject->Type() == OBJECT_NODE)
3358 {
3359 msg.SetVariable(VID_RCC, ((Node *)pObject)->GetLastValues(&msg));
3360 }
3361 else
3362 {
3363 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3364 }
3365 }
3366 else
3367 {
3368 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3369 }
3370 }
3371 else // No object with given ID
3372 {
3373 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3374 }
3375
3376 // Send response
3377 SendMessage(&msg);
3378}
3379
3380
3381//
3382// Open event processing policy
3383//
3384
3385void ClientSession::OpenEPP(DWORD dwRqId)
3386{
3387 CSCPMessage msg;
3388 char szBuffer[256];
3389 BOOL bSuccess = FALSE;
3390
3391 // Prepare response message
3392 msg.SetCode(CMD_REQUEST_COMPLETED);
3393 msg.SetId(dwRqId);
3394
3395 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
3396 {
3397 if (!LockComponent(CID_EPP, m_dwIndex, m_szUserName, NULL, szBuffer))
3398 {
3399 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3400 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3401 }
3402 else
3403 {
3404 m_dwFlags |= CSF_EPP_LOCKED;
3405 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3406 msg.SetVariable(VID_NUM_RULES, g_pEventPolicy->NumRules());
3407 bSuccess = TRUE;
3408 }
3409 }
3410 else
3411 {
3412 // Current user has no rights for event policy management
3413 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3414 }
3415
3416 // Send response
3417 SendMessage(&msg);
3418
3419 // Send policy to client
3420 if (bSuccess)
3421 g_pEventPolicy->SendToClient(this, dwRqId);
3422}
3423
3424
3425//
3426// Close event processing policy
3427//
3428
3429void ClientSession::CloseEPP(DWORD dwRqId)
3430{
3431 CSCPMessage msg;
3432
3433 // Prepare response message
3434 msg.SetCode(CMD_REQUEST_COMPLETED);
3435 msg.SetId(dwRqId);
3436
3437 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
3438 {
3439 if (m_dwFlags & CSF_EPP_LOCKED)
3440 {
3441 UnlockComponent(CID_EPP);
3442 m_dwFlags &= ~CSF_EPP_LOCKED;
3443 }
3444 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3445 }
3446 else
3447 {
3448 // Current user has no rights for event policy management
3449 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3450 }
3451
3452 // Send response
3453 SendMessage(&msg);
3454}
3455
3456
3457//
3458// Save event processing policy
3459//
3460
3461void ClientSession::SaveEPP(CSCPMessage *pRequest)
3462{
3463 CSCPMessage msg;
3464
3465 // Prepare response message
3466 msg.SetCode(CMD_REQUEST_COMPLETED);
3467 msg.SetId(pRequest->GetId());
3468
3469 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
3470 {
3471 if (m_dwFlags & CSF_EPP_LOCKED)
3472 {
3473 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3474 m_dwNumRecordsToUpload = pRequest->GetVariableLong(VID_NUM_RULES);
3475 m_dwRecordsUploaded = 0;
3476 if (m_dwNumRecordsToUpload == 0)
3477 {
3478 g_pEventPolicy->ReplacePolicy(0, NULL);
3479 g_pEventPolicy->SaveToDB();
3480 }
3481 else
3482 {
3483 m_dwFlags |= CSF_EPP_UPLOAD;
3484 m_ppEPPRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRecordsToUpload);
3485 memset(m_ppEPPRuleList, 0, sizeof(EPRule *) * m_dwNumRecordsToUpload);
3486 }
3487 DebugPrintf(5, "Accepted EPP upload request for %d rules", m_dwNumRecordsToUpload);
3488 }
3489 else
3490 {
3491 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3492 }
3493 }
3494 else
3495 {
3496 // Current user has no rights for event policy management
3497 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3498 }
3499
3500 // Send response
3501 SendMessage(&msg);
3502}
3503
3504
3505//
3506// Process EPP rule received from client
3507//
3508
3509void ClientSession::ProcessEPPRecord(CSCPMessage *pRequest)
3510{
3511 if (!(m_dwFlags & CSF_EPP_LOCKED))
3512 {
3513 CSCPMessage msg;
3514
3515 msg.SetCode(CMD_REQUEST_COMPLETED);
3516 msg.SetId(pRequest->GetId());
3517 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3518 SendMessage(&msg);
3519 }
3520 else
3521 {
3522 if (m_dwRecordsUploaded < m_dwNumRecordsToUpload)
3523 {
3524 m_ppEPPRuleList[m_dwRecordsUploaded] = new EPRule(pRequest);
3525 m_dwRecordsUploaded++;
3526 if (m_dwRecordsUploaded == m_dwNumRecordsToUpload)
3527 {
3528 CSCPMessage msg;
3529
3530 // All records received, replace event policy...
3531 DebugPrintf(5, "Replacing event processing policy with a new one at %p (%d rules)",
3532 m_ppEPPRuleList, m_dwNumRecordsToUpload);
3533 g_pEventPolicy->ReplacePolicy(m_dwNumRecordsToUpload, m_ppEPPRuleList);
3534 g_pEventPolicy->SaveToDB();
3535 m_ppEPPRuleList = NULL;
3536
3537 // ... and send final confirmation
3538 msg.SetCode(CMD_REQUEST_COMPLETED);
3539 msg.SetId(pRequest->GetId());
3540 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3541 SendMessage(&msg);
3542
3543 m_dwFlags &= ~CSF_EPP_UPLOAD;
3544 }
3545 }
3546 }
3547}
3548
3549
3550//
3551// Send compiled MIB file to client
3552//
3553
3554void ClientSession::SendMIB(DWORD dwRqId)
3555{
3556 char szBuffer[MAX_PATH];
3557
3558 // Send compiled MIB file
3559 strcpy(szBuffer, g_szDataDir);
3560 strcat(szBuffer, DFILE_COMPILED_MIB);
3561 SendFileOverNXCP(m_hSocket, dwRqId, szBuffer, m_pCtx);
3562}
3563
3564
3565//
3566// Send timestamp of compiled MIB file to client
3567//
3568
3569void ClientSession::SendMIBTimestamp(DWORD dwRqId)
3570{
3571 CSCPMessage msg;
3572 char szBuffer[MAX_PATH];
3573 DWORD dwResult, dwTimeStamp;
3574
3575 // Prepare response message
3576 msg.SetCode(CMD_REQUEST_COMPLETED);
3577 msg.SetId(dwRqId);
3578
3579 strcpy(szBuffer, g_szDataDir);
3580 strcat(szBuffer, DFILE_COMPILED_MIB);
3581 dwResult = SNMPGetMIBTreeTimestamp(szBuffer, &dwTimeStamp);
3582 if (dwResult == SNMP_ERR_SUCCESS)
3583 {
3584 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3585 msg.SetVariable(VID_TIMESTAMP, dwTimeStamp);
3586 }
3587 else
3588 {
3589 switch(dwResult)
3590 {
3591 case SNMP_ERR_FILE_IO:
3592 msg.SetVariable(VID_RCC, RCC_FILE_IO_ERROR);
3593 break;
3594 case SNMP_ERR_BAD_FILE_HEADER:
3595 msg.SetVariable(VID_RCC, RCC_CORRUPTED_MIB_FILE);
3596 break;
3597 default:
3598 msg.SetVariable(VID_RCC, RCC_INTERNAL_ERROR);
3599 break;
3600 }
3601 }
3602
3603 // Send response
3604 SendMessage(&msg);
3605}
3606
3607
3608//
3609// Create new object
3610//
3611
3612void ClientSession::CreateObject(CSCPMessage *pRequest)
3613{
3614 CSCPMessage msg;
3615 NetObj *pObject, *pParent;
3616 int iClass, iServiceType;
3617 TCHAR szObjectName[MAX_OBJECT_NAME];
3618 TCHAR *pszRequest, *pszResponse, *pszComments;
3619 DWORD dwIpAddr;
3620 WORD wIpProto, wIpPort;
3621 BOOL bParentAlwaysValid = FALSE;
3622
3623 // Prepare response message
3624 msg.SetCode(CMD_REQUEST_COMPLETED);
3625 msg.SetId(pRequest->GetId());
3626
3627 iClass = pRequest->GetVariableShort(VID_OBJECT_CLASS);
3628
3629 // Find parent object
3630 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
3631 if (iClass == OBJECT_NODE)
3632 {
3633 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
3634 if ((pParent == NULL) && (dwIpAddr != 0))
3635 {
3636 pParent = FindSubnetForNode(dwIpAddr);
3637 bParentAlwaysValid = TRUE;
3638 }
3639 }
3640 if ((pParent != NULL) || (iClass == OBJECT_NODE))
3641 {
3642 // User should have create access to parent object
3643 if ((pParent != NULL) ?
3644 pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE) :
3645 g_pEntireNet->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE))
3646 {
3647 // Parent object should be of valid type
3648 if (bParentAlwaysValid || IsValidParentClass(iClass, (pParent != NULL) ? pParent->Type() : -1))
3649 {
3650 pRequest->GetVariableStr(VID_OBJECT_NAME, szObjectName, MAX_OBJECT_NAME);
3651 if (IsValidObjectName(szObjectName, TRUE))
3652 {
3653 // Create new object
3654 switch(iClass)
3655 {
3656 case OBJECT_NODE:
3657 pObject = PollNewNode(dwIpAddr,
3658 pRequest->GetVariableLong(VID_IP_NETMASK),
3659 pRequest->GetVariableLong(VID_CREATION_FLAGS),
3660 szObjectName,
3661 pRequest->GetVariableLong(VID_PROXY_NODE),
3662 pRequest->GetVariableLong(VID_SNMP_PROXY),
3663 (pParent != NULL) ? ((pParent->Type() == OBJECT_CLUSTER) ? (Cluster *)pParent : NULL) : NULL);
3664 break;
3665 case OBJECT_CONTAINER:
3666 pObject = new Container(szObjectName,
3667 pRequest->GetVariableLong(VID_CATEGORY));
3668 NetObjInsert(pObject, TRUE);
3669 break;
3670 case OBJECT_TEMPLATEGROUP:
3671 pObject = new TemplateGroup(szObjectName);
3672 NetObjInsert(pObject, TRUE);
3673 pObject->CalculateCompoundStatus(); // Force status change to NORMAL
3674 break;
3675 case OBJECT_TEMPLATE:
3676 pObject = new Template(szObjectName);
3677 NetObjInsert(pObject, TRUE);
3678 pObject->CalculateCompoundStatus(); // Force status change to NORMAL
3679 break;
3680 case OBJECT_CLUSTER:
3681 pObject = new Cluster(szObjectName);
3682 NetObjInsert(pObject, TRUE);
3683 break;
3684 case OBJECT_NETWORKSERVICE:
3685 iServiceType = (int)pRequest->GetVariableShort(VID_SERVICE_TYPE);
3686 wIpProto = pRequest->GetVariableShort(VID_IP_PROTO);
3687 wIpPort = pRequest->GetVariableShort(VID_IP_PORT);
3688 pszRequest = pRequest->GetVariableStr(VID_SERVICE_REQUEST);
3689 pszResponse = pRequest->GetVariableStr(VID_SERVICE_RESPONSE);
3690 pObject = new NetworkService(iServiceType, wIpProto, wIpPort,
3691 pszRequest, pszResponse, (Node *)pParent);
3692 pObject->SetName(szObjectName);
3693 NetObjInsert(pObject, TRUE);
3694 break;
3695 case OBJECT_VPNCONNECTOR:
3696 pObject = new VPNConnector(TRUE);
3697 pObject->SetName(szObjectName);
3698 NetObjInsert(pObject, TRUE);
3699 break;
3700 case OBJECT_CONDITION:
3701 pObject = new Condition(TRUE);
3702 pObject->SetName(szObjectName);
3703 NetObjInsert(pObject, TRUE);
3704 break;
3705 default:
3706 break;
3707 }
3708
3709 // If creation was successful do binding and set comments if needed
3710 if (pObject != NULL)
3711 {
3712 if (pParent != NULL) // parent can be NULL for nodes
3713 {
3714 pParent->AddChild(pObject);
3715 pObject->AddParent(pParent);
3716 pParent->CalculateCompoundStatus();
3717 if (pParent->Type() == OBJECT_CLUSTER)
3718 {
3719 ((Cluster *)pParent)->ApplyToNode((Node *)pObject);
3720 }
3721 }
3722
3723 pszComments = pRequest->GetVariableStr(VID_COMMENTS);
3724 if (pszComments != NULL)
3725 pObject->SetComments(pszComments);
3726
3727 pObject->Unhide();
3728 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3729 msg.SetVariable(VID_OBJECT_ID, pObject->Id());
3730 }
3731 else
3732 {
3733 // :DIRTY HACK:
3734 // PollNewNode will return NULL only if IP already
3735 // in use. some new() can fail there too, but server will
3736 // crash in that case
3737 if (iClass == OBJECT_NODE)
3738 {
3739 msg.SetVariable(VID_RCC, RCC_ALREADY_EXIST);
3740 }
3741 else
3742 {
3743 msg.SetVariable(VID_RCC, RCC_OBJECT_CREATION_FAILED);
3744 }
3745 }
3746 }
3747 else
3748 {
3749 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
3750 }
3751 }
3752 else
3753 {
3754 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3755 }
3756 }
3757 else
3758 {
3759 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3760 }
3761 }
3762 else
3763 {
3764 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3765 }
3766
3767 // Send response
3768 SendMessage(&msg);
3769}
3770
3771
3772//
3773// Bind/unbind object
3774//
3775
3776void ClientSession::ChangeObjectBinding(CSCPMessage *pRequest, BOOL bBind)
3777{
3778 CSCPMessage msg;
3779 NetObj *pParent, *pChild;
3780
3781 // Prepare response message
3782 msg.SetCode(CMD_REQUEST_COMPLETED);
3783 msg.SetId(pRequest->GetId());
3784
3785 // Get parent and child objects
3786 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
3787 pChild = FindObjectById(pRequest->GetVariableLong(VID_CHILD_ID));
3788
3789 // Check access rights and change binding
3790 if ((pParent != NULL) && (pChild != NULL))
3791 {
3792 // User should have modify access to both objects
3793 if ((pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)) &&
3794 (pChild->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
3795 {
3796 // Parent object should be container or service root,
3797 // or template group/root for templates
3798 // For unbind, it can also be template
3799 if ((pParent->Type() == OBJECT_CONTAINER) ||
3800 (pParent->Type() == OBJECT_SERVICEROOT) ||
3801 ((pParent->Type() == OBJECT_TEMPLATE) && (!bBind)) ||
3802 ((pParent->Type() == OBJECT_TEMPLATEGROUP) && (pChild->Type() == OBJECT_TEMPLATE)) ||
3803 ((pParent->Type() == OBJECT_TEMPLATEROOT) && (pChild->Type() == OBJECT_TEMPLATE)))
3804 {
3805 if (bBind)
3806 {
3807 // Prevent loops
3808 if (!pChild->IsChild(pParent->Id()))
3809 {
3810 pParent->AddChild(pChild);
3811 pChild->AddParent(pParent);
3812 pParent->CalculateCompoundStatus();
3813 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3814 }
3815 else
3816 {
3817 msg.SetVariable(VID_RCC, RCC_OBJECT_LOOP);
3818 }
3819 }
3820 else
3821 {
3822 pParent->DeleteChild(pChild);
3823 pChild->DeleteParent(pParent);
3824 if ((pParent->Type() == OBJECT_TEMPLATE) &&
3825 (pChild->Type() == OBJECT_NODE))
3826 {
3827 ((Template *)pParent)->QueueRemoveFromNode(pChild->Id(),
3828 pRequest->GetVariableShort(VID_REMOVE_DCI));
3829 }
3830 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3831 }
3832 }
3833 else
3834 {
3835 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3836 }
3837 }
3838 else
3839 {
3840 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3841 }
3842 }
3843 else
3844 {
3845 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3846 }
3847
3848 // Send response
3849 SendMessage(&msg);
3850}
3851
3852
3853//
3854// Delete object
3855//
3856
3857void ClientSession::DeleteObject(CSCPMessage *pRequest)
3858{
3859 CSCPMessage msg;
3860 NetObj *pObject;
3861
3862 // Prepare response message
3863 msg.SetCode(CMD_REQUEST_COMPLETED);
3864 msg.SetId(pRequest->GetId());
3865
3866 // Find object to be deleted
3867 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3868 if (pObject != NULL)
3869 {
3870 // Check if it is a built-in object, like "Entire Network"
3871 if (pObject->Id() >= 10)
3872 {
3873 // Check access rights
3874 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
3875 {
3876 pObject->Delete(FALSE);
3877 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3878 }
3879 else
3880 {
3881 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3882 }
3883 }
3884 else
3885 {
3886 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3887 }
3888 }
3889 else
3890 {
3891 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3892 }
3893
3894 // Send response
3895 SendMessage(&msg);
3896}
3897
3898
3899//
3900// Process changes in alarms
3901//
3902
3903void ClientSession::OnAlarmUpdate(DWORD dwCode, NXC_ALARM *pAlarm)
3904{
3905 UPDATE_INFO *pUpdate;
3906 NetObj *pObject;
3907
3908 if (IsAuthenticated() && (m_dwActiveChannels & NXC_CHANNEL_ALARMS))
3909 {
3910 pObject = FindObjectById(pAlarm->dwSourceObject);
3911 if (pObject != NULL)
3912 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
3913 {
3914 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
3915 pUpdate->dwCategory = INFO_CAT_ALARM;
3916 pUpdate->dwCode = dwCode;
3917 pUpdate->pData = nx_memdup(pAlarm, sizeof(NXC_ALARM));
3918 m_pUpdateQueue->Put(pUpdate);
3919 }
3920 }
3921}
3922
3923
3924//
3925// Send all alarms to client
3926//
3927
3928void ClientSession::SendAllAlarms(DWORD dwRqId, BOOL bIncludeAck)
3929{
3930 MutexLock(m_mutexSendAlarms, INFINITE);
3931 g_alarmMgr.SendAlarmsToClient(dwRqId, bIncludeAck, this);
3932 MutexUnlock(m_mutexSendAlarms);
3933}
3934
3935
3936//
3937// Acknowledge alarm
3938//
3939
3940void ClientSession::AcknowledgeAlarm(CSCPMessage *pRequest)
3941{
3942 CSCPMessage msg;
3943 NetObj *pObject;
3944 DWORD dwAlarmId;
3945
3946 // Prepare response message
3947 msg.SetCode(CMD_REQUEST_COMPLETED);
3948 msg.SetId(pRequest->GetId());
3949
3950 // Get alarm id and it's source object
3951 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
3952 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
3953 if (pObject != NULL)
3954 {
3955 // User should have "acknowledge alarm" right to the object
3956 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS))
3957 {
3958 msg.SetVariable(VID_RCC, g_alarmMgr.AckById(dwAlarmId, m_dwUserId));
3959 }
3960 else
3961 {
3962 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3963 }
3964 }
3965 else
3966 {
3967 // Normally, for existing alarms pObject will not be NULL,
3968 // so we assume that alarm id is invalid
3969 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
3970 }
3971
3972 // Send response
3973 SendMessage(&msg);
3974}
3975
3976
3977//
3978// Terminate alarm
3979//
3980
3981void ClientSession::TerminateAlarm(CSCPMessage *pRequest)
3982{
3983 CSCPMessage msg;
3984 NetObj *pObject;
3985 DWORD dwAlarmId;
3986
3987 // Prepare response message
3988 msg.SetCode(CMD_REQUEST_COMPLETED);
3989 msg.SetId(pRequest->GetId());
3990
3991 // Get alarm id and it's source object
3992 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
3993 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
3994 if (pObject != NULL)
3995 {
3996 // User should have "terminate alarm" right to the object
3997 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_TERM_ALARMS))
3998 {
3999 msg.SetVariable(VID_RCC, g_alarmMgr.TerminateById(dwAlarmId, m_dwUserId));
4000 }
4001 else
4002 {
4003 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
4004 }
4005 }
4006 else
4007 {
4008 // Normally, for existing alarms pObject will not be NULL,
4009 // so we assume that alarm id is invalid
4010 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
4011 }
4012
4013 // Send response
4014 SendMessage(&msg);
4015}
4016
4017
4018//
4019// Delete alarm
4020//
4021
4022void ClientSession::DeleteAlarm(CSCPMessage *pRequest)
4023{
4024 CSCPMessage msg;
4025 NetObj *pObject;
4026 DWORD dwAlarmId;
4027
4028 // Prepare response message
4029 msg.SetCode(CMD_REQUEST_COMPLETED);
4030 msg.SetId(pRequest->GetId());
4031
4032 // Get alarm id and it's source object
4033 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
4034 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
4035 if (pObject != NULL)
4036 {
4037 // User should have "terminate alarm" right to the object
4038 // and system right "delete alarms"
4039 if ((pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_TERM_ALARMS)) &&
4040 (m_dwSystemAccess & SYSTEM_ACCESS_DELETE_ALARMS))
4041 {
4042 g_alarmMgr.DeleteAlarm(dwAlarmId);
4043 msg.SetVariable(VID_RCC, RCC_SUCCESS);
4044 }
4045 else
4046 {
4047 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
4048 }
4049 }
4050 else
4051 {
4052 // Normally, for existing alarms pObject will not be NULL,
4053 // so we assume that alarm id is invalid
4054 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
4055 }
4056
4057 // Send response
4058 SendMessage(&msg);
4059}
4060
4061
4062//
4063// Lock/unlock action configuration database
4064//
4065
4066void ClientSession::LockActionDB(DWORD dwRqId, BOOL bLock)
4067{
4068 CSCPMessage msg;
4069 char szBuffer[256];
4070
4071 // Prepare response message
4072 msg.SetCode(CMD_REQUEST_COMPLETED);
4073 msg.SetId(dwRqId);
4074
4075 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
4076 {