- All component locks moved to memory
[public/netxms.git] / src / server / core / session.cpp
CommitLineData
21e4b6f0
VK
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 "nms_core.h"
24
06e7be2f 25#ifdef _WIN32
c9ccd685
AK
26# include <direct.h>
27#else
28# include <dirent.h>
06e7be2f
VK
29#endif
30
21e4b6f0 31
ccdbbb52
VK
32//
33// Externals
34//
35
36void UnregisterSession(DWORD dwIndex);
37
38
d966d18a
VK
39//
40// Node poller start data
41//
42
43typedef struct
44{
45 ClientSession *pSession;
46 Node *pNode;
47 int iPollType;
48 DWORD dwRqId;
49} POLLER_START_DATA;
50
51
2d5c8ac8
VK
52//
53// Fill CSCP message with user data
54//
55
56static void FillUserInfoMessage(CSCPMessage *pMsg, NMS_USER *pUser)
57{
58 pMsg->SetVariable(VID_USER_ID, pUser->dwId);
59 pMsg->SetVariable(VID_USER_NAME, pUser->szName);
60 pMsg->SetVariable(VID_USER_FLAGS, pUser->wFlags);
61 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pUser->wSystemRights);
62 pMsg->SetVariable(VID_USER_FULL_NAME, pUser->szFullName);
63 pMsg->SetVariable(VID_USER_DESCRIPTION, pUser->szDescription);
64}
65
66
67//
68// Fill CSCP message with user group data
69//
70
71static void FillGroupInfoMessage(CSCPMessage *pMsg, NMS_USER_GROUP *pGroup)
72{
73 DWORD i, dwId;
74
75 pMsg->SetVariable(VID_USER_ID, pGroup->dwId);
76 pMsg->SetVariable(VID_USER_NAME, pGroup->szName);
77 pMsg->SetVariable(VID_USER_FLAGS, pGroup->wFlags);
78 pMsg->SetVariable(VID_USER_SYS_RIGHTS, pGroup->wSystemRights);
79 pMsg->SetVariable(VID_USER_DESCRIPTION, pGroup->szDescription);
80 pMsg->SetVariable(VID_NUM_MEMBERS, pGroup->dwNumMembers);
81 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < pGroup->dwNumMembers; i++, dwId++)
82 pMsg->SetVariable(dwId, pGroup->pMembers[i]);
83}
84
85
ccdbbb52
VK
86//
87// Client communication read thread starter
88//
89
90THREAD_RESULT THREAD_CALL ClientSession::ReadThreadStarter(void *pArg)
91{
92 ((ClientSession *)pArg)->ReadThread();
93
94 // When ClientSession::ReadThread exits, all other session
95 // threads are already stopped, so we can safely destroy
96 // session object
97 UnregisterSession(((ClientSession *)pArg)->GetIndex());
98 delete (ClientSession *)pArg;
99 return THREAD_OK;
100}
101
102
103//
104// Client communication write thread starter
105//
106
107THREAD_RESULT THREAD_CALL ClientSession::WriteThreadStarter(void *pArg)
108{
109 ((ClientSession *)pArg)->WriteThread();
110 return THREAD_OK;
111}
112
113
114//
115// Received message processing thread starter
116//
117
118THREAD_RESULT THREAD_CALL ClientSession::ProcessingThreadStarter(void *pArg)
119{
120 ((ClientSession *)pArg)->ProcessingThread();
121 return THREAD_OK;
122}
123
124
125//
126// Information update processing thread starter
127//
128
129THREAD_RESULT THREAD_CALL ClientSession::UpdateThreadStarter(void *pArg)
130{
131 ((ClientSession *)pArg)->UpdateThread();
132 return THREAD_OK;
133}
134
135
d966d18a
VK
136//
137// Forced node poll thread starter
138//
139
140THREAD_RESULT THREAD_CALL ClientSession::PollerThreadStarter(void *pArg)
141{
142 ((POLLER_START_DATA *)pArg)->pSession->PollerThread(
143 ((POLLER_START_DATA *)pArg)->pNode,
144 ((POLLER_START_DATA *)pArg)->iPollType,
145 ((POLLER_START_DATA *)pArg)->dwRqId);
146 free(pArg);
147 return THREAD_OK;
148}
149
150
21e4b6f0
VK
151//
152// Client session class constructor
153//
154
b54b2b11 155ClientSession::ClientSession(SOCKET hSocket, DWORD dwHostAddr)
21e4b6f0
VK
156{
157 m_pSendQueue = new Queue;
158 m_pMessageQueue = new Queue;
62f5857f 159 m_pUpdateQueue = new Queue;
21e4b6f0
VK
160 m_hSocket = hSocket;
161 m_dwIndex = INVALID_INDEX;
162 m_iState = STATE_CONNECTED;
163 m_pMsgBuffer = (CSCP_BUFFER *)malloc(sizeof(CSCP_BUFFER));
ccdbbb52
VK
164 m_hWriteThread = INVALID_THREAD_HANDLE;
165 m_hProcessingThread = INVALID_THREAD_HANDLE;
166 m_hUpdateThread = INVALID_THREAD_HANDLE;
03482383
VK
167 m_mutexSendEvents = MutexCreate();
168 m_mutexSendObjects = MutexCreate();
169 m_mutexSendAlarms = MutexCreate();
c9363772 170 m_mutexSendActions = MutexCreate();
d966d18a 171 m_mutexPollerInit = MutexCreate();
b54b2b11
VK
172 m_dwFlags = 0;
173 m_dwHostAddr = dwHostAddr;
174 strcpy(m_szUserName, "<not logged in>");
984542f8 175 m_dwUserId = INVALID_INDEX;
338493a0
VK
176 m_dwOpenDCIListSize = 0;
177 m_pOpenDCIList = NULL;
8f7e2482 178 m_ppEPPRuleList = NULL;
21e4b6f0
VK
179}
180
181
182//
183// Destructor
184//
185
186ClientSession::~ClientSession()
187{
188 shutdown(m_hSocket, 2);
189 closesocket(m_hSocket);
190 delete m_pSendQueue;
191 delete m_pMessageQueue;
62f5857f 192 delete m_pUpdateQueue;
338493a0 193 safe_free(m_pMsgBuffer);
03482383
VK
194 MutexDestroy(m_mutexSendEvents);
195 MutexDestroy(m_mutexSendObjects);
196 MutexDestroy(m_mutexSendAlarms);
c9363772 197 MutexDestroy(m_mutexSendActions);
d966d18a 198 MutexDestroy(m_mutexPollerInit);
338493a0 199 safe_free(m_pOpenDCIList);
8f7e2482
VK
200 if (m_ppEPPRuleList != NULL)
201 {
202 DWORD i;
203
204 if (m_dwFlags & CSF_EPP_UPLOAD) // Aborted in the middle of EPP transfer
205 for(i = 0; i < m_dwRecordsUploaded; i++)
206 delete m_ppEPPRuleList[i];
207 free(m_ppEPPRuleList);
208 }
21e4b6f0
VK
209}
210
211
ccdbbb52
VK
212//
213// Start all threads
214//
215
216void ClientSession::Run(void)
217{
218 m_hWriteThread = ThreadCreateEx(WriteThreadStarter, 0, this);
219 m_hProcessingThread = ThreadCreateEx(ProcessingThreadStarter, 0, this);
220 m_hUpdateThread = ThreadCreateEx(UpdateThreadStarter, 0, this);
221 ThreadCreate(ReadThreadStarter, 0, this);
222}
223
224
21e4b6f0
VK
225//
226// Print debug information
227//
228
229void ClientSession::DebugPrintf(char *szFormat, ...)
230{
231 if ((g_dwFlags & AF_STANDALONE) && (g_dwFlags & AF_DEBUG_CSCP))
232 {
233 va_list args;
234
235 printf("*CSCP(%d)* ", m_dwIndex);
236 va_start(args, szFormat);
237 vprintf(szFormat, args);
238 va_end(args);
239 }
240}
241
242
21e4b6f0
VK
243//
244// ReadThread()
245//
246
247void ClientSession::ReadThread(void)
248{
249 CSCP_MESSAGE *pRawMsg;
250 CSCPMessage *pMsg;
251 int iErr;
338493a0
VK
252 DWORD i;
253 NetObj *pObject;
21e4b6f0
VK
254
255 // Initialize raw message receiving function
a933a2bf 256 RecvCSCPMessage(0, NULL, m_pMsgBuffer, 0);
21e4b6f0
VK
257
258 pRawMsg = (CSCP_MESSAGE *)malloc(65536);
259 while(1)
260 {
a933a2bf 261 if ((iErr = RecvCSCPMessage(m_hSocket, pRawMsg, m_pMsgBuffer, 65536)) <= 0)
21e4b6f0
VK
262 break;
263
a933a2bf
VK
264 // Check if message is too large
265 if (iErr == 1)
266 continue;
267
21e4b6f0 268 // Check that actual received packet size is equal to encoded in packet
6159a875 269 if ((int)ntohl(pRawMsg->dwSize) != iErr)
21e4b6f0 270 {
6159a875 271 DebugPrintf("Actual message size doesn't match wSize value (%d,%d)\n", iErr, ntohl(pRawMsg->dwSize));
21e4b6f0
VK
272 continue; // Bad packet, wait for next
273 }
274
275 // Create message object from raw message
276 pMsg = new CSCPMessage(pRawMsg);
277 m_pMessageQueue->Put(pMsg);
278 }
279 if (iErr < 0)
280 WriteLog(MSG_SESSION_CLOSED, EVENTLOG_WARNING_TYPE, "e", WSAGetLastError());
281 free(pRawMsg);
282
283 // Notify other threads to exit
d09b1909 284 m_pSendQueue->Clear();
ecb7e1ee 285 m_pSendQueue->Put(INVALID_POINTER_VALUE);
d09b1909 286 m_pMessageQueue->Clear();
ecb7e1ee 287 m_pMessageQueue->Put(INVALID_POINTER_VALUE);
d09b1909 288 m_pUpdateQueue->Clear();
8f7e2482 289 m_pUpdateQueue->Put(INVALID_POINTER_VALUE);
ecb7e1ee
VK
290
291 // Wait for other threads to finish
ccdbbb52
VK
292 ThreadJoin(m_hWriteThread);
293 ThreadJoin(m_hProcessingThread);
294 ThreadJoin(m_hUpdateThread);
54abbe0e
VK
295
296 // Remove all locks created by this session
297 RemoveAllSessionLocks(m_dwIndex);
338493a0
VK
298 for(i = 0; i < m_dwOpenDCIListSize; i++)
299 {
300 pObject = FindObjectById(m_pOpenDCIList[i]);
301 if (pObject != NULL)
302 if (pObject->Type() == OBJECT_NODE)
303 ((Node *)pObject)->UnlockDCIList(m_dwIndex);
304 }
8f7e2482
VK
305
306 DebugPrintf("Session closed\n");
21e4b6f0
VK
307}
308
309
310//
311// WriteThread()
312//
313
314void ClientSession::WriteThread(void)
315{
316 CSCP_MESSAGE *pMsg;
7ac0c0a8 317 char szBuffer[128];
21e4b6f0
VK
318
319 while(1)
320 {
321 pMsg = (CSCP_MESSAGE *)m_pSendQueue->GetOrBlock();
ecb7e1ee 322 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
21e4b6f0
VK
323 break;
324
6159a875
VK
325 DebugPrintf("Sending message %s\n", CSCPMessageCodeName(ntohs(pMsg->wCode), szBuffer));
326 if (send(m_hSocket, (const char *)pMsg, ntohl(pMsg->dwSize), 0) <= 0)
21e4b6f0 327 {
9d72bde1 328 safe_free(pMsg);
21e4b6f0
VK
329 break;
330 }
9d72bde1 331 safe_free(pMsg);
21e4b6f0 332 }
8f7e2482
VK
333}
334
335
336//
337// Update processing thread
338//
339
340void ClientSession::UpdateThread(void)
341{
342 UPDATE_INFO *pUpdate;
343 CSCPMessage msg;
344
8f7e2482
VK
345 while(1)
346 {
347 pUpdate = (UPDATE_INFO *)m_pUpdateQueue->GetOrBlock();
348 if (pUpdate == INVALID_POINTER_VALUE) // Session termination indicator
349 break;
350
351 switch(pUpdate->dwCategory)
352 {
353 case INFO_CAT_EVENT:
03482383 354 MutexLock(m_mutexSendEvents, INFINITE);
8f7e2482 355 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, 0, sizeof(NXC_EVENT), pUpdate->pData, NULL));
03482383 356 MutexUnlock(m_mutexSendEvents);
8f7e2482
VK
357 free(pUpdate->pData);
358 break;
359 case INFO_CAT_OBJECT_CHANGE:
03482383 360 MutexLock(m_mutexSendObjects, INFINITE);
8f7e2482 361 msg.SetCode(CMD_OBJECT_UPDATE);
03482383 362 msg.SetId(0);
8f7e2482
VK
363 ((NetObj *)pUpdate->pData)->CreateMessage(&msg);
364 SendMessage(&msg);
03482383 365 MutexUnlock(m_mutexSendObjects);
8f7e2482
VK
366 msg.DeleteAllVariables();
367 ((NetObj *)pUpdate->pData)->DecRefCount();
368 break;
03482383
VK
369 case INFO_CAT_ALARM:
370 MutexLock(m_mutexSendAlarms, INFINITE);
371 msg.SetCode(CMD_ALARM_UPDATE);
372 msg.SetId(0);
c9363772 373 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
b900a78b 374 FillAlarmInfoMessage(&msg, (NXC_ALARM *)pUpdate->pData);
49dde062 375 SendMessage(&msg);
03482383
VK
376 MutexUnlock(m_mutexSendAlarms);
377 msg.DeleteAllVariables();
c9363772
VK
378 free(pUpdate->pData);
379 break;
380 case INFO_CAT_ACTION:
381 MutexLock(m_mutexSendActions, INFINITE);
382 msg.SetCode(CMD_ACTION_DB_UPDATE);
383 msg.SetId(0);
384 msg.SetVariable(VID_NOTIFICATION_CODE, pUpdate->dwCode);
385 msg.SetVariable(VID_ACTION_ID, ((NXC_ACTION *)pUpdate->pData)->dwId);
e91cb822
VK
386 if (pUpdate->dwCode != NX_NOTIFY_ACTION_DELETED)
387 FillActionInfoMessage(&msg, (NXC_ACTION *)pUpdate->pData);
c9363772
VK
388 SendMessage(&msg);
389 MutexUnlock(m_mutexSendActions);
390 msg.DeleteAllVariables();
391 free(pUpdate->pData);
03482383 392 break;
8f7e2482
VK
393 default:
394 break;
395 }
396
397 free(pUpdate);
398 }
21e4b6f0
VK
399}
400
401
402//
403// Message processing thread
404//
405
406void ClientSession::ProcessingThread(void)
407{
3421c063 408 CSCPMessage *pMsg;
74a5aa17 409 char szBuffer[128];
21e4b6f0
VK
410
411 while(1)
412 {
413 pMsg = (CSCPMessage *)m_pMessageQueue->GetOrBlock();
ecb7e1ee 414 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
21e4b6f0
VK
415 break;
416
74a5aa17 417 DebugPrintf("Received message %s\n", CSCPMessageCodeName(pMsg->GetCode(), szBuffer));
21e4b6f0
VK
418 if ((m_iState != STATE_AUTHENTICATED) && (pMsg->GetCode() != CMD_LOGIN))
419 {
420 delete pMsg;
421 continue;
422 }
423
424 switch(pMsg->GetCode())
425 {
426 case CMD_LOGIN:
e100f091 427 Login(pMsg);
21e4b6f0
VK
428 break;
429 case CMD_GET_OBJECTS:
e100f091 430 SendAllObjects(pMsg->GetId());
21e4b6f0
VK
431 break;
432 case CMD_GET_EVENTS:
74a5aa17 433 SendAllEvents(pMsg->GetId());
21e4b6f0
VK
434 break;
435 case CMD_GET_CONFIG_VARLIST:
436 SendAllConfigVars();
437 break;
37c4d6aa 438 case CMD_LOAD_EVENT_DB:
b54b2b11
VK
439 SendEventDB(pMsg->GetId());
440 break;
37c4d6aa
VK
441 case CMD_LOCK_EVENT_DB:
442 LockEventDB(pMsg->GetId());
443 break;
444 case CMD_UNLOCK_EVENT_DB:
445 UnlockEventDB(pMsg->GetId());
b54b2b11 446 break;
605d2931
VK
447 case CMD_SET_EVENT_INFO:
448 SetEventInfo(pMsg);
449 break;
37c4d6aa
VK
450 case CMD_DELETE_EVENT_TEMPLATE:
451 DeleteEventTemplate(pMsg);
452 break;
453 case CMD_GENERATE_EVENT_ID:
454 GenerateEventId(pMsg->GetId());
455 break;
24156e90
VK
456 case CMD_MODIFY_OBJECT:
457 ModifyObject(pMsg);
458 break;
c1c39152
VK
459 case CMD_SET_OBJECT_MGMT_STATUS:
460 ChangeObjectMgmtStatus(pMsg);
461 break;
23a32988
VK
462 case CMD_LOAD_USER_DB:
463 SendUserDB(pMsg->GetId());
464 break;
ff550544
VK
465 case CMD_CREATE_USER:
466 CreateUser(pMsg);
467 break;
468 case CMD_UPDATE_USER:
469 UpdateUser(pMsg);
470 break;
471 case CMD_DELETE_USER:
472 DeleteUser(pMsg);
473 break;
474 case CMD_LOCK_USER_DB:
475 LockUserDB(pMsg->GetId(), TRUE);
476 break;
477 case CMD_UNLOCK_USER_DB:
478 LockUserDB(pMsg->GetId(), FALSE);
479 break;
017e1e13
VK
480 case CMD_SET_PASSWORD:
481 SetPassword(pMsg);
482 break;
7257eb7d
VK
483 case CMD_GET_NODE_DCI_LIST:
484 OpenNodeDCIList(pMsg);
485 break;
486 case CMD_UNLOCK_NODE_DCI_LIST:
487 CloseNodeDCIList(pMsg);
488 break;
9ed4eaff
VK
489 case CMD_CREATE_NEW_DCI:
490 case CMD_MODIFY_NODE_DCI:
491 case CMD_DELETE_NODE_DCI:
492 ModifyNodeDCI(pMsg);
493 break;
933aee5c
VK
494 case CMD_COPY_DCI:
495 CopyDCI(pMsg);
496 break;
ebebc8ea
VK
497 case CMD_GET_DCI_DATA:
498 GetCollectedData(pMsg);
499 break;
06e7be2f
VK
500 case CMD_OPEN_EPP:
501 OpenEPP(pMsg->GetId());
502 break;
503 case CMD_CLOSE_EPP:
504 CloseEPP(pMsg->GetId());
505 break;
506 case CMD_SAVE_EPP:
507 SaveEPP(pMsg);
508 break;
8f7e2482
VK
509 case CMD_EPP_RECORD:
510 ProcessEPPRecord(pMsg);
06e7be2f
VK
511 break;
512 case CMD_GET_MIB_LIST:
513 SendMIBList(pMsg->GetId());
514 break;
515 case CMD_GET_MIB:
516 SendMIB(pMsg);
517 break;
ef44d5ea
VK
518 case CMD_CREATE_OBJECT:
519 CreateObject(pMsg);
520 break;
e6b958c4
VK
521 case CMD_BIND_OBJECT:
522 ChangeObjectBinding(pMsg, TRUE);
523 break;
524 case CMD_UNBIND_OBJECT:
525 ChangeObjectBinding(pMsg, FALSE);
526 break;
f70fc197 527 case CMD_GET_IMAGE_LIST:
aa3743b2 528 SendImageCatalogue(this, pMsg->GetId(), pMsg->GetVariableShort(VID_IMAGE_FORMAT));
f70fc197
VK
529 break;
530 case CMD_LOAD_IMAGE_FILE:
aa3743b2
VK
531 SendImageFile(this, pMsg->GetId(), pMsg->GetVariableLong(VID_IMAGE_ID),
532 pMsg->GetVariableShort(VID_IMAGE_FORMAT));
8bff53f6
VK
533 break;
534 case CMD_GET_DEFAULT_IMAGE_LIST:
535 SendDefaultImageList(this, pMsg->GetId());
f70fc197 536 break;
03482383
VK
537 case CMD_GET_ALL_ALARMS:
538 SendAllAlarms(pMsg->GetId(), pMsg->GetVariableShort(VID_IS_ACK));
539 break;
540 case CMD_GET_ALARM:
541 break;
542 case CMD_ACK_ALARM:
ee20e615
VK
543 AcknowlegeAlarm(pMsg);
544 break;
545 case CMD_DELETE_ALARM:
03482383 546 break;
c9363772
VK
547 case CMD_LOCK_ACTION_DB:
548 LockActionDB(pMsg->GetId(), TRUE);
549 break;
550 case CMD_UNLOCK_ACTION_DB:
551 LockActionDB(pMsg->GetId(), FALSE);
552 break;
553 case CMD_CREATE_ACTION:
554 CreateAction(pMsg);
555 break;
556 case CMD_MODIFY_ACTION:
557 UpdateAction(pMsg);
558 break;
559 case CMD_DELETE_ACTION:
560 DeleteAction(pMsg);
561 break;
e91cb822
VK
562 case CMD_LOAD_ACTIONS:
563 SendAllActions(pMsg->GetId());
564 break;
6849d9be
VK
565 case CMD_GET_CONTAINER_CAT_LIST:
566 SendContainerCategories(pMsg->GetId());
567 break;
88039e6c
VK
568 case CMD_DELETE_OBJECT:
569 DeleteObject(pMsg);
570 break;
0b89f5fb
VK
571 case CMD_POLL_NODE:
572 ForcedNodePoll(pMsg);
573 break;
b562fca8
VK
574 case CMD_TRAP:
575 OnTrap(pMsg);
576 break;
ed1140dc
VK
577 case CMD_WAKEUP_NODE:
578 OnWakeUpNode(pMsg);
579 break;
b4895bbe
VK
580 case CMD_LOCK_TRAP_CFG:
581 LockTrapCfg(pMsg->GetId(), TRUE);
582 break;
583 case CMD_UNLOCK_TRAP_CFG:
584 LockTrapCfg(pMsg->GetId(), FALSE);
585 break;
586 case CMD_CREATE_TRAP:
587 CreateTrap(pMsg);
588 break;
589 case CMD_MODIFY_TRAP:
590 UpdateTrap(pMsg);
591 break;
592 case CMD_DELETE_TRAP:
593 DeleteTrap(pMsg);
594 break;
595 case CMD_LOAD_TRAP_LIST:
596 SendAllTraps(pMsg->GetId());
597 break;
21e4b6f0 598 default:
37c4d6aa
VK
599 {
600 CSCPMessage responce;
601
602 responce.SetId(pMsg->GetId());
603 responce.SetCode(CMD_REQUEST_COMPLETED);
604 responce.SetVariable(VID_RCC, RCC_NOT_IMPLEMENTED);
605 SendMessage(&responce);
606 }
21e4b6f0
VK
607 break;
608 }
609 delete pMsg;
610 }
611}
612
613
e100f091
VK
614//
615// Authenticate client
616//
617
618void ClientSession::Login(CSCPMessage *pRequest)
619{
620 CSCPMessage msg;
6528a4d7 621 BYTE szPassword[SHA1_DIGEST_SIZE];
e100f091
VK
622 char szLogin[MAX_USER_NAME], szBuffer[32];
623
624 // Prepare responce message
625 msg.SetCode(CMD_LOGIN_RESP);
626 msg.SetId(pRequest->GetId());
627
628 if (m_iState != STATE_AUTHENTICATED)
629 {
630
631 pRequest->GetVariableStr(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
6528a4d7 632 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
e100f091
VK
633
634 if (AuthenticateUser(szLogin, szPassword, &m_dwUserId, &m_dwSystemAccess))
635 {
636 m_iState = STATE_AUTHENTICATED;
637 sprintf(m_szUserName, "%s@%s", szLogin, IpToStr(m_dwHostAddr, szBuffer));
638 msg.SetVariable(VID_RCC, RCC_SUCCESS);
639 DebugPrintf("User %s authenticated\n", m_szUserName);
640 }
641 else
642 {
643 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
644 }
645 }
646 else
647 {
648 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
649 }
650
651 // Send responce
652 SendMessage(&msg);
653}
654
655
b54b2b11
VK
656//
657// Send event configuration to client
658//
659
660void ClientSession::SendEventDB(DWORD dwRqId)
661{
662 DB_ASYNC_RESULT hResult;
663 CSCPMessage msg;
664 char szBuffer[1024];
665
666 // Prepare responce message
3a5042fd 667 msg.SetCode(CMD_REQUEST_COMPLETED);
b54b2b11
VK
668 msg.SetId(dwRqId);
669
b8bad201
VK
670 if (!CheckSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB))
671 {
672 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
673 SendMessage(&msg);
674 }
b54b2b11
VK
675 else
676 {
b54b2b11
VK
677 msg.SetVariable(VID_RCC, RCC_SUCCESS);
678 SendMessage(&msg);
679 msg.DeleteAllVariables();
680
681 // Prepare data message
682 msg.SetCode(CMD_EVENT_DB_RECORD);
683 msg.SetId(dwRqId);
684
eafa21c7 685 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,name,severity,flags,message,description FROM events");
ebebc8ea 686 if (hResult != NULL)
b54b2b11 687 {
ebebc8ea
VK
688 while(DBFetch(hResult))
689 {
690 msg.SetVariable(VID_EVENT_ID, DBGetFieldAsyncULong(hResult, 0));
691 msg.SetVariable(VID_NAME, DBGetFieldAsync(hResult, 1, szBuffer, 1024));
692 msg.SetVariable(VID_SEVERITY, DBGetFieldAsyncULong(hResult, 2));
693 msg.SetVariable(VID_FLAGS, DBGetFieldAsyncULong(hResult, 3));
8f7e2482
VK
694
695 DBGetFieldAsync(hResult, 4, szBuffer, 1024);
696 DecodeSQLString(szBuffer);
697 msg.SetVariable(VID_MESSAGE, szBuffer);
698
699 DBGetFieldAsync(hResult, 5, szBuffer, 1024);
700 DecodeSQLString(szBuffer);
701 msg.SetVariable(VID_DESCRIPTION, szBuffer);
702
ebebc8ea
VK
703 SendMessage(&msg);
704 msg.DeleteAllVariables();
705 }
706 DBFreeAsyncResult(hResult);
b54b2b11 707 }
3a5042fd
VK
708
709 // Send end-of-list indicator
37c4d6aa 710 msg.SetVariable(VID_EVENT_ID, (DWORD)0);
3a5042fd 711 SendMessage(&msg);
b54b2b11
VK
712 }
713}
714
715
37c4d6aa
VK
716//
717// Lock event configuration database
718//
719
720void ClientSession::LockEventDB(DWORD dwRqId)
721{
722 CSCPMessage msg;
723 char szBuffer[1024];
724
725 // Prepare responce message
726 msg.SetCode(CMD_REQUEST_COMPLETED);
727 msg.SetId(dwRqId);
728
729 if (!CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
730 {
731 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
732 }
733 else if (!LockComponent(CID_EVENT_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
734 {
735 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
736 msg.SetVariable(VID_LOCKED_BY, szBuffer);
737 }
738 else
739 {
740 m_dwFlags |= CSF_EVENT_DB_LOCKED;
741 m_dwFlags &= ~CSF_EVENT_DB_MODIFIED;
742
743 msg.SetVariable(VID_RCC, RCC_SUCCESS);
744 }
745 SendMessage(&msg);
746}
747
748
3421c063
VK
749//
750// Close event configuration database
751//
752
37c4d6aa 753void ClientSession::UnlockEventDB(DWORD dwRqId)
3421c063
VK
754{
755 CSCPMessage msg;
756
757 msg.SetCode(CMD_REQUEST_COMPLETED);
758 msg.SetId(dwRqId);
759
760 if (m_dwFlags & CSF_EVENT_DB_LOCKED)
761 {
762 // Check if event configuration DB has been modified
763 if (m_dwFlags & CSF_EVENT_DB_MODIFIED)
764 {
765 ReloadEvents();
766
767 // Notify clients on event database change
768 EnumerateClientSessions(NotifyClient, (void *)NX_NOTIFY_EVENTDB_CHANGED);
769 }
770 UnlockComponent(CID_EVENT_DB);
771 m_dwFlags &= ~CSF_EVENT_DB_LOCKED;
772 msg.SetVariable(VID_RCC, RCC_SUCCESS);
773 }
774 else
775 {
776 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
777 }
778 SendMessage(&msg);
779}
780
781
37c4d6aa
VK
782//
783// Update event template
784//
785
786void ClientSession::SetEventInfo(CSCPMessage *pRequest)
787{
788 CSCPMessage msg;
789
790 // Prepare reply message
791 msg.SetCode(CMD_REQUEST_COMPLETED);
792 msg.SetId(pRequest->GetId());
793
794 // Check if we have event configuration database opened
795 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
796 {
797 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
798 }
799 else
800 {
801 // Check access rights
802 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
803 {
804 char szQuery[4096], szName[MAX_EVENT_NAME];
805 DWORD dwEventId;
806 BOOL bEventExist = FALSE;
807 DB_RESULT hResult;
808
809 // Check if event with specific id exists
810 dwEventId = pRequest->GetVariableLong(VID_EVENT_ID);
811 sprintf(szQuery, "SELECT event_id FROM events WHERE event_id=%ld", dwEventId);
812 hResult = DBSelect(g_hCoreDB, szQuery);
813 if (hResult != NULL)
814 {
815 if (DBGetNumRows(hResult) > 0)
816 bEventExist = TRUE;
817 DBFreeResult(hResult);
818 }
819
820 // Check that we are not trying to create event below 100000
821 if (bEventExist || (dwEventId >= FIRST_USER_EVENT_ID))
822 {
823 // Prepare and execute SQL query
824 pRequest->GetVariableStr(VID_NAME, szName, MAX_EVENT_NAME);
825 if (IsValidObjectName(szName))
826 {
827 char szMessage[MAX_DB_STRING], *pszDescription, *pszEscMsg, *pszEscDescr;
828
829 pRequest->GetVariableStr(VID_MESSAGE, szMessage, MAX_DB_STRING);
830 pszEscMsg = EncodeSQLString(szMessage);
831
832 pszDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
833 pszEscDescr = EncodeSQLString(pszDescription);
834 safe_free(pszDescription);
835
836 if (bEventExist)
837 {
838 sprintf(szQuery, "UPDATE events SET name='%s',severity=%ld,flags=%ld,message='%s',description='%s' WHERE event_id=%ld",
839 szName, pRequest->GetVariableLong(VID_SEVERITY), pRequest->GetVariableLong(VID_FLAGS),
840 pszEscMsg, pszEscDescr, dwEventId);
841 }
842 else
843 {
844 sprintf(szQuery, "INSERT INTO events (event_id,name,severity,flags,"
845 "message,description) VALUES (%ld,'%s',%ld,%ld,'%s','%s')",
846 dwEventId, szName, pRequest->GetVariableLong(VID_SEVERITY),
847 pRequest->GetVariableLong(VID_FLAGS), pszEscMsg, pszEscDescr);
848 }
849
850 free(pszEscMsg);
851 free(pszEscDescr);
852
853 if (DBQuery(g_hCoreDB, szQuery))
854 {
855 msg.SetVariable(VID_RCC, RCC_SUCCESS);
856 m_dwFlags |= CSF_EVENT_DB_MODIFIED;
857 }
858 else
859 {
860 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
861 }
862 }
863 else
864 {
865 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
866 }
867 }
868 else
869 {
870 msg.SetVariable(VID_RCC, RCC_INVALID_EVENT_CODE);
871 }
872 }
873 else
874 {
875 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
876 }
877 }
878
879 // Send responce
880 SendMessage(&msg);
881}
882
883
884//
885// Delete event template
886//
887
888void ClientSession::DeleteEventTemplate(CSCPMessage *pRequest)
889{
890 CSCPMessage msg;
891 DWORD dwEventId;
892
893 // Prepare reply message
894 msg.SetCode(CMD_REQUEST_COMPLETED);
895 msg.SetId(pRequest->GetId());
896
897 // Check if we have event configuration database opened
898 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
899 {
900 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
901 }
902 else
903 {
904 dwEventId = pRequest->GetVariableLong(VID_EVENT_ID);
905
906 // Check access rights
907 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) && (dwEventId >= FIRST_USER_EVENT_ID))
908 {
909 TCHAR szQuery[256];
910
911 _stprintf(szQuery, _T("DELETE FROM events WHERE event_id=%ld"), dwEventId);
912 if (DBQuery(g_hCoreDB, szQuery))
913 {
914 msg.SetVariable(VID_RCC, RCC_SUCCESS);
915 m_dwFlags |= CSF_EVENT_DB_LOCKED;
916 }
917 else
918 {
919 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
920 }
921 }
922 else
923 {
924 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
925 }
926 }
927
928 // Send responce
929 SendMessage(&msg);
930}
931
932
933//
934// Generate ID for new event template
935//
936
937void ClientSession::GenerateEventId(DWORD dwRqId)
938{
939 CSCPMessage msg;
940
941 // Prepare reply message
942 msg.SetCode(CMD_REQUEST_COMPLETED);
943 msg.SetId(dwRqId);
944
945 // Check if we have event configuration database opened
946 if (!(m_dwFlags & CSF_EVENT_DB_LOCKED))
947 {
948 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
949 }
950 else
951 {
952 // Check access rights
953 if (CheckSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
954 {
955 msg.SetVariable(VID_EVENT_ID, CreateUniqueId(IDG_EVENT));
956 }
957 else
958 {
959 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
960 }
961 }
962
963 // Send responce
964 SendMessage(&msg);
965}
966
967
21e4b6f0
VK
968//
969// Send all objects to client
970//
971
e100f091 972void ClientSession::SendAllObjects(DWORD dwRqId)
21e4b6f0
VK
973{
974 DWORD i;
975 CSCPMessage msg;
976
e100f091
VK
977 // Send confirmation message
978 msg.SetCode(CMD_REQUEST_COMPLETED);
979 msg.SetId(dwRqId);
980 msg.SetVariable(VID_RCC, RCC_SUCCESS);
981 SendMessage(&msg);
982 msg.DeleteAllVariables();
983
03482383 984 MutexLock(m_mutexSendObjects, INFINITE);
53512272 985
21e4b6f0
VK
986 // Prepare message
987 msg.SetCode(CMD_OBJECT);
988
989 // Send objects, one per message
990 ObjectsGlobalLock();
991 for(i = 0; i < g_dwIdIndexSize; i++)
24156e90
VK
992 if (g_pIndexById[i].pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
993 {
994 g_pIndexById[i].pObject->CreateMessage(&msg);
995 SendMessage(&msg);
996 msg.DeleteAllVariables();
997 }
21e4b6f0
VK
998 ObjectsGlobalUnlock();
999
1000 // Send end of list notification
1001 msg.SetCode(CMD_OBJECT_LIST_END);
1002 SendMessage(&msg);
53512272 1003
03482383 1004 MutexUnlock(m_mutexSendObjects);
21e4b6f0
VK
1005}
1006
1007
1008//
1009// Send all events to client
1010//
1011
74a5aa17 1012void ClientSession::SendAllEvents(DWORD dwRqId)
21e4b6f0 1013{
21e4b6f0 1014 CSCPMessage msg;
20177e8e 1015 DB_ASYNC_RESULT hResult;
9c36ef66 1016 NXC_EVENT event;
21e4b6f0 1017
74a5aa17
VK
1018 // Send confirmation message
1019 msg.SetCode(CMD_REQUEST_COMPLETED);
1020 msg.SetId(dwRqId);
1021 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1022 SendMessage(&msg);
1023 msg.DeleteAllVariables();
1024
03482383 1025 MutexLock(m_mutexSendEvents, INFINITE);
62f5857f 1026
21e4b6f0 1027 // Retrieve events from database
31115ff9
VK
1028 hResult = DBAsyncSelect(g_hCoreDB, "SELECT event_id,event_timestamp,event_source,"
1029 "event_severity,event_message FROM event_log "
1030 "ORDER BY event_timestamp");
21e4b6f0
VK
1031 if (hResult != NULL)
1032 {
1033 // Send events, one per message
20177e8e 1034 while(DBFetch(hResult))
21e4b6f0 1035 {
20177e8e
VK
1036 event.dwEventId = htonl(DBGetFieldAsyncULong(hResult, 0));
1037 event.dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 1));
1038 event.dwSourceId = htonl(DBGetFieldAsyncULong(hResult, 2));
1039 event.dwSeverity = htonl(DBGetFieldAsyncULong(hResult, 3));
1040 DBGetFieldAsync(hResult, 4, event.szMessage, MAX_EVENT_MSG_LENGTH);
8f7e2482 1041 DecodeSQLString(event.szMessage);
74a5aa17 1042 m_pSendQueue->Put(CreateRawCSCPMessage(CMD_EVENT, dwRqId, sizeof(NXC_EVENT), &event, NULL));
9c36ef66 1043 }
20177e8e 1044 DBFreeAsyncResult(hResult);
21e4b6f0
VK
1045 }
1046
1047 // Send end of list notification
1048 msg.SetCode(CMD_EVENT_LIST_END);
1049 SendMessage(&msg);
62f5857f 1050
03482383 1051 MutexUnlock(m_mutexSendEvents);
21e4b6f0
VK
1052}
1053
1054
1055//
1056// Send all configuration variables to client
1057//
1058
1059void ClientSession::SendAllConfigVars(void)
1060{
1061 DWORD i, dwNumRecords;
1062 CSCPMessage msg;
1063 DB_RESULT hResult;
1064
1065 // Check user rights
1066 if ((m_dwUserId != 0) && ((m_dwSystemAccess & SYSTEM_ACCESS_VIEW_CONFIG) == 0))
1067 {
1068 // Access denied
1069 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 1070 msg.SetVariable(VID_ERROR, (DWORD)1);
21e4b6f0
VK
1071 SendMessage(&msg);
1072 }
1073 else
1074 {
1075 // Prepare message
1076 msg.SetCode(CMD_CONFIG_VARIABLE);
1077
1078 // Retrieve configuration variables from database
44375123 1079 hResult = DBSelect(g_hCoreDB, "SELECT var_name,var_value FROM config WHERE is_visible=1");
21e4b6f0
VK
1080 if (hResult != NULL)
1081 {
1082 // Send events, one per message
1083 dwNumRecords = DBGetNumRows(hResult);
1084 for(i = 0; i < dwNumRecords; i++)
1085 {
a5f8dbb8
VK
1086 msg.SetVariable(VID_NAME, DBGetField(hResult, i, 0));
1087 msg.SetVariable(VID_VALUE, DBGetField(hResult, i, 1));
21e4b6f0
VK
1088 SendMessage(&msg);
1089 msg.DeleteAllVariables();
1090 }
20177e8e 1091 DBFreeResult(hResult);
21e4b6f0
VK
1092 }
1093
1094 // Send end of list notification
1095 msg.SetCode(CMD_CONFIG_VARLIST_END);
a5f8dbb8 1096 msg.SetVariable(VID_ERROR, (DWORD)0);
21e4b6f0
VK
1097 SendMessage(&msg);
1098 }
1099}
20177e8e
VK
1100
1101
1102//
1103// Close session forcibly
1104//
1105
1106void ClientSession::Kill(void)
1107{
1108 // We shutdown socket connection, which will cause
1109 // read thread to stop, and other threads will follow
1110 shutdown(m_hSocket, 2);
1111}
62f5857f
VK
1112
1113
1114//
1115// Handler for new events
1116//
1117
1118void ClientSession::OnNewEvent(Event *pEvent)
1119{
1120 UPDATE_INFO *pUpdate;
1121
984542f8
VK
1122 if (m_iState == STATE_AUTHENTICATED)
1123 {
1124 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
1125 pUpdate->dwCategory = INFO_CAT_EVENT;
1126 pUpdate->pData = malloc(sizeof(NXC_EVENT));
1127 pEvent->PrepareMessage((NXC_EVENT *)pUpdate->pData);
1128 m_pUpdateQueue->Put(pUpdate);
1129 }
62f5857f
VK
1130}
1131
1132
1133//
1134// Handler for object changes
1135//
1136
53512272 1137void ClientSession::OnObjectChange(NetObj *pObject)
62f5857f 1138{
53512272
VK
1139 UPDATE_INFO *pUpdate;
1140
984542f8
VK
1141 if (m_iState == STATE_AUTHENTICATED)
1142 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1143 {
1144 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
1145 pUpdate->dwCategory = INFO_CAT_OBJECT_CHANGE;
1146 pUpdate->pData = pObject;
984542f8 1147 pObject->IncRefCount();
333ece94 1148 m_pUpdateQueue->Put(pUpdate);
984542f8 1149 }
62f5857f
VK
1150}
1151
1152
83f0529c
VK
1153//
1154// Send notification message to server
1155//
1156
4de204a3 1157void ClientSession::Notify(DWORD dwCode, DWORD dwData)
83f0529c
VK
1158{
1159 CSCPMessage msg;
1160
1161 msg.SetCode(CMD_NOTIFY);
1162 msg.SetVariable(VID_NOTIFICATION_CODE, dwCode);
4de204a3 1163 msg.SetVariable(VID_NOTIFICATION_DATA, dwData);
83f0529c
VK
1164 SendMessage(&msg);
1165}
605d2931
VK
1166
1167
24156e90
VK
1168//
1169// Modify object
1170//
1171
1172void ClientSession::ModifyObject(CSCPMessage *pRequest)
1173{
ff550544 1174 DWORD dwObjectId, dwResult = RCC_SUCCESS;
24156e90
VK
1175 NetObj *pObject;
1176 CSCPMessage msg;
1177
1178 // Prepare reply message
1179 msg.SetCode(CMD_REQUEST_COMPLETED);
1180 msg.SetId(pRequest->GetId());
1181
1182 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1183 pObject = FindObjectById(dwObjectId);
1184 if (pObject != NULL)
1185 {
1186 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1187 {
ff550544
VK
1188 // If user attempts to change object's ACL, check
1189 // if he has OBJECT_ACCESS_CONTROL permission
1190 if (pRequest->IsVariableExist(VID_ACL_SIZE))
1191 if (!pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CONTROL))
1192 dwResult = RCC_ACCESS_DENIED;
1193
1194 // If allowed, change object and set completion code
1195 if (dwResult != RCC_ACCESS_DENIED)
1196 dwResult = pObject->ModifyFromMessage(pRequest);
24156e90
VK
1197 msg.SetVariable(VID_RCC, dwResult);
1198 }
1199 else
1200 {
1201 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1202 }
1203 }
1204 else
1205 {
1206 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1207 }
1208
1209 // Send responce
1210 SendMessage(&msg);
1211}
23a32988
VK
1212
1213
1214//
1215// Send users database to client
1216//
1217
1218void ClientSession::SendUserDB(DWORD dwRqId)
1219{
1220 CSCPMessage msg;
2d5c8ac8 1221 DWORD i;
23a32988
VK
1222
1223 // Prepare responce message
1224 msg.SetCode(CMD_REQUEST_COMPLETED);
1225 msg.SetId(dwRqId);
1226 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1227 SendMessage(&msg);
1228
1229 // Send users
1230 msg.SetCode(CMD_USER_DATA);
1231 for(i = 0; i < g_dwNumUsers; i++)
1232 {
2d5c8ac8 1233 FillUserInfoMessage(&msg, &g_pUserList[i]);
23a32988
VK
1234 SendMessage(&msg);
1235 msg.DeleteAllVariables();
1236 }
1237
1238 // Send groups
1239 msg.SetCode(CMD_GROUP_DATA);
1240 for(i = 0; i < g_dwNumGroups; i++)
1241 {
2d5c8ac8 1242 FillGroupInfoMessage(&msg, &g_pGroupList[i]);
23a32988
VK
1243 SendMessage(&msg);
1244 msg.DeleteAllVariables();
1245 }
1246
1247 // Send end-of-database notification
1248 msg.SetCode(CMD_USER_DB_EOF);
1249 SendMessage(&msg);
1250}
ff550544
VK
1251
1252
1253//
1254// Create new user
1255//
1256
1257void ClientSession::CreateUser(CSCPMessage *pRequest)
1258{
1259 CSCPMessage msg;
1260
1261 // Prepare responce message
1262 msg.SetCode(CMD_REQUEST_COMPLETED);
1263 msg.SetId(pRequest->GetId());
1264
1265 // Check user rights
1266 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1267 {
1268 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1269 }
1270 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1271 {
1272 // User database have to be locked before any
1273 // changes to user database can be made
1274 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1275 }
1276 else
1277 {
984542f8 1278 DWORD dwResult, dwUserId;
ff550544
VK
1279 BOOL bIsGroup;
1280 char szUserName[MAX_USER_NAME];
1281
1282 pRequest->GetVariableStr(VID_USER_NAME, szUserName, MAX_USER_NAME);
8f7e2482
VK
1283 if (IsValidObjectName(szUserName))
1284 {
1285 bIsGroup = pRequest->GetVariableShort(VID_IS_GROUP);
1286 dwResult = CreateNewUser(szUserName, bIsGroup, &dwUserId);
1287 msg.SetVariable(VID_RCC, dwResult);
1288 if (dwResult == RCC_SUCCESS)
1289 msg.SetVariable(VID_USER_ID, dwUserId); // Send id of new user to client
1290 }
1291 else
1292 {
1293 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
1294 }
ff550544
VK
1295 }
1296
1297 // Send responce
1298 SendMessage(&msg);
1299}
1300
1301
1302//
1303// Update existing user's data
1304//
1305
1306void ClientSession::UpdateUser(CSCPMessage *pRequest)
1307{
612d43dc
VK
1308 CSCPMessage msg;
1309
1310 // Prepare responce message
1311 msg.SetCode(CMD_REQUEST_COMPLETED);
1312 msg.SetId(pRequest->GetId());
1313
1314 // Check user rights
1315 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
1316 {
1317 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1318 }
1319 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1320 {
1321 // User database have to be locked before any
1322 // changes to user database can be made
1323 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1324 }
1325 else
1326 {
86f31e8f 1327 DWORD dwUserId, dwResult;
612d43dc
VK
1328
1329 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1330 if (dwUserId & GROUP_FLAG)
1331 {
1332 NMS_USER_GROUP group;
2d5c8ac8 1333 DWORD i, dwId;
86f31e8f
VK
1334
1335 group.dwId = dwUserId;
2d5c8ac8
VK
1336 pRequest->GetVariableStr(VID_USER_DESCRIPTION, group.szDescription, MAX_USER_DESCR);
1337 pRequest->GetVariableStr(VID_USER_NAME, group.szName, MAX_USER_NAME);
1338 group.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
1339 group.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1340 group.dwNumMembers = pRequest->GetVariableLong(VID_NUM_MEMBERS);
1341 group.pMembers = (DWORD *)malloc(sizeof(DWORD) * group.dwNumMembers);
1342 for(i = 0, dwId = VID_GROUP_MEMBER_BASE; i < group.dwNumMembers; i++, dwId++)
1343 group.pMembers[i] = pRequest->GetVariableLong(dwId);
86f31e8f 1344 dwResult = ModifyGroup(&group);
2d5c8ac8 1345 safe_free(group.pMembers);
612d43dc
VK
1346 }
1347 else
1348 {
1349 NMS_USER user;
1350
1351 user.dwId = dwUserId;
1352 pRequest->GetVariableStr(VID_USER_DESCRIPTION, user.szDescription, MAX_USER_DESCR);
1353 pRequest->GetVariableStr(VID_USER_FULL_NAME, user.szFullName, MAX_USER_FULLNAME);
1354 pRequest->GetVariableStr(VID_USER_NAME, user.szName, MAX_USER_NAME);
1355 user.wFlags = pRequest->GetVariableShort(VID_USER_FLAGS);
86f31e8f
VK
1356 user.wSystemRights = pRequest->GetVariableShort(VID_USER_SYS_RIGHTS);
1357 dwResult = ModifyUser(&user);
612d43dc 1358 }
86f31e8f 1359 msg.SetVariable(VID_RCC, dwResult);
612d43dc
VK
1360 }
1361
1362 // Send responce
1363 SendMessage(&msg);
ff550544
VK
1364}
1365
1366
1367//
1368// Delete user
1369//
1370
1371void ClientSession::DeleteUser(CSCPMessage *pRequest)
1372{
1373 CSCPMessage msg;
1374 DWORD dwUserId;
1375
1376 // Prepare responce message
1377 msg.SetCode(CMD_REQUEST_COMPLETED);
1378 msg.SetId(pRequest->GetId());
1379
612d43dc
VK
1380 // Check user rights
1381 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
ff550544 1382 {
612d43dc
VK
1383 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1384 }
1385 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
1386 {
1387 // User database have to be locked before any
1388 // changes to user database can be made
1389 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1390 }
1391 else
1392 {
1393 // Get Id of user to be deleted
1394 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1395
1396 if (dwUserId != 0)
ff550544 1397 {
c9363772 1398 DWORD dwResult;
612d43dc 1399
c9363772
VK
1400 dwResult = DeleteUserFromDB(dwUserId);
1401 msg.SetVariable(VID_RCC, dwResult);
ff550544
VK
1402 }
1403 else
1404 {
612d43dc
VK
1405 // Nobody can delete system administrator account
1406 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
ff550544
VK
1407 }
1408 }
ff550544
VK
1409
1410 // Send responce
1411 SendMessage(&msg);
1412}
1413
1414
1415//
1416// Lock/unlock user database
1417//
1418
1419void ClientSession::LockUserDB(DWORD dwRqId, BOOL bLock)
1420{
1421 CSCPMessage msg;
1422 char szBuffer[256];
1423
1424 // Prepare responce message
1425 msg.SetCode(CMD_REQUEST_COMPLETED);
1426 msg.SetId(dwRqId);
1427
1428 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
1429 {
1430 if (bLock)
1431 {
1432 if (!LockComponent(CID_USER_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
1433 {
1434 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1435 msg.SetVariable(VID_LOCKED_BY, szBuffer);
1436 }
1437 else
1438 {
1439 m_dwFlags |= CSF_USER_DB_LOCKED;
1440 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1441 }
1442 }
1443 else
1444 {
1445 if (m_dwFlags & CSF_USER_DB_LOCKED)
1446 {
1447 UnlockComponent(CID_USER_DB);
1448 m_dwFlags &= ~CSF_USER_DB_LOCKED;
1449 }
1450 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1451 }
1452 }
1453 else
1454 {
1455 // Current user has no rights for user account management
1456 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1457 }
1458
1459 // Send responce
1460 SendMessage(&msg);
1461}
984542f8
VK
1462
1463
1464//
1465// Notify client on user database update
1466//
1467
1468void ClientSession::OnUserDBUpdate(int iCode, DWORD dwUserId, NMS_USER *pUser, NMS_USER_GROUP *pGroup)
1469{
1470 CSCPMessage msg;
1471
1472 if (m_iState == STATE_AUTHENTICATED)
1473 {
1474 msg.SetCode(CMD_USER_DB_UPDATE);
1475 msg.SetId(0);
1476 msg.SetVariable(VID_UPDATE_TYPE, (WORD)iCode);
984542f8
VK
1477
1478 switch(iCode)
1479 {
1480 case USER_DB_CREATE:
2d5c8ac8 1481 msg.SetVariable(VID_USER_ID, dwUserId);
984542f8 1482 if (dwUserId & GROUP_FLAG)
984542f8 1483 msg.SetVariable(VID_USER_NAME, pGroup->szName);
984542f8 1484 else
984542f8 1485 msg.SetVariable(VID_USER_NAME, pUser->szName);
2d5c8ac8
VK
1486 break;
1487 case USER_DB_MODIFY:
1488 if (dwUserId & GROUP_FLAG)
1489 FillGroupInfoMessage(&msg, pGroup);
1490 else
1491 FillUserInfoMessage(&msg, pUser);
984542f8
VK
1492 break;
1493 default:
2d5c8ac8 1494 msg.SetVariable(VID_USER_ID, dwUserId);
984542f8
VK
1495 break;
1496 }
1497
1498 SendMessage(&msg);
1499 }
1500}
017e1e13
VK
1501
1502
9ed4eaff
VK
1503//
1504// Change management status for the object
1505//
1506
1507void ClientSession::ChangeObjectMgmtStatus(CSCPMessage *pRequest)
1508{
1509 CSCPMessage msg;
1510 DWORD dwObjectId;
1511 NetObj *pObject;
1512
1513 // Prepare responce message
1514 msg.SetCode(CMD_REQUEST_COMPLETED);
1515 msg.SetId(pRequest->GetId());
1516
1517 // Get object id and check access rights
1518 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1519 pObject = FindObjectById(dwObjectId);
1520 if (pObject != NULL)
1521 {
1522 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1523 {
1524 BOOL bIsManaged;
1525
1526 bIsManaged = (BOOL)pRequest->GetVariableShort(VID_MGMT_STATUS);
1527 pObject->SetMgmtStatus(bIsManaged);
1528 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1529 }
1530 else
1531 {
1532 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1533 }
1534 }
1535 else
1536 {
1537 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1538 }
1539
1540 // Send responce
1541 SendMessage(&msg);
1542}
1543
1544
017e1e13
VK
1545//
1546// Set user's password
1547//
1548
1549void ClientSession::SetPassword(CSCPMessage *pRequest)
1550{
1551 CSCPMessage msg;
1552 DWORD dwUserId;
1553
1554 // Prepare responce message
1555 msg.SetCode(CMD_REQUEST_COMPLETED);
1556 msg.SetId(pRequest->GetId());
1557
1558 dwUserId = pRequest->GetVariableLong(VID_USER_ID);
1559
1560 if (((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS) &&
1561 !((dwUserId == 0) && (m_dwUserId != 0))) || // Only administrator can change password for UID 0
1562 (dwUserId == m_dwUserId)) // User can change password for itself
1563 {
1564 DWORD dwResult;
6528a4d7 1565 BYTE szPassword[SHA1_DIGEST_SIZE];
017e1e13 1566
6528a4d7 1567 pRequest->GetVariableBinary(VID_PASSWORD, szPassword, SHA1_DIGEST_SIZE);
017e1e13
VK
1568 dwResult = SetUserPassword(dwUserId, szPassword);
1569 msg.SetVariable(VID_RCC, dwResult);
1570 }
1571 else
1572 {
1573 // Current user has no rights to change password for specific user
1574 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1575 }
1576
1577 // Send responce
1578 SendMessage(&msg);
1579}
7257eb7d
VK
1580
1581
1582//
1583// Send node's DCIs to client and lock data collection settings
1584//
1585
1586void ClientSession::OpenNodeDCIList(CSCPMessage *pRequest)
1587{
1588 CSCPMessage msg;
3c55b85d
VK
1589 DWORD dwObjectId;
1590 NetObj *pObject;
1591 BOOL bSuccess = FALSE;
7257eb7d
VK
1592
1593 // Prepare responce message
1594 msg.SetCode(CMD_REQUEST_COMPLETED);
1595 msg.SetId(pRequest->GetId());
1596
3c55b85d
VK
1597 // Get node id and check object class and access rights
1598 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1599 pObject = FindObjectById(dwObjectId);
1600 if (pObject != NULL)
1601 {
62d11997
VK
1602 if ((pObject->Type() == OBJECT_NODE) ||
1603 (pObject->Type() == OBJECT_TEMPLATE))
3c55b85d
VK
1604 {
1605 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1606 {
1607 // Try to lock DCI list
62d11997 1608 bSuccess = ((Template *)pObject)->LockDCIList(m_dwIndex);
3c55b85d 1609 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_COMPONENT_LOCKED);
338493a0
VK
1610
1611 // Modify list of open nodes DCI lists
1612 if (bSuccess)
1613 {
1614 m_pOpenDCIList = (DWORD *)realloc(m_pOpenDCIList, sizeof(DWORD) * (m_dwOpenDCIListSize + 1));
1615 m_pOpenDCIList[m_dwOpenDCIListSize] = dwObjectId;
1616 m_dwOpenDCIListSize++;
1617 }
3c55b85d
VK
1618 }
1619 else
1620 {
1621 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1622 }
1623 }
1624 else
1625 {
1626 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1627 }
1628 }
1629 else
1630 {
1631 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1632 }
7257eb7d
VK
1633
1634 // Send responce
1635 SendMessage(&msg);
3c55b85d
VK
1636
1637 // If DCI list was successfully locked, send it to client
1638 if (bSuccess)
62d11997 1639 ((Template *)pObject)->SendItemsToClient(this, pRequest->GetId());
7257eb7d
VK
1640}
1641
1642
1643//
1644// Unlock node's data collection settings
1645//
1646
1647void ClientSession::CloseNodeDCIList(CSCPMessage *pRequest)
1648{
1649 CSCPMessage msg;
3c55b85d
VK
1650 DWORD dwObjectId;
1651 NetObj *pObject;
7257eb7d
VK
1652
1653 // Prepare responce message
1654 msg.SetCode(CMD_REQUEST_COMPLETED);
1655 msg.SetId(pRequest->GetId());
1656
3c55b85d
VK
1657 // Get node id and check object class and access rights
1658 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1659 pObject = FindObjectById(dwObjectId);
1660 if (pObject != NULL)
1661 {
62d11997
VK
1662 if ((pObject->Type() == OBJECT_NODE) ||
1663 (pObject->Type() == OBJECT_TEMPLATE))
3c55b85d
VK
1664 {
1665 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1666 {
1667 BOOL bSuccess;
1668
1669 // Try to unlock DCI list
62d11997 1670 bSuccess = ((Template *)pObject)->UnlockDCIList(m_dwIndex);
3c55b85d 1671 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_OUT_OF_STATE_REQUEST);
338493a0
VK
1672
1673 // Modify list of open nodes DCI lists
1674 if (bSuccess)
1675 {
1676 DWORD i;
1677
1678 for(i = 0; i < m_dwOpenDCIListSize; i++)
1679 if (m_pOpenDCIList[i] == dwObjectId)
1680 {
1681 m_dwOpenDCIListSize--;
1682 memmove(&m_pOpenDCIList[i], &m_pOpenDCIList[i + 1],
1683 sizeof(DWORD) * (m_dwOpenDCIListSize - i));
1684 break;
1685 }
1686 }
3c55b85d
VK
1687 }
1688 else
1689 {
1690 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1691 }
1692 }
1693 else
1694 {
1695 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1696 }
1697 }
1698 else
1699 {
1700 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1701 }
1702
7257eb7d
VK
1703 // Send responce
1704 SendMessage(&msg);
1705}
c1c39152
VK
1706
1707
1708//
9ed4eaff 1709// Create, modify, or delete data collection item for node
c1c39152
VK
1710//
1711
9ed4eaff 1712void ClientSession::ModifyNodeDCI(CSCPMessage *pRequest)
c1c39152
VK
1713{
1714 CSCPMessage msg;
1715 DWORD dwObjectId;
1716 NetObj *pObject;
1717
1718 // Prepare responce message
1719 msg.SetCode(CMD_REQUEST_COMPLETED);
1720 msg.SetId(pRequest->GetId());
1721
9ed4eaff 1722 // Get node id and check object class and access rights
c1c39152
VK
1723 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1724 pObject = FindObjectById(dwObjectId);
1725 if (pObject != NULL)
1726 {
62d11997
VK
1727 if ((pObject->Type() == OBJECT_NODE) ||
1728 (pObject->Type() == OBJECT_TEMPLATE))
c1c39152 1729 {
62d11997 1730 if (((Template *)pObject)->IsLockedBySession(m_dwIndex))
9ed4eaff
VK
1731 {
1732 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
1733 {
07a45e04 1734 DWORD i, dwItemId, dwNumMaps, *pdwMapId, *pdwMapIndex;
9ed4eaff
VK
1735 DCItem *pItem;
1736 BOOL bSuccess;
1737
1738 switch(pRequest->GetCode())
1739 {
1740 case CMD_CREATE_NEW_DCI:
1741 // Create dummy DCI
1742 pItem = new DCItem(CreateUniqueId(IDG_ITEM), "no name", DS_INTERNAL,
0ae741b9 1743 DCI_DT_INT, 60, 30, (Node *)pObject);
9ed4eaff 1744 pItem->SetStatus(ITEM_STATUS_DISABLED);
62d11997 1745 if (((Template *)pObject)->AddItem(pItem))
9ed4eaff
VK
1746 {
1747 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1748 // Return new item id to client
1749 msg.SetVariable(VID_DCI_ID, pItem->Id());
1750 }
1751 else // Unable to add item to node
1752 {
1753 delete pItem;
1754 msg.SetVariable(VID_RCC, RCC_DUPLICATE_DCI);
1755 }
1756 break;
1757 case CMD_MODIFY_NODE_DCI:
1758 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
62d11997
VK
1759 bSuccess = ((Template *)pObject)->UpdateItem(dwItemId, pRequest, &dwNumMaps,
1760 &pdwMapIndex, &pdwMapId);
07a45e04
VK
1761 if (bSuccess)
1762 {
1763 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1764
1765 // Send index to id mapping for newly created thresholds to client
1766 msg.SetVariable(VID_DCI_NUM_MAPS, dwNumMaps);
1767 for(i = 0; i < dwNumMaps; i++)
1768 {
1769 pdwMapId[i] = htonl(pdwMapId[i]);
1770 pdwMapIndex[i] = htonl(pdwMapIndex[i]);
1771 }
1772 msg.SetVariable(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(DWORD) * dwNumMaps);
1773 msg.SetVariable(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(DWORD) * dwNumMaps);
7247842d
VK
1774 safe_free(pdwMapId);
1775 safe_free(pdwMapIndex);
07a45e04
VK
1776 }
1777 else
1778 {
1779 msg.SetVariable(VID_RCC, RCC_INVALID_DCI_ID);
1780 }
9ed4eaff
VK
1781 break;
1782 case CMD_DELETE_NODE_DCI:
1783 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
62d11997 1784 bSuccess = ((Template *)pObject)->DeleteItem(dwItemId);
9ed4eaff
VK
1785 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_DCI_ID);
1786 break;
1787 }
70573ffe
VK
1788 if (bSuccess)
1789 ((Template *)pObject)->SetDCIModificationFlag();
9ed4eaff
VK
1790 }
1791 else // User doesn't have MODIFY rights on object
1792 {
1793 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1794 }
1795 }
1796 else // Nodes DCI list not locked by this session
1797 {
1798 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1799 }
c1c39152 1800 }
9ed4eaff 1801 else // Object is not a node
c1c39152 1802 {
9ed4eaff 1803 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
c1c39152
VK
1804 }
1805 }
9ed4eaff 1806 else // No object with given ID
c1c39152
VK
1807 {
1808 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1809 }
1810
1811 // Send responce
1812 SendMessage(&msg);
1813}
ebebc8ea
VK
1814
1815
933aee5c 1816//
62d11997 1817// Copy DCI from one node or template to another
933aee5c
VK
1818//
1819
1820void ClientSession::CopyDCI(CSCPMessage *pRequest)
1821{
1822 CSCPMessage msg;
1823 NetObj *pSource, *pDestination;
1824
1825 // Prepare responce message
1826 msg.SetCode(CMD_REQUEST_COMPLETED);
1827 msg.SetId(pRequest->GetId());
1828
1829 // Get source and destination
1830 pSource = FindObjectById(pRequest->GetVariableLong(VID_SOURCE_OBJECT_ID));
1831 pDestination = FindObjectById(pRequest->GetVariableLong(VID_DESTINATION_OBJECT_ID));
1832 if ((pSource != NULL) && (pDestination != NULL))
1833 {
1834 // Check object types
62d11997
VK
1835 if (((pSource->Type() == OBJECT_NODE) || (pSource->Type() == OBJECT_TEMPLATE)) &&
1836 (pDestination->Type() == OBJECT_NODE))
933aee5c 1837 {
62d11997 1838 if (((Template *)pSource)->IsLockedBySession(m_dwIndex))
933aee5c
VK
1839 {
1840 // Check access rights
1841 if ((pSource->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ)) &&
1842 (pDestination->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
1843 {
1844 // Attempt to lock destination's DCI list
079c3851
VK
1845 if ((pDestination->Id() == pSource->Id()) ||
1846 (((Template *)pDestination)->LockDCIList(m_dwIndex)))
933aee5c
VK
1847 {
1848 DWORD i, *pdwItemList, dwNumItems;
1849 const DCItem *pSrcItem;
1850 DCItem *pDstItem;
1851 int iErrors = 0;
1852
1853 // Get list of items to be copied
1854 dwNumItems = pRequest->GetVariableLong(VID_NUM_ITEMS);
1855 pdwItemList = (DWORD *)malloc(sizeof(DWORD) * dwNumItems);
1856 pRequest->GetVariableInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
1857
1858 // Copy items
1859 for(i = 0; i < dwNumItems; i++)
1860 {
62d11997 1861 pSrcItem = ((Template *)pSource)->GetItemById(pdwItemList[i]);
933aee5c
VK
1862 if (pSrcItem != NULL)
1863 {
1864 pDstItem = new DCItem(pSrcItem);
1865 pDstItem->SetId(CreateUniqueId(IDG_ITEM));
1866 pDstItem->SetStatus(ITEM_STATUS_ACTIVE);
8f3374c9 1867 pDstItem->BindToNode((Template *)pDestination);
62d11997 1868 if (!((Template *)pDestination)->AddItem(pDstItem))
933aee5c
VK
1869 {
1870 delete pDstItem;
1871 iErrors++;
1872 }
1873 }
1874 else
1875 {
1876 iErrors++;
1877 }
1878 }
1879
1880 // Cleanup
1881 free(pdwItemList);
079c3851
VK
1882 if (pDestination->Id() != pSource->Id())
1883 ((Template *)pDestination)->UnlockDCIList(m_dwIndex);
933aee5c
VK
1884 msg.SetVariable(VID_RCC, (iErrors == 0) ? RCC_SUCCESS : RCC_DCI_COPY_ERRORS);
1885 }
1886 else // Destination's DCI list already locked by someone else
1887 {
1888 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
1889 }
1890 }
1891 else // User doesn't have enough rights on object(s)
1892 {
1893 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
1894 }
1895 }
1896 else // Source node DCI list not locked by this session
1897 {
1898 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1899 }
1900 }
1901 else // Object(s) is not a node
1902 {
1903 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1904 }
1905 }
1906 else // No object(s) with given ID
1907 {
1908 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
1909 }
1910
1911 // Send responce
1912 SendMessage(&msg);
1913}
1914
1915
ebebc8ea
VK
1916//
1917// Get collected data
1918//
1919
1920void ClientSession::GetCollectedData(CSCPMessage *pRequest)
1921{
1922 CSCPMessage msg;
1923 DWORD dwObjectId;
1924 NetObj *pObject;
6159a875 1925 BOOL bSuccess = FALSE;
2b9c1c41 1926 static DWORD m_dwRowSize[] = { 8, 8, 12, 12, 260, 12 };
ebebc8ea
VK
1927
1928 // Prepare responce message
1929 msg.SetCode(CMD_REQUEST_COMPLETED);
1930 msg.SetId(pRequest->GetId());
1931
1932 // Get node id and check object class and access rights
1933 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
1934 pObject = FindObjectById(dwObjectId);
1935 if (pObject != NULL)
1936 {
1937 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
1938 {
1939 DB_ASYNC_RESULT hResult;
1940 DWORD dwItemId, dwMaxRows, dwTimeFrom, dwTimeTo;
6159a875 1941 DWORD dwAllocatedRows = 100, dwNumRows = 0;
bdce7422
VK
1942 char szQuery[512], szCond[256];
1943 int iPos = 0, iType;
1944 DCI_DATA_HEADER *pData = NULL;
6159a875 1945 DCI_DATA_ROW *pCurr;
bdce7422
VK
1946
1947 // Send CMD_REQUEST_COMPLETED message
1948 msg.SetVariable(VID_RCC, RCC_SUCCESS);
1949 SendMessage(&msg);
ebebc8ea
VK
1950
1951 // Get request parameters
1952 dwItemId = pRequest->GetVariableLong(VID_DCI_ID);
1953 dwMaxRows = pRequest->GetVariableLong(VID_MAX_ROWS);
1954 dwTimeFrom = pRequest->GetVariableLong(VID_TIME_FROM);
1955 dwTimeTo = pRequest->GetVariableLong(VID_TIME_TO);
1956
9f20696e 1957 szCond[0] = 0;
bdce7422
VK
1958 if (dwTimeFrom != 0)
1959 {
1dc90d86 1960 sprintf(szCond, " AND idata_timestamp>=%d", dwTimeFrom);
bdce7422
VK
1961 iPos = strlen(szCond);
1962 }
1963 if (dwTimeTo != 0)
1964 {
1dc90d86 1965 sprintf(&szCond[iPos], " AND idata_timestamp<=%d", dwTimeTo);
bdce7422
VK
1966 }
1967
31115ff9 1968 sprintf(szQuery, "SELECT idata_timestamp,idata_value FROM idata_%d WHERE item_id=%d%s ORDER BY idata_timestamp DESC",
bdce7422 1969 dwObjectId, dwItemId, szCond);
ebebc8ea
VK
1970 hResult = DBAsyncSelect(g_hCoreDB, szQuery);
1971 if (hResult != NULL)
1972 {
6159a875 1973 // Get item's data type to determine actual row size
bdce7422
VK
1974 iType = ((Node *)pObject)->GetItemType(dwItemId);
1975
6159a875
VK
1976 // Allocate initial memory block and prepare data header
1977 pData = (DCI_DATA_HEADER *)malloc(dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
1978 pData->dwDataType = htonl((DWORD)iType);
1979 pData->dwItemId = htonl(dwItemId);
1980
1981 // Fill memory block with records
1982 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER));
ebebc8ea
VK
1983 while(DBFetch(hResult))
1984 {
6159a875 1985 if ((dwMaxRows > 0) && (dwNumRows >= dwMaxRows))
bdce7422 1986 break;
6159a875
VK
1987
1988 // Extend buffer if we are at the end
1989 if (dwNumRows == dwAllocatedRows)
1990 {
1991 dwAllocatedRows += 50;
1992 pData = (DCI_DATA_HEADER *)realloc(pData,
1993 dwAllocatedRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER));
1994 pCurr = (DCI_DATA_ROW *)(((char *)pData) + sizeof(DCI_DATA_HEADER) + m_dwRowSize[iType] * dwNumRows);
1995 }
1996
1997 dwNumRows++;
1998
1999 pCurr->dwTimeStamp = htonl(DBGetFieldAsyncULong(hResult, 0));
2000 switch(iType)
2001 {
0ae741b9
VK
2002 case DCI_DT_INT:
2003 case DCI_DT_UINT:
9f20696e
VK
2004 pCurr->value.dwInteger = htonl(DBGetFieldAsyncULong(hResult, 1));
2005 break;
0ae741b9
VK
2006 case DCI_DT_INT64:
2007 case DCI_DT_UINT64:
b50f1100 2008 pCurr->value.qwInt64 = htonq(DBGetFieldAsyncUQuad(hResult, 1));
0ae741b9 2009 break;
42d7ed00 2010 case DCI_DT_FLOAT:
9f20696e 2011 pCurr->value.dFloat = htond(DBGetFieldAsyncDouble(hResult, 1));
6159a875 2012 break;
42d7ed00 2013 case DCI_DT_STRING:
6159a875
VK
2014 DBGetFieldAsync(hResult, 1, pCurr->value.szString, MAX_DCI_STRING_VALUE);
2015 break;
2016 }
2017 pCurr = (DCI_DATA_ROW *)(((char *)pCurr) + m_dwRowSize[iType]);
ebebc8ea
VK
2018 }
2019 DBFreeAsyncResult(hResult);
9f20696e 2020 pData->dwNumRows = htonl(dwNumRows);
6159a875
VK
2021
2022 // Prepare and send raw message with fetched data
2023 m_pSendQueue->Put(
2024 CreateRawCSCPMessage(CMD_DCI_DATA, pRequest->GetId(),
2025 dwNumRows * m_dwRowSize[iType] + sizeof(DCI_DATA_HEADER),
2026 pData, NULL));
2027 free(pData);
2028 bSuccess = TRUE;
ebebc8ea 2029 }
62d11997
VK
2030 else
2031 {
2032 msg.SetVariable(VID_RCC, RCC_DB_FAILURE);
2033 }
ebebc8ea
VK
2034 }
2035 else
2036 {
2037 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2038 }
2039 }
2040 else // No object with given ID
2041 {
2042 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2043 }
2044
2045 // Send responce
6159a875
VK
2046 if (!bSuccess)
2047 SendMessage(&msg);
ebebc8ea 2048}
06e7be2f
VK
2049
2050
2051//
2052// Open event processing policy
2053//
2054
2055void ClientSession::OpenEPP(DWORD dwRqId)
2056{
2057 CSCPMessage msg;
2058 char szBuffer[256];
2059 BOOL bSuccess = FALSE;
2060
2061 // Prepare responce message
2062 msg.SetCode(CMD_REQUEST_COMPLETED);
2063 msg.SetId(dwRqId);
2064
2065 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2066 {
2067 if (!LockComponent(CID_EPP, m_dwIndex, m_szUserName, NULL, szBuffer))
2068 {
2069 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2070 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2071 }
2072 else
2073 {
2074 m_dwFlags |= CSF_EPP_LOCKED;
2075 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2076 msg.SetVariable(VID_NUM_RULES, g_pEventPolicy->NumRules());
2077 bSuccess = TRUE;
2078 }
2079 }
2080 else
2081 {
2082 // Current user has no rights for event policy management
2083 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2084 }
2085
2086 // Send responce
2087 SendMessage(&msg);
2088
2089 // Send policy to client
2090 if (bSuccess)
2091 g_pEventPolicy->SendToClient(this, dwRqId);
2092}
2093
2094
2095//
2096// Close event processing policy
2097//
2098
2099void ClientSession::CloseEPP(DWORD dwRqId)
2100{
2101 CSCPMessage msg;
2102
2103 // Prepare responce message
2104 msg.SetCode(CMD_REQUEST_COMPLETED);
2105 msg.SetId(dwRqId);
2106
2107 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2108 {
2109 if (m_dwFlags & CSF_EPP_LOCKED)
2110 {
2111 UnlockComponent(CID_EPP);
2112 m_dwFlags &= ~CSF_EPP_LOCKED;
2113 }
2114 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2115 }
2116 else
2117 {
2118 // Current user has no rights for event policy management
2119 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2120 }
2121
2122 // Send responce
2123 SendMessage(&msg);
2124}
2125
2126
2127//
2128// Save event processing policy
2129//
2130
8f7e2482 2131void ClientSession::SaveEPP(CSCPMessage *pRequest)
06e7be2f 2132{
8f7e2482
VK
2133 CSCPMessage msg;
2134
2135 // Prepare responce message
2136 msg.SetCode(CMD_REQUEST_COMPLETED);
2137 msg.SetId(pRequest->GetId());
2138
2139 if (m_dwSystemAccess & SYSTEM_ACCESS_EPP)
2140 {
2141 if (m_dwFlags & CSF_EPP_LOCKED)
2142 {
2143 msg.SetVariable(VID_RCC, RCC_SUCCESS);
8f7e2482
VK
2144 m_dwNumRecordsToUpload = pRequest->GetVariableLong(VID_NUM_RULES);
2145 m_dwRecordsUploaded = 0;
043fe1ec
VK
2146 if (m_dwNumRecordsToUpload == 0)
2147 {
2148 g_pEventPolicy->ReplacePolicy(0, NULL);
2149 g_pEventPolicy->SaveToDB();
2150 }
2151 else
2152 {
2153 m_dwFlags |= CSF_EPP_UPLOAD;
2154 m_ppEPPRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRecordsToUpload);
2155 memset(m_ppEPPRuleList, 0, sizeof(EPRule *) * m_dwNumRecordsToUpload);
2156 }
8f7e2482
VK
2157 DebugPrintf("Accepted EPP upload request for %d rules\n", m_dwNumRecordsToUpload);
2158 }
2159 else
2160 {
2161 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2162 }
2163 }
2164 else
2165 {
2166 // Current user has no rights for event policy management
2167 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2168 }
2169
2170 // Send responce
2171 SendMessage(&msg);
06e7be2f
VK
2172}
2173
2174
2175//
8f7e2482 2176// Process EPP rule received from client
06e7be2f
VK
2177//
2178
8f7e2482 2179void ClientSession::ProcessEPPRecord(CSCPMessage *pRequest)
06e7be2f 2180{
8f7e2482
VK
2181 if (!(m_dwFlags & CSF_EPP_LOCKED))
2182 {
2183 CSCPMessage msg;
2184
2185 msg.SetCode(CMD_REQUEST_COMPLETED);
2186 msg.SetId(pRequest->GetId());
2187 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2188 SendMessage(&msg);
2189 }
2190 else
2191 {
2192 if (m_dwRecordsUploaded < m_dwNumRecordsToUpload)
2193 {
2194 m_ppEPPRuleList[m_dwRecordsUploaded] = new EPRule(pRequest);
2195 m_dwRecordsUploaded++;
2196 if (m_dwRecordsUploaded == m_dwNumRecordsToUpload)
2197 {
2198 CSCPMessage msg;
2199
2200 // All records received, replace event policy...
2201 DebugPrintf("Replacing event processing policy with a new one at %p (%d rules)\n",
2202 m_ppEPPRuleList, m_dwNumRecordsToUpload);
2203 g_pEventPolicy->ReplacePolicy(m_dwNumRecordsToUpload, m_ppEPPRuleList);
043fe1ec 2204 g_pEventPolicy->SaveToDB();
8f7e2482
VK
2205 m_ppEPPRuleList = NULL;
2206
2207 // ... and send final confirmation
2208 msg.SetCode(CMD_REQUEST_COMPLETED);
2209 msg.SetId(pRequest->GetId());
2210 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2211 SendMessage(&msg);
2212
2213 m_dwFlags &= ~CSF_EPP_UPLOAD;
2214 }
2215 }
2216 }
06e7be2f
VK
2217}
2218
2219
2220//
2221// Send list of available MIB files to client
2222//
2223
2224void ClientSession::SendMIBList(DWORD dwRqId)
2225{
2226 CSCPMessage msg;
2227 DWORD dwId1, dwId2, dwNumFiles;
2228 DIR *dir;
2229 int iBufPos;
c9ccd685 2230#ifdef _WIN32
06e7be2f 2231 struct direct *dptr;
c9ccd685
AK
2232#else
2233 struct dirent *dptr;
2234#endif
06e7be2f
VK
2235 char szBuffer[MAX_PATH];
2236 BYTE md5Hash[MD5_DIGEST_SIZE];
2237
2238 // Prepare responce message
2239 msg.SetCode(CMD_MIB_LIST);
2240 msg.SetId(dwRqId);
2241
2242 // Read directory
2243 dwNumFiles = 0;
2244 strcpy(szBuffer, g_szDataDir);
2245 strcat(szBuffer, DDIR_MIBS);
2246 dir = opendir(szBuffer);
2247 if (dir != NULL)
2248 {
06f6e54c 2249 strcat(szBuffer, FS_PATH_SEPARATOR);
06e7be2f
VK
2250 iBufPos = strlen(szBuffer);
2251 dwId1 = VID_MIB_NAME_BASE;
2252 dwId2 = VID_MIB_HASH_BASE;
2253 while((dptr = readdir(dir)) != NULL)
2254 {
06f6e54c
VK
2255 if (dptr->d_name[0] == '.')
2256 continue;
2257
06e7be2f
VK
2258 strcpy(&szBuffer[iBufPos], dptr->d_name);
2259 if (CalculateFileMD5Hash(szBuffer, md5Hash))
2260 {
2261 msg.SetVariable(dwId1++, dptr->d_name);
2262 msg.SetVariable(dwId2++, md5Hash, MD5_DIGEST_SIZE);
2263 dwNumFiles++;
2264 }
2265 }
2266 closedir(dir);
2267 }
2268
2269 msg.SetVariable(VID_NUM_MIBS, dwNumFiles);
2270
2271 // Send responce
2272 SendMessage(&msg);
2273}
2274
2275
2276//
2277// Send requested MIB file to client
2278//
2279
2280void ClientSession::SendMIB(CSCPMessage *pRequest)
2281{
2282 CSCPMessage msg;
2283 BYTE *pFile;
2284 DWORD dwFileSize;
2285 char szBuffer[MAX_PATH], szMIB[MAX_PATH];
2286
2287 // Prepare responce message
2288 msg.SetCode(CMD_MIB);
2289 msg.SetId(pRequest->GetId());
2290
2291 // Get name of the requested file
2292 pRequest->GetVariableStr(VID_MIB_NAME, szMIB, MAX_PATH);
2293
2294 // Load file into memory
2295 strcpy(szBuffer, g_szDataDir);
2296 strcat(szBuffer, DDIR_MIBS);
2297#ifdef _WIN32
2298 strcat(szBuffer, "\\");
2299#else
2300 strcat(szBuffer, "/");
2301#endif
2302 strcat(szBuffer, szMIB);
2303 pFile = LoadFile(szBuffer, &dwFileSize);
2304 if (pFile != NULL)
2305 {
2306 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2307 msg.SetVariable(VID_MIB_FILE_SIZE, dwFileSize);
2308 msg.SetVariable(VID_MIB_FILE, pFile, dwFileSize);
2309 free(pFile);
2310 }
2311 else
2312 {
2313 msg.SetVariable(VID_RCC, RCC_SYSTEM_FAILURE);
2314 }
2315
2316 // Send responce
2317 SendMessage(&msg);
3421c063
VK
2318}
2319
2320
ef44d5ea
VK
2321//
2322// Create new object
2323//
2324
2325void ClientSession::CreateObject(CSCPMessage *pRequest)
2326{
e6b958c4
VK
2327 CSCPMessage msg;
2328 NetObj *pObject, *pParent;
2329 int iClass;
917aa2e6 2330 char *pDescription, szObjectName[MAX_OBJECT_NAME];
b688074e
VK
2331 DWORD dwIpAddr;
2332 BOOL bParentAlwaysValid = FALSE;
e6b958c4
VK
2333
2334 // Prepare responce message
2335 msg.SetCode(CMD_REQUEST_COMPLETED);
2336 msg.SetId(pRequest->GetId());
2337
b688074e
VK
2338 iClass = pRequest->GetVariableShort(VID_OBJECT_CLASS);
2339
e6b958c4
VK
2340 // Find parent object
2341 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
7cbe553e 2342 if (iClass == OBJECT_NODE)
b688074e
VK
2343 {
2344 dwIpAddr = pRequest->GetVariableLong(VID_IP_ADDRESS);
7cbe553e
VK
2345 if ((pParent == NULL) && (dwIpAddr != 0))
2346 {
2347 pParent = FindSubnetForNode(dwIpAddr);
2348 bParentAlwaysValid = TRUE;
2349 }
b688074e
VK
2350 }
2351 if ((pParent != NULL) || (iClass == OBJECT_NODE))
e6b958c4
VK
2352 {
2353 // User should have create access to parent object
b688074e
VK
2354 if ((pParent != NULL) ?
2355 pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE) :
2356 g_pEntireNet->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_CREATE))
e6b958c4 2357 {
62d11997 2358 // Parent object should be of valid type
b688074e 2359 if (bParentAlwaysValid || IsValidParentClass(iClass, (pParent != NULL) ? pParent->Type() : -1))
e6b958c4 2360 {
e6b958c4 2361 pRequest->GetVariableStr(VID_OBJECT_NAME, szObjectName, MAX_OBJECT_NAME);
8f7e2482 2362 if (IsValidObjectName(szObjectName))
e6b958c4 2363 {
62d11997
VK
2364 // Create new object
2365 switch(iClass)
e6b958c4 2366 {
62d11997 2367 case OBJECT_NODE:
b688074e 2368 pObject = PollNewNode(dwIpAddr, pRequest->GetVariableLong(VID_IP_NETMASK),
62d11997
VK
2369 DF_DEFAULT, szObjectName);
2370 break;
2371 case OBJECT_CONTAINER:
2372 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2373 pObject = new Container(szObjectName,
2374 pRequest->GetVariableLong(VID_CATEGORY),
2375 pDescription);
2376 safe_free(pDescription);
2377 NetObjInsert(pObject, TRUE);
2378 break;
2379 case OBJECT_TEMPLATEGROUP:
2380 pDescription = pRequest->GetVariableStr(VID_DESCRIPTION);
2381 pObject = new TemplateGroup(szObjectName, pDescription);
2382 safe_free(pDescription);
2383 NetObjInsert(pObject, TRUE);
2384 break;
2385 case OBJECT_TEMPLATE:
2386 pObject = new Template;
2387 pObject->SetName(szObjectName);
2388 NetObjInsert(pObject, TRUE);
2389 break;
2390 }
917aa2e6 2391
62d11997
VK
2392 // If creation was successful do binding
2393 if (pObject != NULL)
2394 {
7cbe553e
VK
2395 if (pParent != NULL) // parent can be NULL for nodes
2396 {
2397 pParent->AddChild(pObject);
2398 pObject->AddParent(pParent);
2399 }
62d11997
VK
2400 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2401 msg.SetVariable(VID_OBJECT_ID, pObject->Id());
917aa2e6
VK
2402 }
2403 else
2404 {
62d11997 2405 msg.SetVariable(VID_RCC, RCC_OBJECT_CREATION_FAILED);
917aa2e6 2406 }
e6b958c4
VK
2407 }
2408 else
2409 {
8f7e2482 2410 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
e6b958c4
VK
2411 }
2412 }
2413 else
2414 {
2415 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2416 }
2417 }
2418 else
2419 {
2420 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2421 }
2422 }
2423 else
2424 {
2425 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2426 }
2427
2428 // Send responce
2429 SendMessage(&msg);
2430}
2431
2432
2433//
2434// Bind/unbind object
2435//
2436
2437void ClientSession::ChangeObjectBinding(CSCPMessage *pRequest, BOOL bBind)
2438{
2439 CSCPMessage msg;
2440 NetObj *pParent, *pChild;
2441
2442 // Prepare responce message
2443 msg.SetCode(CMD_REQUEST_COMPLETED);
2444 msg.SetId(pRequest->GetId());
2445
2446 // Get parent and child objects
2447 pParent = FindObjectById(pRequest->GetVariableLong(VID_PARENT_ID));
2448 pChild = FindObjectById(pRequest->GetVariableLong(VID_CHILD_ID));
2449
2450 // Check access rights and change binding
2451 if ((pParent != NULL) && (pChild != NULL))
2452 {
2453 // User should have modify access to both objects
2454 if ((pParent->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)) &&
2455 (pChild->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY)))
2456 {
2457 // Parent object should be container or service root
2458 if ((pParent->Type() == OBJECT_CONTAINER) ||
2459 (pParent->Type() == OBJECT_SERVICEROOT))
2460 {
2461 if (bBind)
2462 {
917aa2e6
VK
2463 // Prevent loops
2464 if (!pChild->IsChild(pParent->Id()))
2465 {
2466 pParent->AddChild(pChild);
2467 pChild->AddParent(pParent);
2468 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2469 }
2470 else
2471 {
2472 msg.SetVariable(VID_RCC, RCC_OBJECT_LOOP);
2473 }
e6b958c4
VK
2474 }
2475 else
2476 {
2477 pParent->DeleteChild(pChild);
2478 pChild->DeleteParent(pParent);
917aa2e6 2479 msg.SetVariable(VID_RCC, RCC_SUCCESS);
e6b958c4 2480 }
e6b958c4
VK
2481 }
2482 else
2483 {
2484 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2485 }
2486 }
2487 else
2488 {
2489 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2490 }
2491 }
2492 else
2493 {
2494 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2495 }
2496
2497 // Send responce
2498 SendMessage(&msg);
ef44d5ea 2499}
03482383
VK
2500
2501
88039e6c
VK
2502//
2503// Delete object
2504//
2505
2506void ClientSession::DeleteObject(CSCPMessage *pRequest)
2507{
2508 CSCPMessage msg;
2509 NetObj *pObject;
2510
2511 // Prepare responce message
2512 msg.SetCode(CMD_REQUEST_COMPLETED);
2513 msg.SetId(pRequest->GetId());
2514
2515 // Find object to be deleted
2516 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2517 if (pObject != NULL)
2518 {
2519 // Check if it is a built-in object, like "Entire Network"
2520 if (pObject->Id() >= 10)
2521 {
2522 // Check access rights
2523 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
2524 {
2525 pObject->Delete();
2526 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2527 }
2528 else
2529 {
2530 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2531 }
2532 }
2533 else
2534 {
2535 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2536 }
2537 }
2538 else
2539 {
2540 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2541 }
2542
2543 // Send responce
2544 SendMessage(&msg);
2545}
2546
2547
03482383
VK
2548//
2549// Process changes in alarms
2550//
2551
2552void ClientSession::OnAlarmUpdate(DWORD dwCode, NXC_ALARM *pAlarm)
2553{
2554 UPDATE_INFO *pUpdate;
2555 NetObj *pObject;
2556
2557 if (m_iState == STATE_AUTHENTICATED)
2558 {
2559 pObject = FindObjectById(pAlarm->dwSourceObject);
2560 if (pObject != NULL)
2561 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ_ALARMS))
2562 {
2563 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2564 pUpdate->dwCategory = INFO_CAT_ALARM;
c9363772
VK
2565 pUpdate->dwCode = dwCode;
2566 pUpdate->pData = nx_memdup(pAlarm, sizeof(NXC_ALARM));
03482383
VK
2567 m_pUpdateQueue->Put(pUpdate);
2568 }
2569 }
2570}
2571
2572
2573//
2574// Send all alarms to client
2575//
2576
2577void ClientSession::SendAllAlarms(DWORD dwRqId, BOOL bIncludeAck)
2578{
2579 MutexLock(m_mutexSendAlarms, INFINITE);
2580 g_alarmMgr.SendAlarmsToClient(dwRqId, bIncludeAck, this);
2581 MutexUnlock(m_mutexSendAlarms);
2582}
ee20e615
VK
2583
2584
2585//
2586// Acknowlege alarm
2587//
2588
2589void ClientSession::AcknowlegeAlarm(CSCPMessage *pRequest)
2590{
2591 CSCPMessage msg;
2592 NetObj *pObject;
2593 DWORD dwAlarmId;
2594
2595 // Prepare responce message
2596 msg.SetCode(CMD_REQUEST_COMPLETED);
2597 msg.SetId(pRequest->GetId());
2598
2599 // Get alarm id and it's source object
2600 dwAlarmId = pRequest->GetVariableLong(VID_ALARM_ID);
2601 pObject = g_alarmMgr.GetAlarmSourceObject(dwAlarmId);
2602 if (pObject != NULL)
2603 {
2604 // User should have "acknowlege alarm" right to the object
2605 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_ACK_ALARMS))
2606 {
2607 g_alarmMgr.AckById(dwAlarmId, m_dwUserId);
2608 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2609 }
2610 else
2611 {
2612 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2613 }
2614 }
2615 else
2616 {
2617 // Normally, for existing alarms pObject will not be NULL,
2618 // so we assume that alarm id is invalid
2619 msg.SetVariable(VID_RCC, RCC_INVALID_ALARM_ID);
2620 }
2621
2622 // Send responce
2623 SendMessage(&msg);
2624}
c9363772
VK
2625
2626
2627//
2628// Lock/unlock action configuration database
2629//
2630
2631void ClientSession::LockActionDB(DWORD dwRqId, BOOL bLock)
2632{
2633 CSCPMessage msg;
2634 char szBuffer[256];
2635
2636 // Prepare responce message
2637 msg.SetCode(CMD_REQUEST_COMPLETED);
2638 msg.SetId(dwRqId);
2639
2640 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
2641 {
2642 if (bLock)
2643 {
2644 if (!LockComponent(CID_ACTION_DB, m_dwIndex, m_szUserName, NULL, szBuffer))
2645 {
2646 msg.SetVariable(VID_RCC, RCC_COMPONENT_LOCKED);
2647 msg.SetVariable(VID_LOCKED_BY, szBuffer);
2648 }
2649 else
2650 {
2651 m_dwFlags |= CSF_ACTION_DB_LOCKED;
2652 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2653 }
2654 }
2655 else
2656 {
2657 if (m_dwFlags & CSF_ACTION_DB_LOCKED)
2658 {
2659 UnlockComponent(CID_ACTION_DB);
2660 m_dwFlags &= ~CSF_ACTION_DB_LOCKED;
2661 }
2662 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2663 }
2664 }
2665 else
2666 {
2667 // Current user has no rights for action management
2668 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2669 }
2670
2671 // Send responce
2672 SendMessage(&msg);
2673}
2674
2675
2676//
2677// Create new action
2678//
2679
2680void ClientSession::CreateAction(CSCPMessage *pRequest)
2681{
2682 CSCPMessage msg;
2683
2684 // Prepare responce message
2685 msg.SetCode(CMD_REQUEST_COMPLETED);
2686 msg.SetId(pRequest->GetId());
2687
2688 // Check user rights
2689 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
2690 {
2691 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2692 }
2693 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
2694 {
2695 // Action database have to be locked before any
2696 // changes can be made
2697 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2698 }
2699 else
2700 {
2701 DWORD dwResult, dwActionId;
2702 char szActionName[MAX_USER_NAME];
2703
2704 pRequest->GetVariableStr(VID_ACTION_NAME, szActionName, MAX_OBJECT_NAME);
2705 if (IsValidObjectName(szActionName))
2706 {
2707 dwResult = CreateNewAction(szActionName, &dwActionId);
2708 msg.SetVariable(VID_RCC, dwResult);
2709 if (dwResult == RCC_SUCCESS)
2710 msg.SetVariable(VID_ACTION_ID, dwActionId); // Send id of new action to client
2711 }
2712 else
2713 {
2714 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_NAME);
2715 }
2716 }
2717
2718 // Send responce
2719 SendMessage(&msg);
2720}
2721
2722
2723//
2724// Update existing action's data
2725//
2726
2727void ClientSession::UpdateAction(CSCPMessage *pRequest)
2728{
2729 CSCPMessage msg;
2730
2731 // Prepare responce message
2732 msg.SetCode(CMD_REQUEST_COMPLETED);
2733 msg.SetId(pRequest->GetId());
2734
2735 // Check user rights
2736 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
2737 {
2738 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2739 }
2740 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
2741 {
2742 // Action database have to be locked before any
2743 // changes can be made
2744 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2745 }
2746 else
2747 {
15b8d488 2748 msg.SetVariable(VID_RCC, ModifyActionFromMessage(pRequest));
c9363772
VK
2749 }
2750
2751 // Send responce
2752 SendMessage(&msg);
2753}
2754
2755
2756//
2757// Delete action
2758//
2759
2760void ClientSession::DeleteAction(CSCPMessage *pRequest)
2761{
2762 CSCPMessage msg;
2763 DWORD dwActionId;
2764
2765 // Prepare responce message
2766 msg.SetCode(CMD_REQUEST_COMPLETED);
2767 msg.SetId(pRequest->GetId());
2768
2769 // Check user rights
2770 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS))
2771 {
2772 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2773 }
2774 else if (!(m_dwFlags & CSF_ACTION_DB_LOCKED))
2775 {
2776 // Action database have to be locked before any
2777 // changes can be made
2778 msg.SetVariable(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2779 }
2780 else
2781 {
2782 // Get Id of action to be deleted
2783 dwActionId = pRequest->GetVariableLong(VID_ACTION_ID);
15b8d488 2784 msg.SetVariable(VID_RCC, DeleteActionFromDB(dwActionId));
c9363772
VK
2785 }
2786
2787 // Send responce
2788 SendMessage(&msg);
2789}
2790
2791
2792//
2793// Process changes in actions
2794//
2795
2796void ClientSession::OnActionDBUpdate(DWORD dwCode, NXC_ACTION *pAction)
2797{
2798 UPDATE_INFO *pUpdate;
2799
2800 if (m_iState == STATE_AUTHENTICATED)
2801 {
2802 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS)
2803 {
2804 pUpdate = (UPDATE_INFO *)malloc(sizeof(UPDATE_INFO));
2805 pUpdate->dwCategory = INFO_CAT_ACTION;
2806 pUpdate->dwCode = dwCode;
2807 pUpdate->pData = nx_memdup(pAction, sizeof(NXC_ACTION));
2808 m_pUpdateQueue->Put(pUpdate);
2809 }
2810 }
2811}
e91cb822
VK
2812
2813
2814//
2815// Send all actions to client
2816//
2817
2818void ClientSession::SendAllActions(DWORD dwRqId)
2819{
2820 CSCPMessage msg;
2821
2822 // Prepare responce message
2823 msg.SetCode(CMD_REQUEST_COMPLETED);
2824 msg.SetId(dwRqId);
2825
2826 // Check user rights
2827 if ((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_ACTIONS) ||
2828 (m_dwSystemAccess & SYSTEM_ACCESS_EPP))
2829 {
2830 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2831 SendMessage(&msg);
2832 MutexLock(m_mutexSendActions, INFINITE);
2833 SendActionsToClient(this, dwRqId);
2834 MutexUnlock(m_mutexSendActions);
2835 }
2836 else
2837 {
2838 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2839 SendMessage(&msg);
2840 }
2841}
6849d9be
VK
2842
2843
2844//
2845// Send list of configured container categories to client
2846//
2847
2848void ClientSession::SendContainerCategories(DWORD dwRqId)
2849{
2850 CSCPMessage msg;
2851 DWORD i;
2852
2853 // Prepare responce message
2854 msg.SetCode(CMD_CONTAINER_CAT_DATA);
2855 msg.SetId(dwRqId);
2856
2857 for(i = 0; i < g_dwNumCategories; i++)
2858 {
2859 msg.SetVariable(VID_CATEGORY_ID, g_pContainerCatList[i].dwCatId);
2860 msg.SetVariable(VID_CATEGORY_NAME, g_pContainerCatList[i].szName);
2861 msg.SetVariable(VID_IMAGE_ID, g_pContainerCatList[i].dwImageId);
2862 msg.SetVariable(VID_DESCRIPTION, g_pContainerCatList[i].pszDescription);
2863 SendMessage(&msg);
2864 msg.DeleteAllVariables();
2865 }
2866
2867 // Send end-of-list indicator
2868 msg.SetVariable(VID_CATEGORY_ID, (DWORD)0);
2869 SendMessage(&msg);
2870}
0b89f5fb
VK
2871
2872
2873//
2874// Perform a forced node poll
2875//
2876
2877void ClientSession::ForcedNodePoll(CSCPMessage *pRequest)
2878{
eb8b1960 2879 CSCPMessage msg;
d966d18a 2880 POLLER_START_DATA *pData;
eb8b1960 2881 NetObj *pObject;
d966d18a
VK
2882
2883 pData = (POLLER_START_DATA *)malloc(sizeof(POLLER_START_DATA));
0ba90743 2884 pData->pSession = this;
d966d18a 2885 MutexLock(m_mutexPollerInit, INFINITE);
eb8b1960
VK
2886
2887 // Prepare responce message
d966d18a 2888 pData->dwRqId = pRequest->GetId();
eb8b1960 2889 msg.SetCode(CMD_POLLING_INFO);
d966d18a 2890 msg.SetId(pData->dwRqId);
eb8b1960
VK
2891
2892 // Get polling type
d966d18a 2893 pData->iPollType = pRequest->GetVariableShort(VID_POLL_TYPE);
eb8b1960
VK
2894
2895 // Find object to be deleted
2896 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
2897 if (pObject != NULL)
2898 {
2899 // We can do polls only for node objects
2900 if ((pObject->Type() == OBJECT_NODE) &&
d966d18a 2901 ((pData->iPollType == POLL_STATUS) || (pData->iPollType == POLL_CONFIGURATION)))
eb8b1960
VK
2902 {
2903 // Check access rights
2904 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2905 {
2906 ((Node *)pObject)->IncRefCount();
2907
d966d18a
VK
2908 pData->pNode = (Node *)pObject;
2909 ThreadCreate(PollerThreadStarter, 0, pData);
2910 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
2911 msg.SetVariable(VID_POLLER_MESSAGE, _T("Poll request accepted\r\n"));
eb8b1960
VK
2912 }
2913 else
2914 {
2915 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
2916 }
2917 }
2918 else
2919 {
2920 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
2921 }
2922 }
2923 else
2924 {
2925 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
2926 }
2927
2928 // Send responce
2929 SendMessage(&msg);
d966d18a 2930 MutexUnlock(m_mutexPollerInit);
eb8b1960
VK
2931}
2932
2933
2934//
2935// Send message fro poller to client
2936//
2937
d966d18a 2938void ClientSession::SendPollerMsg(DWORD dwRqId, TCHAR *pszMsg)
eb8b1960
VK
2939{
2940 CSCPMessage msg;
2941
2942 msg.SetCode(CMD_POLLING_INFO);
d966d18a 2943 msg.SetId(dwRqId);
eb8b1960
VK
2944 msg.SetVariable(VID_RCC, RCC_OPERATION_IN_PROGRESS);
2945 msg.SetVariable(VID_POLLER_MESSAGE, pszMsg);
2946 SendMessage(&msg);
0b89f5fb 2947}
d966d18a
VK
2948
2949
2950//
2951// Node poller thread
2952//
2953
2954void ClientSession::PollerThread(Node *pNode, int iPollType, DWORD dwRqId)
2955{
2956 CSCPMessage msg;
2957
2958 // Wait while parent thread finishes initialization
2959 MutexLock(m_mutexPollerInit, INFINITE);
2960 MutexUnlock(m_mutexPollerInit);
2961
0ba90743
VK
2962 switch(iPollType)
2963 {
2964 case POLL_STATUS:
2965 pNode->StatusPoll(this, dwRqId);
2966 break;
2967 case POLL_CONFIGURATION:
2968 pNode->ConfigurationPoll(this, dwRqId);
2969 break;
2970 default:
2971 SendPollerMsg(dwRqId, _T("Invalid poll type requested\r\n"));
2972 break;
2973 }
d966d18a
VK
2974 pNode->DecRefCount();
2975
2976 msg.SetCode(CMD_POLLING_INFO);
2977 msg.SetId(dwRqId);
2978 msg.SetVariable(VID_RCC, RCC_SUCCESS);
2979 SendMessage(&msg);
2980}
b562fca8
VK
2981
2982
2983//
2984// Receive event from user
2985//
2986
2987void ClientSession::OnTrap(CSCPMessage *pRequest)
2988{
2989 CSCPMessage msg;
2990 DWORD dwObjectId, dwEventCode;
2991 int i, iNumArgs;
2992 NetObj *pObject;
2993 TCHAR *pszArgList[32];
2994 TCHAR szFormat[] = "ssssssssssssssssssssssssssssssss";
2995 BOOL bSuccess;
2996
2997 // Prepare responce message
2998 msg.SetCode(CMD_REQUEST_COMPLETED);
2999 msg.SetId(pRequest->GetId());
3000
3001 // Find event's source object
3002 dwObjectId = pRequest->GetVariableLong(VID_OBJECT_ID);
3003 if (dwObjectId != 0)
3004 pObject = FindObjectById(dwObjectId); // Object is specified explicitely
3005 else
3006 pObject = FindNodeByIP(m_dwHostAddr); // Client is the source
3007 if (pObject != NULL)
3008 {
3009 // User should have SEND_EVENTS access right to object
3010 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_SEND_EVENTS))
3011 {
3012 dwEventCode = pRequest->GetVariableLong(VID_EVENT_ID);
3013 iNumArgs = pRequest->GetVariableShort(VID_NUM_ARGS);
3014 for(i = 0; i < iNumArgs; i++)
3015 pszArgList[i] = pRequest->GetVariableStr(VID_EVENT_ARG_BASE + i);
3016
3017 // Following call is not very good, but I'm too lazy now
3018 // to change PostEvent()
3019 szFormat[iNumArgs] = 0;
3020 bSuccess = PostEvent(dwEventCode, pObject->Id(), (iNumArgs > 0) ? szFormat : NULL,
3021 pszArgList[0], pszArgList[1], pszArgList[2], pszArgList[3],
3022 pszArgList[4], pszArgList[5], pszArgList[6], pszArgList[7],
3023 pszArgList[8], pszArgList[9], pszArgList[10], pszArgList[11],
3024 pszArgList[12], pszArgList[13], pszArgList[14], pszArgList[15],
3025 pszArgList[16], pszArgList[17], pszArgList[18], pszArgList[19],
3026 pszArgList[20], pszArgList[21], pszArgList[22], pszArgList[23],
3027 pszArgList[24], pszArgList[25], pszArgList[26], pszArgList[27],
6ed0d23d 3028 pszArgList[28], pszArgList[29], pszArgList[30], pszArgList[31]);
b562fca8
VK
3029
3030 // Cleanup
3031 for(i = 0; i < iNumArgs; i++)
3032 free(pszArgList[i]);
3033
3034 msg.SetVariable(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_EVENT_CODE);
3035 }
3036 else
3037 {
3038 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3039 }
3040 }
3041 else
3042 {
3043 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3044 }
3045
3046 // Send responce
3047 SendMessage(&msg);
3048}
ed1140dc
VK
3049
3050
3051//
3052// Wake up node
3053//
3054
3055void ClientSession::OnWakeUpNode(CSCPMessage *pRequest)
3056{
3057 NetObj *pObject;
3058 CSCPMessage msg;
3059
3060 // Prepare responce message
3061 msg.SetCode(CMD_REQUEST_COMPLETED);
3062 msg.SetId(pRequest->GetId());
3063
3064 // Find node or interface object
3065 pObject = FindObjectById(pRequest->GetVariableLong(VID_OBJECT_ID));
3066 if (pObject != NULL)
3067 {
3068 if ((pObject->Type() == OBJECT_NODE) ||
3069 (pObject->Type() == OBJECT_INTERFACE))
3070 {
3071 if (pObject->CheckAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3072 {
3073 DWORD dwResult;
3074
3075 if (pObject->Type() == OBJECT_NODE)
3076 dwResult = ((Node *)pObject)->WakeUp();
3077 else
3078 dwResult = ((Interface *)pObject)->WakeUp();
3079 msg.SetVariable(VID_RCC, dwResult);
3080 }
3081 else
3082 {
3083 msg.SetVariable(VID_RCC, RCC_ACCESS_DENIED);
3084 }
3085 }
3086 else
3087 {
3088 msg.SetVariable(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3089 }
3090 }
3091 else
3092 {
3093 msg.SetVariable(VID_RCC, RCC_INVALID_OBJECT_ID);
3094 }
3095
3096 // Send responce
3097 SendMessage(&msg);
3098}
b4895bbe
VK
3099
3100
3101//
3102// Create new trap configuration record
3103//
3104
3105void ClientSession::CreateTrap(CSCPMessage *pRequest)
3106{
3107}
3108
3109
3110//
3111// Update trap configuration record
3112//
3113
3114void ClientSession::UpdateTrap(CSCPMessage *pRequest)
3115{
3116}
3117
3118
3119//
3120// Delete trap configuration record
3121//
3122
3123void ClientSession::DeleteTrap(CSCPMessage *pRequest)
3124{
3125}
3126
3127
3128//
3129// Lock/unlock trap configuration
3130//
3131
3132void ClientSession::LockTrapCfg(DWORD dwRqId, BOOL bLock)
3133{
3134}
3135
3136
3137//
3138// Send all trap configuration records to client
3139//
3140
3141void ClientSession::SendAllTraps(DWORD dwRqId)
3142{
3143}