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