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