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