- Fixed issue #0000017 (server crash after DCI copy)
[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->ChangeBinding(CreateUniqueId(IDG_ITEM),
2141 (Template *)pDestination);
2142 if (!((Template *)pDestination)->AddItem(pDstItem))
2143 {
2144 delete pDstItem;
2145 iErrors++;
2146 }
2147 }
2148 else
2149 {
2150 iErrors++;
2151 }
2152 }
2153
2154 // Cleanup
2155 free(pdwItemList);
2156 if (pDestination->Id() != pSource->Id())
2157 ((Template *)pDestination)->UnlockDCIList(m_dwIndex);
2158 msg.SetVariable(VID_RCC, (iErrors == 0) ? RCC_SUCCESS : RCC_DCI_COPY_ERRORS);
2159 }
2160 else // Destination's DCI list already locked by someone else
2161 {
2162 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2163 }
2164 }
2165 else // User doesn't have enough rights on object(s)
2166 {
2167 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2168 }
2169 }
2170 else // Source node DCI list not locked by this session
2171 {
2172 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2173 }
2174 }
2175 else // Object(s) is not a node
2176 {
2177 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2178 }
2179 }
2180 else // No object(s) with given ID
2181 {
2182 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2183 }
2184
2185 // Send responce
2186 SendMessage(&msg);
2187 }
2188
2189
2190 //
2191 // Get collected data
2192 //
2193
2194 void ClientSession::GetCollectedData(CSCPMessage *pRequest)
2195 {
2196 CSCPMessage msg;
2197 DWORD dwObjectId;
2198 NetObj *pObject;
2199 BOOL bSuccess = FALSE;
2200 static DWORD m_dwRowSize[] = { 8, 8, 12, 12, 260, 12 };
2201
2202 // Prepare responce message
2203 msg.SetCode(CMD_REQUEST_COMPLETED);
2204 msg.SetId(pRequest->GetId());
2205
2206 // Get node id and check object class and access rights
2207 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
2208 pObject = FindObjectById(dwObjectId);
2209 if (pObject != NULL)
2210 {
2211 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2212 {
2213 DB_ASYNC_RESULT hResult;
2214 DWORD dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo;
2215 DWORD dwAllocatedRows = 100, dwNumRows = 0;
2216 char szQuery[512], szCond[256];
2217 int iPos = 0, iType;
2218 DCI_DATA_HEADER *pData = NULL;
2219 DCI_DATA_ROW *pCurr;
2220
2221 // Send CMD_REQUEST_COMPLETED message
2222 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2223 SendMessage(&msg);
2224
2225 // Get request parameters
2226 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
2227 dwMaxRows = pRequest->GetVariableLong(VID_MAX_ROWS);
2228 dwTimeFrom = pRequest->GetVariableLong(VID_TIME_FROM);
2229 dwTimeTo = pRequest->GetVariableLong(VID_TIME_TO);
2230
2231 szCond[0] = 0;
2232 if (dwTimeFrom != 0)
2233 {
2234 sprintf(szCond, " AND idata_timestamp>=%d", dwTimeFrom);
2235 iPos = strlen(szCond);
2236 }
2237 if (dwTimeTo != 0)
2238 {
2239 sprintf(&szCond[iPos], " AND idata_timestamp<=%d", dwTimeTo);
2240 }
2241
2242 // Get item's data type to determine actual row size
2243 iType = ((Node *)pObject)->GetItemType(dwItemId);
2244
2245 // Create database-dependent query for fetching N rows
2246 if (dwMaxRows > 0)
2247 {
2248 switch(g_dwDBSyntax)
2249 {
2250 case DB_SYNTAX_MSSQL:
2251 sprintf(szQuery, "SELECT TOP %ld idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2252 dwMaxRows, dwObjectId, dwItemId, szCond);
2253 break;
2254 case DB_SYNTAX_MYSQL:
2255 case DB_SYNTAX_PGSQL:
2256 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC LIMIT %ld",
2257 dwObjectId, dwItemId, szCond, dwMaxRows);
2258 break;
2259 default:
2260 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2261 dwObjectId, dwItemId, szCond);
2262 break;
2263 }
2264 }
2265 else
2266 {
2267 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
2268 dwObjectId, dwItemId, szCond);
2269 }
2270 hResult = DBAsyncSelect(g_hCoreDB, szQuery);
2271 if (hResult != NULL)
2272 {
2273 // Allocate initial memory block and prepare data header
2274 pData = (DCI_DATA_HEADER *)malloc(dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
2275 pData->dwDataType = htonl((DWORD)iType);
2276 pData->dwItemId = htonl(dwItemId);
2277
2278 // Fill memory block with records
2279 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
2280 while(DBFetch(hResult))
2281 {
2282 if ((dwMaxRows > 0) && (dwNumRows >= dwMaxRows))
2283 break;
2284
2285 // Extend buffer if we are at the end
2286 if (dwNumRows == dwAllocatedRows)
2287 {
2288 dwAllocatedRows += 50;
2289 pData = (DCI_DATA_HEADER *)realloc(pData,
2290 dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
2291 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER) + m_dwRowSize[iType] * dwNumRows);
2292 }
2293
2294 dwNumRows++;
2295
2296 pCurr->dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 0));
2297 switch(iType)
2298 {
2299 case DCI_DT_INT:
2300 case DCI_DT_UINT:
2301 pCurr->value.dwInteger = htonl(DBGetFieldAsyncULong(hResult, 1));
2302 break;
2303 case DCI_DT_INT64:
2304 case DCI_DT_UINT64:
2305 pCurr->value.qwInt64 = htonq(DBGetFieldAsyncUInt64(hResult, 1));
2306 break;
2307 case DCI_DT_FLOAT:
2308 pCurr->value.dFloat = htond(DBGetFieldAsyncDouble(hResult, 1));
2309 break;
2310 case DCI_DT_STRING:
2311 DBGetFieldAsync(hResult, 1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
2312 break;
2313 }
2314 pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + m_dwRowSize[iType]);
2315 }
2316 DBFreeAsyncResult(hResult);
2317 pData->dwNumRows = htonl(dwNumRows);
2318
2319 // Prepare and send raw message with fetched data
2320 m_pSendQueue->Put(
2321 CreateRawCSCPMessage(CMD_DCI_DATA, pRequest->GetId(),
2322 dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER),
2323 pData, NULL));
2324 free(pData);
2325 bSuccess = TRUE;
2326 }
2327 else
2328 {
2329 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
2330 }
2331 }
2332 else
2333 {
2334 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2335 }
2336 }
2337 else // No object with given ID
2338 {
2339 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2340 }
2341
2342 // Send responce
2343 if (!bSuccess)
2344 SendMessage(&msg);
2345 }
2346
2347
2348 //
2349 // Send latest collected values for all DCIs of given node
2350 //
2351
2352 void ClientSession::SendLastValues(CSCPMessage *pRequest)
2353 {
2354 CSCPMessage msg;
2355 NetObj *pObject;
2356
2357 // Prepare responce message
2358 msg.SetCode(CMD_REQUEST_COMPLETED);
2359 msg.SetId(pRequest->GetId());
2360
2361 // Get node id and check object class and access rights
2362 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2363 if (pObject != NULL)
2364 {
2365 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2366 {
2367 if (pObject->Type() == OBJECT_NODE)
2368 {
2369 msg.SetVariable(VID_RCC, ((Node *)pObject)->GetLastValues(&msg));
2370 }
2371 else
2372 {
2373 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2374 }
2375 }
2376 else
2377 {
2378 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2379 }
2380 }
2381 else // No object with given ID
2382 {
2383 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2384 }
2385
2386 // Send responce
2387 SendMessage(&msg);
2388 }
2389
2390
2391 //
2392 // Open event processing policy
2393 //
2394
2395 void ClientSession::OpenEPP(DWORD dwRqId)
2396 {
2397 CSCPMessage msg;
2398 char szBuffer[256];
2399 BOOL bSuccess = FALSE;
2400
2401 // Prepare responce message
2402 msg.SetCode(CMD_REQUEST_COMPLETED);
2403 msg.SetId(dwRqId);
2404
2405 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2406 {
2407 if (!LockComponent(CID_EPP, m_dwIndex, m_szUserName, NULL, szBuffer))
2408 {
2409 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2410 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2411 }
2412 else
2413 {
2414 m_dwFlags |= CSF_EPP_LOCKED;
2415 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2416 msg.SetVariable(VID_NUM_RULES, g_pEventPolicy->NumRules());
2417 bSuccess = TRUE;
2418 }
2419 }
2420 else
2421 {
2422 // Current user has no rights for event policy management
2423 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2424 }
2425
2426 // Send responce
2427 SendMessage(&msg);
2428
2429 // Send policy to client
2430 if (bSuccess)
2431 g_pEventPolicy->SendToClient(this, dwRqId);
2432 }
2433
2434
2435 //
2436 // Close event processing policy
2437 //
2438
2439 void ClientSession::CloseEPP(DWORD dwRqId)
2440 {
2441 CSCPMessage msg;
2442
2443 // Prepare responce message
2444 msg.SetCode(CMD_REQUEST_COMPLETED);
2445 msg.SetId(dwRqId);
2446
2447 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2448 {
2449 if (m_dwFlags & CSF_EPP_LOCKED)
2450 {
2451 UnlockComponent(CID_EPP);
2452 m_dwFlags &= ~CSF_EPP_LOCKED;
2453 }
2454 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2455 }
2456 else
2457 {
2458 // Current user has no rights for event policy management
2459 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2460 }
2461
2462 // Send responce
2463 SendMessage(&msg);
2464 }
2465
2466
2467 //
2468 // Save event processing policy
2469 //
2470
2471 void ClientSession::SaveEPP(CSCPMessage *pRequest)
2472 {
2473 CSCPMessage msg;
2474
2475 // Prepare responce message
2476 msg.SetCode(CMD_REQUEST_COMPLETED);
2477 msg.SetId(pRequest->GetId());
2478
2479 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2480 {
2481 if (m_dwFlags & CSF_EPP_LOCKED)
2482 {
2483 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2484 m_dwNumRecordsToUpload = pRequest->GetVariableLong(VID_NUM_RULES);
2485 m_dwRecordsUploaded = 0;
2486 if (m_dwNumRecordsToUpload == 0)
2487 {
2488 g_pEventPolicy->ReplacePolicy(0, NULL);
2489 g_pEventPolicy->SaveToDB();
2490 }
2491 else
2492 {
2493 m_dwFlags |= CSF_EPP_UPLOAD;
2494 m_ppEPPRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRecordsToUpload);
2495 memset(m_ppEPPRuleList, 0, sizeof(EPRule *) * m_dwNumRecordsToUpload);
2496 }
2497 DebugPrintf("Accepted EPP upload request for %d rules\n", m_dwNumRecordsToUpload);
2498 }
2499 else
2500 {
2501 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2502 }
2503 }
2504 else
2505 {
2506 // Current user has no rights for event policy management
2507 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2508 }
2509
2510 // Send responce
2511 SendMessage(&msg);
2512 }
2513
2514
2515 //
2516 // Process EPP rule received from client
2517 //
2518
2519 void ClientSession::ProcessEPPRecord(CSCPMessage *pRequest)
2520 {
2521 if (!(m_dwFlags & CSF_EPP_LOCKED))
2522 {
2523 CSCPMessage msg;
2524
2525 msg.SetCode(CMD_REQUEST_COMPLETED);
2526 msg.SetId(pRequest->GetId());
2527 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2528 SendMessage(&msg);
2529 }
2530 else
2531 {
2532 if (m_dwRecordsUploaded < m_dwNumRecordsToUpload)
2533 {
2534 m_ppEPPRuleList[m_dwRecordsUploaded] = new EPRule(pRequest);
2535 m_dwRecordsUploaded++;
2536 if (m_dwRecordsUploaded == m_dwNumRecordsToUpload)
2537 {
2538 CSCPMessage msg;
2539
2540 // All records received, replace event policy...
2541 DebugPrintf("Replacing event processing policy with a new one at %p (%d rules)\n",
2542 m_ppEPPRuleList, m_dwNumRecordsToUpload);
2543 g_pEventPolicy->ReplacePolicy(m_dwNumRecordsToUpload, m_ppEPPRuleList);
2544 g_pEventPolicy->SaveToDB();
2545 m_ppEPPRuleList = NULL;
2546
2547 // ... and send final confirmation
2548 msg.SetCode(CMD_REQUEST_COMPLETED);
2549 msg.SetId(pRequest->GetId());
2550 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2551 SendMessage(&msg);
2552
2553 m_dwFlags &= ~CSF_EPP_UPLOAD;
2554 }
2555 }
2556 }
2557 }
2558
2559
2560 //
2561 // Send list of available MIB files to client
2562 //
2563
2564 void ClientSession::SendMIBList(DWORD dwRqId)
2565 {
2566 CSCPMessage msg;
2567 DWORD dwId1, dwId2, dwNumFiles;
2568 DIR *dir;
2569 int iBufPos;
2570 struct dirent *dptr;
2571 char szBuffer[MAX_PATH];
2572 BYTE md5Hash[MD5_DIGEST_SIZE];
2573
2574 // Prepare responce message
2575 msg.SetCode(CMD_MIB_LIST);
2576 msg.SetId(dwRqId);
2577
2578 // Read directory
2579 dwNumFiles = 0;
2580 strcpy(szBuffer, g_szDataDir);
2581 strcat(szBuffer, DDIR_MIBS);
2582 dir = opendir(szBuffer);
2583 if (dir != NULL)
2584 {
2585 strcat(szBuffer, FS_PATH_SEPARATOR);
2586 iBufPos = strlen(szBuffer);
2587 dwId1 = VID_MIB_NAME_BASE;
2588 dwId2 = VID_MIB_HASH_BASE;
2589 while((dptr = readdir(dir)) != NULL)
2590 {
2591 if (dptr->d_name[0] == '.')
2592 continue;
2593
2594 strcpy(&szBuffer[iBufPos], dptr->d_name);
2595 if (CalculateFileMD5Hash(szBuffer, md5Hash))
2596 {
2597 msg.SetVariable(dwId1++, dptr->d_name);
2598 msg.SetVariable(dwId2++, md5Hash, MD5_DIGEST_SIZE);
2599 dwNumFiles++;
2600 }
2601 }
2602 closedir(dir);
2603 }
2604
2605 msg.SetVariable(VID_NUM_MIBS, dwNumFiles);
2606
2607 // Send responce
2608 SendMessage(&msg);
2609 }
2610
2611
2612 //
2613 // Send requested MIB file to client
2614 //
2615
2616 void ClientSession::SendMIB(CSCPMessage *pRequest)
2617 {
2618 CSCPMessage msg;
2619 BYTE *pFile;
2620 DWORD dwFileSize;
2621 char szBuffer[MAX_PATH], szMIB[MAX_PATH];
2622
2623 // Prepare responce message
2624 msg.SetCode(CMD_MIB);
2625 msg.SetId(pRequest->GetId());
2626
2627 // Get name of the requested file
2628 pRequest->GetVariableStr(VID_MIB_NAME, szMIB, MAX_PATH);
2629
2630 // Load file into memory
2631 strcpy(szBuffer, g_szDataDir);
2632 strcat(szBuffer, DDIR_MIBS);
2633 #ifdef _WIN32
2634 strcat(szBuffer, "\\");
2635 #else
2636 strcat(szBuffer, "/");
2637 #endif
2638 strcat(szBuffer, szMIB);
2639 pFile = LoadFile(szBuffer, &dwFileSize);
2640 if (pFile != NULL)
2641 {
2642 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2643 msg.SetVariable(VID_MIB_FILE_SIZE, dwFileSize);
2644 msg.SetVariable(VID_MIB_FILE, pFile, dwFileSize);
2645 free(pFile);
2646 }
2647 else
2648 {
2649 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
2650 }
2651
2652 // Send responce
2653 SendMessage(&msg);
2654 }
2655
2656
2657 //
2658 // Create new object
2659 //
2660
2661 void ClientSession::CreateObject(CSCPMessage *pRequest)
2662 {
2663 CSCPMessage msg;
2664 NetObj *pObject, *pParent;
2665 int iClass, iServiceType;
2666 TCHAR *pDescription, szObjectName[MAX_OBJECT_NAME];
2667 TCHAR *pszRequest, *pszResponce;
2668 DWORD dwIpAddr;
2669 WORD wIpProto, wIpPort;
2670 BOOL bParentAlwaysValid = FALSE;
2671
2672 // Prepare responce message
2673 msg.SetCode(CMD_REQUEST_COMPLETED);
2674 msg.SetId(pRequest->GetId());
2675
2676 iClass = pRequest->GetVariableShort(VID_OBJECT_CLASS);
2677
2678 // Find parent object
2679 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2680 if (iClass == OBJECT_NODE)
2681 {
2682 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
2683 if ((pParent == NULL) && (dwIpAddr != 0))
2684 {
2685 pParent = FindSubnetForNode(dwIpAddr);
2686 bParentAlwaysValid = TRUE;
2687 }
2688 }
2689 if ((pParent != NULL) || (iClass == OBJECT_NODE))
2690 {
2691 // User should have create access to parent object
2692 if ((pParent != NULL) ?
2693 pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE) :
2694 g_pEntireNet->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE))
2695 {
2696 // Parent object should be of valid type
2697 if (bParentAlwaysValid || IsValidParentClass(iClass, (pParent != NULL) ? pParent->Type() : -1))
2698 {
2699 pRequest->GetVariableStr(VID_OBJECT_NAME, szObjectName, MAX_OBJECT_NAME);
2700 if (IsValidObjectName(szObjectName))
2701 {
2702 // Create new object
2703 switch(iClass)
2704 {
2705 case OBJECT_NODE:
2706 pObject = PollNewNode(dwIpAddr, pRequest->GetVariableLong(VID_IP_NETMASK),
2707 DF_DEFAULT, szObjectName);
2708 break;
2709 case OBJECT_CONTAINER:
2710 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2711 pObject = new Container(szObjectName,
2712 pRequest->GetVariableLong(VID_CATEGORY),
2713 pDescription);
2714 safe_free(pDescription);
2715 NetObjInsert(pObject, TRUE);
2716 break;
2717 case OBJECT_TEMPLATEGROUP:
2718 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2719 pObject = new TemplateGroup(szObjectName, pDescription);
2720 safe_free(pDescription);
2721 NetObjInsert(pObject, TRUE);
2722 break;
2723 case OBJECT_TEMPLATE:
2724 pObject = new Template;
2725 pObject->SetName(szObjectName);
2726 NetObjInsert(pObject, TRUE);
2727 break;
2728 case OBJECT_NETWORKSERVICE:
2729 iServiceType = (int)pRequest->GetVariableShort(VID_SERVICE_TYPE);
2730 wIpProto = pRequest->GetVariableShort(VID_IP_PROTO);
2731 wIpPort = pRequest->GetVariableShort(VID_IP_PORT);
2732 pszRequest = pRequest->GetVariableStr(VID_SERVICE_REQUEST);
2733 pszResponce = pRequest->GetVariableStr(VID_SERVICE_RESPONCE);
2734 pObject = new NetworkService(iServiceType, wIpProto, wIpPort,
2735 pszRequest, pszResponce, (Node *)pParent);
2736 pObject->SetName(szObjectName);
2737 NetObjInsert(pObject, TRUE);
2738 break;
2739 }
2740
2741 // If creation was successful do binding
2742 if (pObject != NULL)
2743 {
2744 if (pParent != NULL) // parent can be NULL for nodes
2745 {
2746 pParent->AddChild(pObject);
2747 pObject->AddParent(pParent);
2748 pParent->CalculateCompoundStatus();
2749 }
2750 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2751 msg.SetVariable(VID_OBJECT_ID, pObject->Id());
2752 }
2753 else
2754 {
2755 msg.SetVariable(VID_RCC, RCC_OBJECT_CREATION_FAILED);
2756 }
2757 }
2758 else
2759 {
2760 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
2761 }
2762 }
2763 else
2764 {
2765 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2766 }
2767 }
2768 else
2769 {
2770 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2771 }
2772 }
2773 else
2774 {
2775 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2776 }
2777
2778 // Send responce
2779 SendMessage(&msg);
2780 }
2781
2782
2783 //
2784 // Bind/unbind object
2785 //
2786
2787 void ClientSession::ChangeObjectBinding(CSCPMessage *pRequest, BOOL bBind)
2788 {
2789 CSCPMessage msg;
2790 NetObj *pParent, *pChild;
2791
2792 // Prepare responce message
2793 msg.SetCode(CMD_REQUEST_COMPLETED);
2794 msg.SetId(pRequest->GetId());
2795
2796 // Get parent and child objects
2797 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2798 pChild = FindObjectById(pRequest->GetVariableLong(VID_CHILD_ID));
2799
2800 // Check access rights and change binding
2801 if ((pParent != NULL) && (pChild != NULL))
2802 {
2803 // User should have modify access to both objects
2804 if ((pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)) &&
2805 (pChild->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2806 {
2807 // Parent object should be container or service root
2808 if ((pParent->Type() == OBJECT_CONTAINER) ||
2809 (pParent->Type() == OBJECT_SERVICEROOT))
2810 {
2811 if (bBind)
2812 {
2813 // Prevent loops
2814 if (!pChild->IsChild(pParent->Id()))
2815 {
2816 pParent->AddChild(pChild);
2817 pChild->AddParent(pParent);
2818 pParent->CalculateCompoundStatus();
2819 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2820 }
2821 else
2822 {
2823 msg.SetVariable(VID_RCC, RCC_OBJECT_LOOP);
2824 }
2825 }
2826 else
2827 {
2828 pParent->DeleteChild(pChild);
2829 pChild->DeleteParent(pParent);
2830 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2831 }
2832 }
2833 else
2834 {
2835 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2836 }
2837 }
2838 else
2839 {
2840 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2841 }
2842 }
2843 else
2844 {
2845 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2846 }
2847
2848 // Send responce
2849 SendMessage(&msg);
2850 }
2851
2852
2853 //
2854 // Delete object
2855 //
2856
2857 void ClientSession::DeleteObject(CSCPMessage *pRequest)
2858 {
2859 CSCPMessage msg;
2860 NetObj *pObject;
2861
2862 // Prepare responce message
2863 msg.SetCode(CMD_REQUEST_COMPLETED);
2864 msg.SetId(pRequest->GetId());
2865
2866 // Find object to be deleted
2867 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2868 if (pObject != NULL)
2869 {
2870 // Check if it is a built-in object, like "Entire Network"
2871 if (pObject->Id() >= 10)
2872 {
2873 // Check access rights
2874 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
2875 {
2876 pObject->Delete(FALSE);
2877 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2878 }
2879 else
2880 {
2881 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2882 }
2883 }
2884 else
2885 {
2886 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2887 }
2888 }
2889 else
2890 {
2891 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2892 }
2893
2894 // Send responce
2895 SendMessage(&msg);
2896 }
2897
2898
2899 //
2900 // Process changes in alarms
2901 //
2902
2903 void ClientSession::OnAlarmUpdate(DWORD dwCode, NXC_ALARM *pAlarm)
2904 {
2905 UPDATE_INFO *pUpdate;
2906 NetObj *pObject;
2907
2908 if (IsAuthenticated())
2909 {
2910 pObject = FindObjectById(pAlarm->dwSourceObject);
2911 if (pObject != NULL)
2912 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
2913 {
2914 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2915 pUpdate->dwCategory = INFO_CAT_ALARM;
2916 pUpdate->dwCode = dwCode;
2917 pUpdate->pData = nx_memdup(pAlarm, sizeof(NXC_ALARM));
2918 m_pUpdateQueue->Put(pUpdate);
2919 }
2920 }
2921 }
2922
2923
2924 //
2925 // Send all alarms to client
2926 //
2927
2928 void ClientSession::SendAllAlarms(DWORD dwRqId, BOOL bIncludeAck)
2929 {
2930 MutexLock(m_mutexSendAlarms, INFINITE);
2931 g_alarmMgr.SendAlarmsToClient(dwRqId, bIncludeAck, this);
2932 MutexUnlock(m_mutexSendAlarms);
2933 }
2934
2935
2936 //
2937 // Acknowlege alarm
2938 //
2939
2940 void ClientSession::AcknowlegeAlarm(CSCPMessage *pRequest)
2941 {
2942 CSCPMessage msg;
2943 NetObj *pObject;
2944 DWORD dwAlarmId;
2945
2946 // Prepare responce message
2947 msg.SetCode(CMD_REQUEST_COMPLETED);
2948 msg.SetId(pRequest->GetId());
2949
2950 // Get alarm id and it's source object
2951 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
2952 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
2953 if (pObject != NULL)
2954 {
2955 // User should have "acknowlege alarm" right to the object
2956 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS))
2957 {
2958 g_alarmMgr.AckById(dwAlarmId, m_dwUserId);
2959 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2960 }
2961 else
2962 {
2963 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2964 }
2965 }
2966 else
2967 {
2968 // Normally, for existing alarms pObject will not be NULL,
2969 // so we assume that alarm id is invalid
2970 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
2971 }
2972
2973 // Send responce
2974 SendMessage(&msg);
2975 }
2976
2977
2978 //
2979 // Delete alarm
2980 //
2981
2982 void ClientSession::DeleteAlarm(CSCPMessage *pRequest)
2983 {
2984 CSCPMessage msg;
2985 NetObj *pObject;
2986 DWORD dwAlarmId;
2987
2988 // Prepare responce message
2989 msg.SetCode(CMD_REQUEST_COMPLETED);
2990 msg.SetId(pRequest->GetId());
2991
2992 // Get alarm id and it's source object
2993 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
2994 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
2995 if (pObject != NULL)
2996 {
2997 // User should have "acknowlege alarm" right to the object
2998 // and system right "delete alarms"
2999 if ((pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS)) &&
3000 (m_dwSystemAccess & SYSTEM_ACCESS_DELETE_ALARMS))
3001 {
3002 g_alarmMgr.DeleteAlarm(dwAlarmId);
3003 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3004 }
3005 else
3006 {
3007 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3008 }
3009 }
3010 else
3011 {
3012 // Normally, for existing alarms pObject will not be NULL,
3013 // so we assume that alarm id is invalid
3014 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
3015 }
3016
3017 // Send responce
3018 SendMessage(&msg);
3019 }
3020
3021
3022 //
3023 // Lock/unlock action configuration database
3024 //
3025
3026 void ClientSession::LockActionDB(DWORD dwRqId, BOOL bLock)
3027 {
3028 CSCPMessage msg;
3029 char szBuffer[256];
3030
3031 // Prepare responce message
3032 msg.SetCode(CMD_REQUEST_COMPLETED);
3033 msg.SetId(dwRqId);
3034
3035 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
3036 {
3037 if (bLock)
3038 {
3039 if (!LockComponent(CID_ACTION_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
3040 {
3041 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3042 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3043 }
3044 else
3045 {
3046 m_dwFlags |= CSF_ACTION_DB_LOCKED;
3047 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3048 }
3049 }
3050 else
3051 {
3052 if (m_dwFlags & CSF_ACTION_DB_LOCKED)
3053 {
3054 UnlockComponent(CID_ACTION_DB);
3055 m_dwFlags &= ~CSF_ACTION_DB_LOCKED;
3056 }
3057 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3058 }
3059 }
3060 else
3061 {
3062 // Current user has no rights for action management
3063 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3064 }
3065
3066 // Send responce
3067 SendMessage(&msg);
3068 }
3069
3070
3071 //
3072 // Create new action
3073 //
3074
3075 void ClientSession::CreateAction(CSCPMessage *pRequest)
3076 {
3077 CSCPMessage msg;
3078
3079 // Prepare responce message
3080 msg.SetCode(CMD_REQUEST_COMPLETED);
3081 msg.SetId(pRequest->GetId());
3082
3083 // Check user rights
3084 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3085 {
3086 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3087 }
3088 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3089 {
3090 // Action database have to be locked before any
3091 // changes can be made
3092 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3093 }
3094 else
3095 {
3096 DWORD dwResult, dwActionId;
3097 char szActionName[MAX_USER_NAME];
3098
3099 pRequest->GetVariableStr(VID_ACTION_NAME, szActionName, MAX_OBJECT_NAME);
3100 if (IsValidObjectName(szActionName))
3101 {
3102 dwResult = CreateNewAction(szActionName, &dwActionId);
3103 msg.SetVariable(VID_RCC, dwResult);
3104 if (dwResult == RCC_SUCCESS)
3105 msg.SetVariable(VID_ACTION_ID, dwActionId); // Send id of new action to client
3106 }
3107 else
3108 {
3109 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
3110 }
3111 }
3112
3113 // Send responce
3114 SendMessage(&msg);
3115 }
3116
3117
3118 //
3119 // Update existing action's data
3120 //
3121
3122 void ClientSession::UpdateAction(CSCPMessage *pRequest)
3123 {
3124 CSCPMessage msg;
3125
3126 // Prepare responce message
3127 msg.SetCode(CMD_REQUEST_COMPLETED);
3128 msg.SetId(pRequest->GetId());
3129
3130 // Check user rights
3131 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3132 {
3133 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3134 }
3135 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3136 {
3137 // Action database have to be locked before any
3138 // changes can be made
3139 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3140 }
3141 else
3142 {
3143 msg.SetVariable(VID_RCC, ModifyActionFromMessage(pRequest));
3144 }
3145
3146 // Send responce
3147 SendMessage(&msg);
3148 }
3149
3150
3151 //
3152 // Delete action
3153 //
3154
3155 void ClientSession::DeleteAction(CSCPMessage *pRequest)
3156 {
3157 CSCPMessage msg;
3158 DWORD dwActionId;
3159
3160 // Prepare responce message
3161 msg.SetCode(CMD_REQUEST_COMPLETED);
3162 msg.SetId(pRequest->GetId());
3163
3164 // Check user rights
3165 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
3166 {
3167 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3168 }
3169 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
3170 {
3171 // Action database have to be locked before any
3172 // changes can be made
3173 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3174 }
3175 else
3176 {
3177 // Get Id of action to be deleted
3178 dwActionId = pRequest->GetVariableLong(VID_ACTION_ID);
3179 if (!g_pEventPolicy->ActionInUse(dwActionId))
3180 {
3181 msg.SetVariable(VID_RCC, DeleteActionFromDB(dwActionId));
3182 }
3183 else
3184 {
3185 msg.SetVariable(VID_RCC, RCC_ACTION_IN_USE);
3186 }
3187 }
3188
3189 // Send responce
3190 SendMessage(&msg);
3191 }
3192
3193
3194 //
3195 // Process changes in actions
3196 //
3197
3198 void ClientSession::OnActionDBUpdate(DWORD dwCode, NXC_ACTION *pAction)
3199 {
3200 UPDATE_INFO *pUpdate;
3201
3202 if (IsAuthenticated())
3203 {
3204 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
3205 {
3206 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
3207 pUpdate->dwCategory = INFO_CAT_ACTION;
3208 pUpdate->dwCode = dwCode;
3209 pUpdate->pData = nx_memdup(pAction, sizeof(NXC_ACTION));
3210 m_pUpdateQueue->Put(pUpdate);
3211 }
3212 }
3213 }
3214
3215
3216 //
3217 // Send all actions to client
3218 //
3219
3220 void ClientSession::SendAllActions(DWORD dwRqId)
3221 {
3222 CSCPMessage msg;
3223
3224 // Prepare responce message
3225 msg.SetCode(CMD_REQUEST_COMPLETED);
3226 msg.SetId(dwRqId);
3227
3228 // Check user rights
3229 if ((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS) ||
3230 (m_dwSystemAccess & SYSTEM_ACCESS_EPP))
3231 {
3232 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3233 SendMessage(&msg);
3234 MutexLock(m_mutexSendActions, INFINITE);
3235 SendActionsToClient(this, dwRqId);
3236 MutexUnlock(m_mutexSendActions);
3237 }
3238 else
3239 {
3240 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3241 SendMessage(&msg);
3242 }
3243 }
3244
3245
3246 //
3247 // Send list of configured container categories to client
3248 //
3249
3250 void ClientSession::SendContainerCategories(DWORD dwRqId)
3251 {
3252 CSCPMessage msg;
3253 DWORD i;
3254
3255 // Prepare responce message
3256 msg.SetCode(CMD_CONTAINER_CAT_DATA);
3257 msg.SetId(dwRqId);
3258
3259 for(i = 0; i < g_dwNumCategories; i++)
3260 {
3261 msg.SetVariable(VID_CATEGORY_ID, g_pContainerCatList[i].dwCatId);
3262 msg.SetVariable(VID_CATEGORY_NAME, g_pContainerCatList[i].szName);
3263 msg.SetVariable(VID_IMAGE_ID, g_pContainerCatList[i].dwImageId);
3264 msg.SetVariable(VID_DESCRIPTION, g_pContainerCatList[i].pszDescription);
3265 SendMessage(&msg);
3266 msg.DeleteAllVariables();
3267 }
3268
3269 // Send end-of-list indicator
3270 msg.SetVariable(VID_CATEGORY_ID, (DWORD)0);
3271 SendMessage(&msg);
3272 }
3273
3274
3275 //
3276 // Perform a forced node poll
3277 //
3278
3279 void ClientSession::ForcedNodePoll(CSCPMessage *pRequest)
3280 {
3281 CSCPMessage msg;
3282 POLLER_START_DATA *pData;
3283 NetObj *pObject;
3284
3285 pData = (POLLER_START_DATA *)malloc(sizeof(POLLER_START_DATA));
3286 pData->pSession = this;
3287 MutexLock(m_mutexPollerInit, INFINITE);
3288
3289 // Prepare responce message
3290 pData->dwRqId = pRequest->GetId();
3291 msg.SetCode(CMD_POLLING_INFO);
3292 msg.SetId(pData->dwRqId);
3293
3294 // Get polling type
3295 pData->iPollType = pRequest->GetVariableShort(VID_POLL_TYPE);
3296
3297 // Find object to be deleted
3298 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3299 if (pObject != NULL)
3300 {
3301 // We can do polls only for node objects
3302 if ((pObject->Type() == OBJECT_NODE) &&
3303 ((pData->iPollType == POLL_STATUS) || (pData->iPollType == POLL_CONFIGURATION)))
3304 {
3305 // Check access rights
3306 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
3307 {
3308 ((Node *)pObject)->IncRefCount();
3309 m_dwRefCount++;
3310
3311 pData->pNode = (Node *)pObject;
3312 ThreadCreate(PollerThreadStarter, 0, pData);
3313 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
3314 msg.SetVariable(VID_POLLER_MESSAGE, _T("Poll request accepted\r\n"));
3315 }
3316 else
3317 {
3318 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3319 }
3320 }
3321 else
3322 {
3323 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3324 }
3325 }
3326 else
3327 {
3328 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3329 }
3330
3331 // Send responce
3332 SendMessage(&msg);
3333 MutexUnlock(m_mutexPollerInit);
3334 }
3335
3336
3337 //
3338 // Send message fro poller to client
3339 //
3340
3341 void ClientSession::SendPollerMsg(DWORD dwRqId, TCHAR *pszMsg)
3342 {
3343 CSCPMessage msg;
3344
3345 msg.SetCode(CMD_POLLING_INFO);
3346 msg.SetId(dwRqId);
3347 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
3348 msg.SetVariable(VID_POLLER_MESSAGE, pszMsg);
3349 SendMessage(&msg);
3350 }
3351
3352
3353 //
3354 // Node poller thread
3355 //
3356
3357 void ClientSession::PollerThread(Node *pNode, int iPollType, DWORD dwRqId)
3358 {
3359 CSCPMessage msg;
3360
3361 // Wait while parent thread finishes initialization
3362 MutexLock(m_mutexPollerInit, INFINITE);
3363 MutexUnlock(m_mutexPollerInit);
3364
3365 switch(iPollType)
3366 {
3367 case POLL_STATUS:
3368 pNode->StatusPoll(this, dwRqId);
3369 break;
3370 case POLL_CONFIGURATION:
3371 pNode->ConfigurationPoll(this, dwRqId);
3372 break;
3373 default:
3374 SendPollerMsg(dwRqId, _T("Invalid poll type requested\r\n"));
3375 break;
3376 }
3377 pNode->DecRefCount();
3378
3379 msg.SetCode(CMD_POLLING_INFO);
3380 msg.SetId(dwRqId);
3381 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3382 SendMessage(&msg);
3383 }
3384
3385
3386 //
3387 // Receive event from user
3388 //
3389
3390 void ClientSession::OnTrap(CSCPMessage *pRequest)
3391 {
3392 CSCPMessage msg;
3393 DWORD dwObjectId, dwEventCode;
3394 int i, iNumArgs;
3395 NetObj *pObject;
3396 TCHAR *pszArgList[32];
3397 TCHAR szFormat[] = "ssssssssssssssssssssssssssssssss";
3398 BOOL bSuccess;
3399
3400 // Prepare responce message
3401 msg.SetCode(CMD_REQUEST_COMPLETED);
3402 msg.SetId(pRequest->GetId());
3403
3404 // Find event's source object
3405 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
3406 if (dwObjectId != 0)
3407 pObject = FindObjectById(dwObjectId); // Object is specified explicitely
3408 else
3409 pObject = FindNodeByIP(m_dwHostAddr); // Client is the source
3410 if (pObject != NULL)
3411 {
3412 // User should have SEND_EVENTS access right to object
3413 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_SEND_EVENTS))
3414 {
3415 dwEventCode = pRequest->GetVariableLong(VID_EVENT_CODE);
3416 iNumArgs = pRequest->GetVariableShort(VID_NUM_ARGS);
3417 for(i = 0; i < iNumArgs; i++)
3418 pszArgList[i] = pRequest->GetVariableStr(VID_EVENT_ARG_BASE + i);
3419
3420 // Following call is not very good, but I'm too lazy now
3421 // to change PostEvent()
3422 szFormat[iNumArgs] = 0;
3423 bSuccess = PostEvent(dwEventCode, pObject->Id(), (iNumArgs > 0) ? szFormat : NULL,
3424 pszArgList[0], pszArgList[1], pszArgList[2], pszArgList[3],
3425 pszArgList[4], pszArgList[5], pszArgList[6], pszArgList[7],
3426 pszArgList[8], pszArgList[9], pszArgList[10], pszArgList[11],
3427 pszArgList[12], pszArgList[13], pszArgList[14], pszArgList[15],
3428 pszArgList[16], pszArgList[17], pszArgList[18], pszArgList[19],
3429 pszArgList[20], pszArgList[21], pszArgList[22], pszArgList[23],
3430 pszArgList[24], pszArgList[25], pszArgList[26], pszArgList[27],
3431 pszArgList[28], pszArgList[29], pszArgList[30], pszArgList[31]);
3432
3433 // Cleanup
3434 for(i = 0; i < iNumArgs; i++)
3435 free(pszArgList[i]);
3436
3437 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_EVENT_CODE);
3438 }
3439 else
3440 {
3441 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3442 }
3443 }
3444 else
3445 {
3446 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3447 }
3448
3449 // Send responce
3450 SendMessage(&msg);
3451 }
3452
3453
3454 //
3455 // Wake up node
3456 //
3457
3458 void ClientSession::OnWakeUpNode(CSCPMessage *pRequest)
3459 {
3460 NetObj *pObject;
3461 CSCPMessage msg;
3462
3463 // Prepare responce message
3464 msg.SetCode(CMD_REQUEST_COMPLETED);
3465 msg.SetId(pRequest->GetId());
3466
3467 // Find node or interface object
3468 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3469 if (pObject != NULL)
3470 {
3471 if ((pObject->Type() == OBJECT_NODE) ||
3472 (pObject->Type() == OBJECT_INTERFACE))
3473 {
3474 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3475 {
3476 DWORD dwResult;
3477
3478 if (pObject->Type() == OBJECT_NODE)
3479 dwResult = ((Node *)pObject)->WakeUp();
3480 else
3481 dwResult = ((Interface *)pObject)->WakeUp();
3482 msg.SetVariable(VID_RCC, dwResult);
3483 }
3484 else
3485 {
3486 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3487 }
3488 }
3489 else
3490 {
3491 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3492 }
3493 }
3494 else
3495 {
3496 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3497 }
3498
3499 // Send responce
3500 SendMessage(&msg);
3501 }
3502
3503
3504 //
3505 // Query specific parameter from node
3506 //
3507
3508 void ClientSession::QueryParameter(CSCPMessage *pRequest)
3509 {
3510 NetObj *pObject;
3511 CSCPMessage msg;
3512
3513 // Prepare responce message
3514 msg.SetCode(CMD_REQUEST_COMPLETED);
3515 msg.SetId(pRequest->GetId());
3516
3517 // Find node object
3518 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3519 if (pObject != NULL)
3520 {
3521 if (pObject->Type() == OBJECT_NODE)
3522 {
3523 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3524 {
3525 DWORD dwResult;
3526 TCHAR szBuffer[256], szName[MAX_PARAM_NAME];
3527
3528 pRequest->GetVariableStr(VID_NAME, szName, MAX_PARAM_NAME);
3529 dwResult = ((Node *)pObject)->GetItemForClient(pRequest->GetVariableShort(VID_DCI_SOURCE_TYPE),
3530 szName, szBuffer, 256);
3531 msg.SetVariable(VID_RCC, dwResult);
3532 if (dwResult == RCC_SUCCESS)
3533 msg.SetVariable(VID_VALUE, szBuffer);
3534 }
3535 else
3536 {
3537 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3538 }
3539 }
3540 else
3541 {
3542 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3543 }
3544 }
3545 else
3546 {
3547 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3548 }
3549
3550 // Send responce
3551 SendMessage(&msg);
3552 }
3553
3554
3555 //
3556 // Edit trap configuration record
3557 //
3558
3559 void ClientSession::EditTrap(int iOperation, CSCPMessage *pRequest)
3560 {
3561 CSCPMessage msg;
3562 DWORD dwTrapId, dwResult;
3563
3564 // Prepare responce message
3565 msg.SetCode(CMD_REQUEST_COMPLETED);
3566 msg.SetId(pRequest->GetId());
3567
3568 // Check access rights
3569 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3570 {
3571 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3572 {
3573 switch(iOperation)
3574 {
3575 case TRAP_CREATE:
3576 dwResult = CreateNewTrap(&dwTrapId);
3577 msg.SetVariable(VID_RCC, dwResult);
3578 if (dwResult == RCC_SUCCESS)
3579 msg.SetVariable(VID_TRAP_ID, dwTrapId); // Send id of new trap to client
3580 break;
3581 case TRAP_UPDATE:
3582 msg.SetVariable(VID_RCC, UpdateTrapFromMsg(pRequest));
3583 break;
3584 case TRAP_DELETE:
3585 dwTrapId = pRequest->GetVariableLong(VID_TRAP_ID);
3586 msg.SetVariable(VID_RCC, DeleteTrap(dwTrapId));
3587 break;
3588 default:
3589 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
3590 break;
3591 }
3592 }
3593 else
3594 {
3595 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3596 }
3597 }
3598 else
3599 {
3600 // Current user has no rights for trap management
3601 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3602 }
3603
3604 // Send responce
3605 SendMessage(&msg);
3606 }
3607
3608
3609 //
3610 // Lock/unlock trap configuration
3611 //
3612
3613 void ClientSession::LockTrapCfg(DWORD dwRqId, BOOL bLock)
3614 {
3615 CSCPMessage msg;
3616 char szBuffer[256];
3617
3618 // Prepare responce message
3619 msg.SetCode(CMD_REQUEST_COMPLETED);
3620 msg.SetId(dwRqId);
3621
3622 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3623 {
3624 if (bLock)
3625 {
3626 if (!LockComponent(CID_TRAP_CFG, m_dwIndex, m_szUserName, NULL, szBuffer))
3627 {
3628 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3629 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3630 }
3631 else
3632 {
3633 m_dwFlags |= CSF_TRAP_CFG_LOCKED;
3634 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3635 }
3636 }
3637 else
3638 {
3639 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3640 {
3641 UnlockComponent(CID_TRAP_CFG);
3642 m_dwFlags &= ~CSF_TRAP_CFG_LOCKED;
3643 }
3644 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3645 }
3646 }
3647 else
3648 {
3649 // Current user has no rights for trap management
3650 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3651 }
3652
3653 // Send responce
3654 SendMessage(&msg);
3655 }
3656
3657
3658 //
3659 // Send all trap configuration records to client
3660 //
3661
3662 void ClientSession::SendAllTraps(DWORD dwRqId)
3663 {
3664 CSCPMessage msg;
3665 BOOL bSuccess = FALSE;
3666
3667 // Prepare responce message
3668 msg.SetCode(CMD_REQUEST_COMPLETED);
3669 msg.SetId(dwRqId);
3670
3671 if (m_dwSystemAccess & SYSTEM_ACCESS_CONFIGURE_TRAPS)
3672 {
3673 if (m_dwFlags & CSF_TRAP_CFG_LOCKED)
3674 {
3675 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3676 SendMessage(&msg);
3677 bSuccess = TRUE;
3678 SendTrapsToClient(this, dwRqId);
3679 }
3680 else
3681 {
3682 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3683 }
3684 }
3685 else
3686 {
3687 // Current user has no rights for trap management
3688 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3689 }
3690
3691 // Send responce
3692 if (!bSuccess)
3693 SendMessage(&msg);
3694 }
3695
3696
3697 //
3698 // Lock/unlock package database
3699 //
3700
3701 void ClientSession::LockPackageDB(DWORD dwRqId, BOOL bLock)
3702 {
3703 CSCPMessage msg;
3704 char szBuffer[256];
3705
3706 // Prepare responce message
3707 msg.SetCode(CMD_REQUEST_COMPLETED);
3708 msg.SetId(dwRqId);
3709
3710 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3711 {
3712 if (bLock)
3713 {
3714 if (!LockComponent(CID_PACKAGE_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
3715 {
3716 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
3717 msg.SetVariable(VID_LOCKED_BY, szBuffer);
3718 }
3719 else
3720 {
3721 m_dwFlags |= CSF_PACKAGE_DB_LOCKED;
3722 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3723 }
3724 }
3725 else
3726 {
3727 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3728 {
3729 UnlockComponent(CID_PACKAGE_DB);
3730 m_dwFlags &= ~CSF_PACKAGE_DB_LOCKED;
3731 }
3732 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3733 }
3734 }
3735 else
3736 {
3737 // Current user has no rights for trap management
3738 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3739 }
3740
3741 // Send responce
3742 SendMessage(&msg);
3743 }
3744
3745
3746 //
3747 // Send list of all installed packages to client
3748 //
3749
3750 void ClientSession::SendAllPackages(DWORD dwRqId)
3751 {
3752 CSCPMessage msg;
3753 DB_ASYNC_RESULT hResult;
3754 BOOL bSuccess = FALSE;
3755 TCHAR szBuffer[MAX_DB_STRING];
3756
3757 // Prepare responce message
3758 msg.SetCode(CMD_REQUEST_COMPLETED);
3759 msg.SetId(dwRqId);
3760
3761 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3762 {
3763 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3764 {
3765 hResult = DBAsyncSelect(g_hCoreDB, "SELECT pkg_id,version,platform,pkg_file,pkg_name,description FROM agent_pkg");
3766 if (hResult != NULL)
3767 {
3768 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3769 SendMessage(&msg);
3770 bSuccess = TRUE;
3771
3772 msg.SetCode(CMD_PACKAGE_INFO);
3773 msg.DeleteAllVariables();
3774
3775 while(DBFetch(hResult))
3776 {
3777 msg.SetVariable(VID_PACKAGE_ID, DBGetFieldAsyncULong(hResult, 0));
3778 msg.SetVariable(VID_PACKAGE_VERSION, DBGetFieldAsync(hResult, 1, szBuffer, MAX_DB_STRING));
3779 msg.SetVariable(VID_PLATFORM_NAME, DBGetFieldAsync(hResult, 2, szBuffer, MAX_DB_STRING));
3780 msg.SetVariable(VID_FILE_NAME, DBGetFieldAsync(hResult, 3, szBuffer, MAX_DB_STRING));
3781 msg.SetVariable(VID_PACKAGE_NAME, DBGetFieldAsync(hResult, 4, szBuffer, MAX_DB_STRING));
3782 DBGetFieldAsync(hResult, 5, szBuffer, MAX_DB_STRING);
3783 DecodeSQLString(szBuffer);
3784 msg.SetVariable(VID_DESCRIPTION, szBuffer);
3785 SendMessage(&msg);
3786 msg.DeleteAllVariables();
3787 }
3788
3789 msg.SetVariable(VID_PACKAGE_ID, (DWORD)0);
3790 SendMessage(&msg);
3791
3792 DBFreeAsyncResult(hResult);
3793 }
3794 else
3795 {
3796 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
3797 }
3798 }
3799 else
3800 {
3801 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3802 }
3803 }
3804 else
3805 {
3806 // Current user has no rights for package management
3807 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3808 }
3809
3810 // Send responce
3811 if (!bSuccess)
3812 SendMessage(&msg);
3813 }
3814
3815
3816 //
3817 // Install package to server
3818 //
3819
3820 void ClientSession::InstallPackage(CSCPMessage *pRequest)
3821 {
3822 CSCPMessage msg;
3823 TCHAR szPkgName[MAX_PACKAGE_NAME_LEN], szDescription[MAX_DB_STRING];
3824 TCHAR szPkgVersion[MAX_AGENT_VERSION_LEN], szFileName[MAX_DB_STRING];
3825 TCHAR szPlatform[MAX_PLATFORM_NAME_LEN], *pszCleanFileName, *pszEscDescr;
3826 TCHAR szQuery[2048];
3827
3828 // Prepare responce message
3829 msg.SetCode(CMD_REQUEST_COMPLETED);
3830 msg.SetId(pRequest->GetId());
3831
3832 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3833 {
3834 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3835 {
3836 pRequest->GetVariableStr(VID_PACKAGE_NAME, szPkgName, MAX_PACKAGE_NAME_LEN);
3837 pRequest->GetVariableStr(VID_DESCRIPTION, szDescription, MAX_DB_STRING);
3838 pRequest->GetVariableStr(VID_FILE_NAME, szFileName, MAX_DB_STRING);
3839 pRequest->GetVariableStr(VID_PACKAGE_VERSION, szPkgVersion, MAX_AGENT_VERSION_LEN);
3840 pRequest->GetVariableStr(VID_PLATFORM_NAME, szPlatform, MAX_PLATFORM_NAME_LEN);
3841
3842 // Remove possible path specification from file name
3843 pszCleanFileName = GetCleanFileName(szFileName);
3844
3845 if (IsValidObjectName(pszCleanFileName) &&
3846 IsValidObjectName(szPkgName) &&
3847 IsValidObjectName(szPkgVersion) &&
3848 IsValidObjectName(szPlatform))
3849 {
3850 // Check if same package already exist
3851 if (!IsPackageInstalled(szPkgName, szPkgVersion, szPlatform))
3852 {
3853 // Check for duplicate file name
3854 if (!IsPackageFileExist(pszCleanFileName))
3855 {
3856 // Prepare for file receive
3857 if (m_hCurrFile == -1)
3858 {
3859 _tcscpy(m_szCurrFileName, g_szDataDir);
3860 _tcscat(m_szCurrFileName, DDIR_PACKAGES);
3861 _tcscat(m_szCurrFileName, FS_PATH_SEPARATOR);
3862 _tcscat(m_szCurrFileName, pszCleanFileName);
3863 m_hCurrFile = _topen(m_szCurrFileName, O_CREAT | O_TRUNC | O_WRONLY | O_BINARY, S_IRUSR | S_IWUSR);
3864 if (m_hCurrFile != -1)
3865 {
3866 m_dwFileRqId = pRequest->GetId();
3867 m_dwUploadCommand = CMD_INSTALL_PACKAGE;
3868 m_dwUploadData = CreateUniqueId(IDG_PACKAGE);
3869 msg.SetVariable(VID_RCC, RCC_SUCCESS);
3870 msg.SetVariable(VID_PACKAGE_ID, m_dwUploadData);
3871
3872 // Create record in database
3873 pszEscDescr = EncodeSQLString(szDescription);
3874 _sntprintf(szQuery, 2048, _T("INSERT INTO agent_pkg (pkg_id,pkg_name,"
3875 "version,description,platform,pkg_file) "
3876 "VALUES (%ld,'%s','%s','%s','%s','%s')"),
3877 m_dwUploadData, szPkgName, szPkgVersion, pszEscDescr,
3878 szPlatform, pszCleanFileName);
3879 free(pszEscDescr);
3880 DBQuery(g_hCoreDB, szQuery);
3881 }
3882 else
3883 {
3884 msg.SetVariable(VID_RCC, RCC_IO_ERROR);
3885 }
3886 }
3887 else
3888 {
3889 msg.SetVariable(VID_RCC, RCC_RESOURCE_BUSY);
3890 }
3891 }
3892 else
3893 {
3894 msg.SetVariable(VID_RCC, RCC_PACKAGE_FILE_EXIST);
3895 }
3896 }
3897 else
3898 {
3899 msg.SetVariable(VID_RCC, RCC_DUPLICATE_PACKAGE);
3900 }
3901 }
3902 else
3903 {
3904 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
3905 }
3906 }
3907 else
3908 {
3909 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3910 }
3911 }
3912 else
3913 {
3914 // Current user has no rights for package management
3915 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3916 }
3917
3918 // Send responce
3919 SendMessage(&msg);
3920 }
3921
3922
3923 //
3924 // Remove package from server
3925 //
3926
3927 void ClientSession::RemovePackage(CSCPMessage *pRequest)
3928 {
3929 CSCPMessage msg;
3930 DWORD dwPkgId;
3931
3932 // Prepare responce message
3933 msg.SetCode(CMD_REQUEST_COMPLETED);
3934 msg.SetId(pRequest->GetId());
3935
3936 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_PACKAGES)
3937 {
3938 if (m_dwFlags & CSF_PACKAGE_DB_LOCKED)
3939 {
3940 dwPkgId = pRequest->GetVariableLong(VID_PACKAGE_ID);
3941 msg.SetVariable(VID_RCC, UninstallPackage(dwPkgId));
3942 }
3943 else
3944 {
3945 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3946 }
3947 }
3948 else
3949 {
3950 // Current user has no rights for package management
3951 msg.