Collected DCI data recalculation based on stored raw values and current transformatio...
[public/netxms.git] / src / server / core / session.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Copyright (C) 2003-2017 Raden Solutions
4 **
5 ** This program is free software; you can redistribute it and/or modify
6 ** it under the terms of the GNU General Public License as published by
7 ** the Free Software Foundation; either version 2 of the License, or
8 ** (at your option) any later version.
9 **
10 ** This program is distributed in the hope that it will be useful,
11 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 ** GNU General Public License for more details.
14 **
15 ** You should have received a copy of the GNU General Public License
16 ** along with this program; if not, write to the Free Software
17 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 **
19 ** File: session.cpp
20 **
21 **/
22
23 #include "nxcore.h"
24 #include <netxms_mt.h>
25 #include <nxtools.h>
26 #include <nxstat.h>
27
28 #ifdef _WIN32
29 #include <psapi.h>
30 #else
31 #include <dirent.h>
32 #endif
33
34 #ifdef WITH_ZMQ
35 #include "zeromq.h"
36 #endif
37
38 // WARNING! this hack works only for d2i_X509(); be careful when adding new code
39 #ifdef OPENSSL_CONST
40 # undef OPENSSL_CONST
41 #endif
42 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
43 # define OPENSSL_CONST const
44 #else
45 # define OPENSSL_CONST
46 #endif
47
48 /**
49 * Constants
50 */
51 #define TRAP_CREATE 1
52 #define TRAP_UPDATE 2
53 #define TRAP_DELETE 3
54
55 #define MAX_MSG_SIZE 4194304
56
57 /**
58 * Externals
59 */
60 extern Queue g_nodePollerQueue;
61 extern Queue g_dciCacheLoaderQueue;
62 extern ThreadPool *g_dataCollectorThreadPool;
63
64 void UnregisterClientSession(int id);
65 void ResetDiscoveryPoller();
66 NXCPMessage *ForwardMessageToReportingServer(NXCPMessage *request, ClientSession *session);
67 void RemovePendingFileTransferRequests(ClientSession *session);
68 bool UpdateAddressListFromMessage(NXCPMessage *msg);
69 void FillComponentsMessage(NXCPMessage *msg);
70
71 void GetPredictionEngines(NXCPMessage *msg);
72 bool GetPredictedData(ClientSession *session, const NXCPMessage *request, NXCPMessage *response, DataCollectionTarget *dcTarget);
73
74 void GetAgentTunnels(NXCPMessage *msg);
75 UINT32 BindAgentTunnel(UINT32 tunnelId, UINT32 nodeId);
76 UINT32 UnbindAgentTunnel(UINT32 nodeId);
77
78
79 /**
80 * Node poller start data
81 */
82 typedef struct
83 {
84 ClientSession *pSession;
85 DataCollectionTarget *pTarget;
86 int iPollType;
87 UINT32 dwRqId;
88 } POLLER_START_DATA;
89
90 /**
91 * Additional processing thread start data
92 */
93 typedef struct
94 {
95 ClientSession *pSession;
96 NXCPMessage *pMsg;
97 } PROCTHREAD_START_DATA;
98
99 /**
100 * Callback to delete agent connections for loading files in destructor
101 */
102 static void DeleteCallback(NetObj* obj, void *data)
103 {
104 ((AgentConnection *)obj)->decRefCount();
105 }
106
107 /**
108 * Callback for sending image library delete notifications
109 */
110 static void ImageLibraryDeleteCallback(ClientSession *pSession, void *pArg)
111 {
112 pSession->onLibraryImageChange(*((const uuid *)pArg), true);
113 }
114
115 /**
116 * Additional message processing thread starters
117 */
118 #define CALL_IN_NEW_THREAD(func, msg) \
119 { \
120 PROCTHREAD_START_DATA *pData = (PROCTHREAD_START_DATA *)malloc(sizeof(PROCTHREAD_START_DATA)); \
121 pData->pSession = this; \
122 pData->pMsg = msg; \
123 msg = NULL; /* prevent deletion by main processing thread*/ \
124 InterlockedIncrement(&m_refCount); \
125 ThreadPoolExecute(g_mainThreadPool, ThreadStarter_##func, pData); \
126 }
127
128 #define DEFINE_THREAD_STARTER(func) \
129 void ClientSession::ThreadStarter_##func(void *pArg) \
130 { \
131 ((PROCTHREAD_START_DATA *)pArg)->pSession->debugPrintf(6, _T("Method ") _T(#func) _T(" called on background thread")); \
132 ((PROCTHREAD_START_DATA *)pArg)->pSession->func(((PROCTHREAD_START_DATA *)pArg)->pMsg); \
133 InterlockedDecrement(&((PROCTHREAD_START_DATA *)pArg)->pSession->m_refCount); \
134 delete ((PROCTHREAD_START_DATA *)pArg)->pMsg; \
135 free(pArg); \
136 }
137
138 DEFINE_THREAD_STARTER(cancelFileMonitoring)
139 DEFINE_THREAD_STARTER(clearDCIData)
140 DEFINE_THREAD_STARTER(createObject)
141 DEFINE_THREAD_STARTER(executeAction)
142 DEFINE_THREAD_STARTER(executeScript)
143 DEFINE_THREAD_STARTER(executeLibraryScript)
144 DEFINE_THREAD_STARTER(fileManagerControl)
145 DEFINE_THREAD_STARTER(findIpAddress)
146 DEFINE_THREAD_STARTER(findMacAddress)
147 DEFINE_THREAD_STARTER(findHostname)
148 DEFINE_THREAD_STARTER(findNodeConnection)
149 DEFINE_THREAD_STARTER(forceDCIPoll)
150 DEFINE_THREAD_STARTER(forwardToReportingServer)
151 DEFINE_THREAD_STARTER(getAgentFile)
152 DEFINE_THREAD_STARTER(getAlarms)
153 DEFINE_THREAD_STARTER(getAlarmEvents)
154 DEFINE_THREAD_STARTER(getCollectedData)
155 DEFINE_THREAD_STARTER(getLocationHistory)
156 DEFINE_THREAD_STARTER(getNetworkPath)
157 DEFINE_THREAD_STARTER(getPredictedData)
158 DEFINE_THREAD_STARTER(getRoutingTable)
159 DEFINE_THREAD_STARTER(getServerFile)
160 DEFINE_THREAD_STARTER(getServerLogQueryData)
161 DEFINE_THREAD_STARTER(getSwitchForwardingDatabase)
162 DEFINE_THREAD_STARTER(getTableCollectedData)
163 DEFINE_THREAD_STARTER(importConfiguration)
164 DEFINE_THREAD_STARTER(openHelpdeskIssue)
165 DEFINE_THREAD_STARTER(processConsoleCommand)
166 DEFINE_THREAD_STARTER(queryAgentTable)
167 DEFINE_THREAD_STARTER(queryL2Topology)
168 DEFINE_THREAD_STARTER(queryParameter)
169 DEFINE_THREAD_STARTER(queryServerLog)
170 DEFINE_THREAD_STARTER(recalculateDCIValues)
171 DEFINE_THREAD_STARTER(sendMib)
172 DEFINE_THREAD_STARTER(uploadUserFileToAgent)
173 DEFINE_THREAD_STARTER(getRepositories)
174 DEFINE_THREAD_STARTER(addRepository)
175 DEFINE_THREAD_STARTER(modifyRepository)
176 DEFINE_THREAD_STARTER(deleteRepository)
177
178 /**
179 * Client communication read thread starter
180 */
181 THREAD_RESULT THREAD_CALL ClientSession::readThreadStarter(void *pArg)
182 {
183 ThreadSetName("SessionReader");
184 ((ClientSession *)pArg)->readThread();
185
186 // When ClientSession::ReadThread exits, all other session
187 // threads are already stopped, so we can safely destroy
188 // session object
189 UnregisterClientSession(((ClientSession *)pArg)->getId());
190 delete (ClientSession *)pArg;
191 return THREAD_OK;
192 }
193
194 /**
195 * Client communication write thread starter
196 */
197 THREAD_RESULT THREAD_CALL ClientSession::writeThreadStarter(void *pArg)
198 {
199 ThreadSetName("SessionWriter");
200 ((ClientSession *)pArg)->writeThread();
201 return THREAD_OK;
202 }
203
204 /**
205 * Received message processing thread starter
206 */
207 THREAD_RESULT THREAD_CALL ClientSession::processingThreadStarter(void *pArg)
208 {
209 ThreadSetName("SessionProc");
210 ((ClientSession *)pArg)->processingThread();
211 return THREAD_OK;
212 }
213
214 /**
215 * Client session class constructor
216 */
217 ClientSession::ClientSession(SOCKET hSocket, const InetAddress& addr)
218 {
219 m_sendQueue = new Queue;
220 m_requestQueue = new Queue;
221 m_hSocket = hSocket;
222 m_id = -1;
223 m_state = SESSION_STATE_INIT;
224 m_pCtx = NULL;
225 m_hWriteThread = INVALID_THREAD_HANDLE;
226 m_hProcessingThread = INVALID_THREAD_HANDLE;
227 m_mutexSocketWrite = MutexCreate();
228 m_mutexSendObjects = MutexCreate();
229 m_mutexSendAlarms = MutexCreate();
230 m_mutexSendActions = MutexCreate();
231 m_mutexSendAuditLog = MutexCreate();
232 m_mutexPollerInit = MutexCreate();
233 m_subscriptionLock = MutexCreate();
234 m_subscriptions = new StringObjectMap<UINT32>(true);
235 m_dwFlags = 0;
236 m_clientType = CLIENT_TYPE_DESKTOP;
237 m_clientAddr = addr;
238 m_clientAddr.toString(m_workstation);
239 m_webServerAddress[0] = 0;
240 m_loginName[0] = 0;
241 _tcscpy(m_sessionName, _T("<not logged in>"));
242 _tcscpy(m_clientInfo, _T("n/a"));
243 m_dwUserId = INVALID_INDEX;
244 m_dwSystemAccess = 0;
245 m_dwOpenDCIListSize = 0;
246 m_pOpenDCIList = NULL;
247 m_ppEPPRuleList = NULL;
248 m_wCurrentCmd = 0;
249 m_dwNumRecordsToUpload = 0;
250 m_dwRecordsUploaded = 0;
251 m_refCount = 0;
252 m_dwEncryptionRqId = 0;
253 m_dwEncryptionResult = 0;
254 m_condEncryptionSetup = INVALID_CONDITION_HANDLE;
255 m_console = NULL;
256 m_loginTime = time(NULL);
257 m_musicTypeList.add(_T("wav"));
258 _tcscpy(m_language, _T("en"));
259 m_serverCommands = new HashMap<UINT32, CommandExec>(true);
260 m_downloadFileMap = new HashMap<UINT32, ServerDownloadFileInfo>(true);
261 }
262
263 /**
264 * Destructor
265 */
266 ClientSession::~ClientSession()
267 {
268 if (m_hSocket != -1)
269 closesocket(m_hSocket);
270 delete m_sendQueue;
271 delete m_requestQueue;
272 MutexDestroy(m_mutexSocketWrite);
273 MutexDestroy(m_mutexSendObjects);
274 MutexDestroy(m_mutexSendAlarms);
275 MutexDestroy(m_mutexSendActions);
276 MutexDestroy(m_mutexSendAuditLog);
277 MutexDestroy(m_mutexPollerInit);
278 MutexDestroy(m_subscriptionLock);
279 delete m_subscriptions;
280 free(m_pOpenDCIList);
281 if (m_ppEPPRuleList != NULL)
282 {
283 UINT32 i;
284
285 if (m_dwFlags & CSF_EPP_UPLOAD) // Aborted in the middle of EPP transfer
286 for(i = 0; i < m_dwRecordsUploaded; i++)
287 delete m_ppEPPRuleList[i];
288 free(m_ppEPPRuleList);
289 }
290 if (m_pCtx != NULL)
291 m_pCtx->decRefCount();
292 if (m_condEncryptionSetup != INVALID_CONDITION_HANDLE)
293 ConditionDestroy(m_condEncryptionSetup);
294
295 if (m_console != NULL)
296 {
297 delete m_console->pMsg;
298 free(m_console);
299 }
300 m_musicTypeList.clear();
301 if (m_agentConn.size() > 0)
302 {
303 m_agentConn.forEach(&DeleteCallback, NULL);
304 }
305
306 delete m_serverCommands;
307 delete m_downloadFileMap;
308 }
309
310 /**
311 * Start all threads
312 */
313 void ClientSession::run()
314 {
315 m_hWriteThread = ThreadCreateEx(writeThreadStarter, 0, this);
316 m_hProcessingThread = ThreadCreateEx(processingThreadStarter, 0, this);
317 ThreadCreate(readThreadStarter, 0, this);
318 }
319
320 /**
321 * Print debug information
322 */
323 void ClientSession::debugPrintf(int level, const TCHAR *format, ...)
324 {
325 if (level <= nxlog_get_debug_level())
326 {
327 va_list args;
328 TCHAR buffer[8192];
329
330 va_start(args, format);
331 _vsntprintf(buffer, 8192, format, args);
332 va_end(args);
333 DbgPrintf(level, _T("[CLSN-%d] %s"), m_id, buffer);
334 }
335 }
336
337 /**
338 * Write audit log
339 */
340 void ClientSession::writeAuditLog(const TCHAR *subsys, bool success, UINT32 objectId, const TCHAR *format, ...)
341 {
342 va_list args;
343 va_start(args, format);
344 WriteAuditLog2(subsys, success, m_dwUserId, m_workstation, m_id, objectId, format, args);
345 va_end(args);
346 }
347
348 /**
349 * Write audit log with old and new values for changed entity
350 */
351 void ClientSession::writeAuditLogWithValues(const TCHAR *subsys, bool success, UINT32 objectId, const TCHAR *oldValue, const TCHAR *newValue, const TCHAR *format, ...)
352 {
353 va_list args;
354 va_start(args, format);
355 WriteAuditLogWithValues2(subsys, success, m_dwUserId, m_workstation, m_id, objectId, oldValue, newValue, format, args);
356 va_end(args);
357 }
358
359 /**
360 * Write audit log with old and new values for changed entity
361 */
362 void ClientSession::writeAuditLogWithValues(const TCHAR *subsys, bool success, UINT32 objectId, json_t *oldValue, json_t *newValue, const TCHAR *format, ...)
363 {
364 va_list args;
365 va_start(args, format);
366 WriteAuditLogWithJsonValues2(subsys, success, m_dwUserId, m_workstation, m_id, objectId, oldValue, newValue, format, args);
367 va_end(args);
368 }
369
370 /**
371 * Check channel subscription
372 */
373 bool ClientSession::isSubscribedTo(const TCHAR *channel) const
374 {
375 MutexLock(m_subscriptionLock);
376 bool subscribed = m_subscriptions->contains(channel);
377 MutexUnlock(m_subscriptionLock);
378 return subscribed;
379 }
380
381 /**
382 * Read thread
383 */
384 void ClientSession::readThread()
385 {
386 TCHAR szBuffer[256];
387 UINT32 i;
388 NetObj *object;
389
390 SocketMessageReceiver receiver(m_hSocket, 4096, MAX_MSG_SIZE);
391 while(true)
392 {
393 MessageReceiverResult result;
394 NXCPMessage *msg = receiver.readMessage(900000, &result);
395
396 // Check for decryption error
397 if (result == MSGRECV_DECRYPTION_FAILURE)
398 {
399 debugPrintf(4, _T("readThread: Unable to decrypt received message"));
400 continue;
401 }
402
403 // Receive error
404 if (msg == NULL)
405 {
406 if (result == MSGRECV_CLOSED)
407 debugPrintf(5, _T("readThread: connection closed"));
408 else
409 debugPrintf(5, _T("readThread: message receiving error (%s)"), AbstractMessageReceiver::resultToText(result));
410 break;
411 }
412
413 if (nxlog_get_debug_level() >= 8)
414 {
415 String msgDump = NXCPMessage::dump(receiver.getRawMessageBuffer(), NXCP_VERSION);
416 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR *)msgDump);
417 }
418
419 // Special handling for raw messages
420 if (msg->isBinary())
421 {
422 debugPrintf(6, _T("Received raw message %s"), NXCPMessageCodeName(msg->getCode(), szBuffer));
423
424 if ((msg->getCode() == CMD_FILE_DATA) ||
425 (msg->getCode() == CMD_ABORT_FILE_TRANSFER))
426 {
427 ServerDownloadFileInfo *dInfo = m_downloadFileMap->get(msg->getId());
428 if (dInfo != NULL)
429 {
430 if (msg->getCode() == CMD_FILE_DATA)
431 {
432 if (dInfo->write(msg->getBinaryData(), msg->getBinaryDataSize(), msg->isCompressedStream()))
433 {
434 if (msg->isEndOfFile())
435 {
436 debugPrintf(6, _T("Got end of file marker"));
437 NXCPMessage response;
438
439 response.setCode(CMD_REQUEST_COMPLETED);
440 response.setId(msg->getId());
441 response.setField(VID_RCC, RCC_SUCCESS);
442 sendMessage(&response);
443
444 dInfo->close(true);
445 m_downloadFileMap->remove(msg->getId());
446 }
447 }
448 else
449 {
450 debugPrintf(6, _T("I/O error"));
451 // I/O error
452 NXCPMessage response;
453
454 response.setCode(CMD_REQUEST_COMPLETED);
455 response.setId(msg->getId());
456 response.setField(VID_RCC, RCC_IO_ERROR);
457 sendMessage(&response);
458
459 dInfo->close(false);
460 m_downloadFileMap->remove(msg->getId());
461 }
462 }
463 else
464 {
465 // Abort current file transfer because of client's problem
466 dInfo->close(false);
467 m_downloadFileMap->remove(msg->getId());
468 }
469 }
470 else
471 {
472 AgentConnection *conn = (AgentConnection *)m_agentConn.get(msg->getId());
473 if (conn != NULL)
474 {
475 if (msg->getCode() == CMD_FILE_DATA)
476 {
477 if (conn->sendMessage(msg)) //send raw message
478 {
479 if (msg->isEndOfFile())
480 {
481 debugPrintf(6, _T("Got end of file marker"));
482 //get response with specific ID if ok< then send ok, else send error
483 m_agentConn.remove(msg->getId());
484 conn->decRefCount();
485
486 NXCPMessage response;
487 response.setCode(CMD_REQUEST_COMPLETED);
488 response.setId(msg->getId());
489 response.setField(VID_RCC, RCC_SUCCESS);
490 sendMessage(&response);
491 }
492 }
493 else
494 {
495 debugPrintf(6, _T("Error while sending to agent"));
496 // I/O error
497 m_agentConn.remove(msg->getId());
498 conn->decRefCount();
499
500 NXCPMessage response;
501 response.setCode(CMD_REQUEST_COMPLETED);
502 response.setId(msg->getId());
503 response.setField(VID_RCC, RCC_IO_ERROR); //set result that came from agent
504 sendMessage(&response);
505 }
506 }
507 else
508 {
509 // Resend abort message
510 conn->sendMessage(msg);
511 m_agentConn.remove(msg->getId());
512 conn->decRefCount();
513 }
514 }
515 else
516 {
517 debugPrintf(4, _T("Out of state message (ID: %d)"), msg->getId());
518 }
519 }
520 }
521 delete msg;
522 }
523 else
524 {
525 if ((msg->getCode() == CMD_SESSION_KEY) && (msg->getId() == m_dwEncryptionRqId))
526 {
527 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(msg->getCode(), szBuffer));
528 m_dwEncryptionResult = SetupEncryptionContext(msg, &m_pCtx, NULL, g_pServerKey, NXCP_VERSION);
529 receiver.setEncryptionContext(m_pCtx);
530 ConditionSet(m_condEncryptionSetup);
531 m_dwEncryptionRqId = 0;
532 delete msg;
533 }
534 else if (msg->getCode() == CMD_KEEPALIVE)
535 {
536 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(msg->getCode(), szBuffer));
537 respondToKeepalive(msg->getId());
538 delete msg;
539 }
540 else
541 {
542 m_requestQueue->put(msg);
543 }
544 }
545 }
546
547 // Mark as terminated (sendMessage calls will not work after that point)
548 m_dwFlags |= CSF_TERMINATED;
549
550 // Notify other threads to exit
551 NXCP_MESSAGE *rawMsg;
552 while((rawMsg = (NXCP_MESSAGE *)m_sendQueue->get()) != NULL)
553 free(rawMsg);
554 m_sendQueue->put(INVALID_POINTER_VALUE);
555
556 NXCPMessage *msg;
557 while((msg = (NXCPMessage *)m_requestQueue->get()) != NULL)
558 delete msg;
559 m_requestQueue->put(INVALID_POINTER_VALUE);
560
561 // Wait for other threads to finish
562 ThreadJoin(m_hWriteThread);
563 ThreadJoin(m_hProcessingThread);
564
565 // remove all pending file transfers from reporting server
566 RemovePendingFileTransferRequests(this);
567
568 // Remove all locks created by this session
569 RemoveAllSessionLocks(m_id);
570 for(i = 0; i < m_dwOpenDCIListSize; i++)
571 {
572 object = FindObjectById(m_pOpenDCIList[i]);
573 if (object != NULL)
574 if (object->isDataCollectionTarget() || (object->getObjectClass() == OBJECT_TEMPLATE))
575 ((Template *)object)->unlockDCIList(m_id);
576 }
577
578 // Waiting while reference count becomes 0
579 if (m_refCount > 0)
580 {
581 debugPrintf(3, _T("Waiting for pending requests..."));
582 do
583 {
584 ThreadSleep(1);
585 } while(m_refCount > 0);
586 }
587
588 if (m_dwFlags & CSF_AUTHENTICATED)
589 {
590 CALL_ALL_MODULES(pfClientSessionClose, (this));
591 WriteAuditLog(AUDIT_SECURITY, TRUE, m_dwUserId, m_workstation, m_id, 0, _T("User logged out (client: %s)"), m_clientInfo);
592 }
593 debugPrintf(3, _T("Session closed"));
594 }
595
596 /**
597 * Network write thread
598 */
599 void ClientSession::writeThread()
600 {
601 while(true)
602 {
603 NXCP_MESSAGE *rawMsg = (NXCP_MESSAGE *)m_sendQueue->getOrBlock();
604 if (rawMsg == INVALID_POINTER_VALUE) // Session termination indicator
605 break;
606
607 sendRawMessage(rawMsg);
608 free(rawMsg);
609 }
610 }
611
612 /**
613 * Message processing thread
614 */
615 void ClientSession::processingThread()
616 {
617 NXCPMessage *pMsg;
618 TCHAR szBuffer[128];
619 UINT32 i;
620 int status;
621
622 while(true)
623 {
624 pMsg = (NXCPMessage *)m_requestQueue->getOrBlock();
625 if (pMsg == INVALID_POINTER_VALUE) // Session termination indicator
626 break;
627
628 m_wCurrentCmd = pMsg->getCode();
629 debugPrintf(6, _T("Received message %s"), NXCPMessageCodeName(m_wCurrentCmd, szBuffer));
630 if (!(m_dwFlags & CSF_AUTHENTICATED) &&
631 (m_wCurrentCmd != CMD_LOGIN) &&
632 (m_wCurrentCmd != CMD_GET_SERVER_INFO) &&
633 (m_wCurrentCmd != CMD_REQUEST_ENCRYPTION) &&
634 (m_wCurrentCmd != CMD_GET_MY_CONFIG) &&
635 (m_wCurrentCmd != CMD_REGISTER_AGENT))
636 {
637 delete pMsg;
638 continue;
639 }
640
641 m_state = SESSION_STATE_PROCESSING;
642 switch(m_wCurrentCmd)
643 {
644 case CMD_LOGIN:
645 login(pMsg);
646 break;
647 case CMD_GET_SERVER_INFO:
648 sendServerInfo(pMsg->getId());
649 break;
650 case CMD_GET_MY_CONFIG:
651 sendConfigForAgent(pMsg);
652 break;
653 case CMD_GET_OBJECTS:
654 sendAllObjects(pMsg);
655 break;
656 case CMD_GET_SELECTED_OBJECTS:
657 sendSelectedObjects(pMsg);
658 break;
659 case CMD_GET_CONFIG_VARLIST:
660 getConfigurationVariables(pMsg->getId());
661 break;
662 case CMD_GET_PUBLIC_CONFIG_VAR:
663 getPublicConfigurationVariable(pMsg);
664 break;
665 case CMD_SET_CONFIG_VARIABLE:
666 setConfigurationVariable(pMsg);
667 break;
668 case CMD_SET_CONFIG_TO_DEFAULT:
669 setDefaultConfigurationVariableValues(pMsg);
670 break;
671 case CMD_DELETE_CONFIG_VARIABLE:
672 deleteConfigurationVariable(pMsg);
673 break;
674 case CMD_CONFIG_GET_CLOB:
675 getConfigCLOB(pMsg);
676 break;
677 case CMD_CONFIG_SET_CLOB:
678 setConfigCLOB(pMsg);
679 break;
680 case CMD_GET_ALARM_CATEGORIES:
681 getAlarmCategories(pMsg->getId());
682 break;
683 case CMD_MODIFY_ALARM_CATEGORY:
684 modifyAlarmCategory(pMsg);
685 break;
686 case CMD_DELETE_ALARM_CATEGORY:
687 deleteAlarmCategory(pMsg);
688 break;
689 case CMD_LOAD_EVENT_DB:
690 sendEventDB(pMsg);
691 break;
692 case CMD_SET_EVENT_INFO:
693 modifyEventTemplate(pMsg);
694 break;
695 case CMD_DELETE_EVENT_TEMPLATE:
696 deleteEventTemplate(pMsg);
697 break;
698 case CMD_GENERATE_EVENT_CODE:
699 generateEventCode(pMsg->getId());
700 break;
701 case CMD_MODIFY_OBJECT:
702 modifyObject(pMsg);
703 break;
704 case CMD_SET_OBJECT_MGMT_STATUS:
705 changeObjectMgmtStatus(pMsg);
706 break;
707 case CMD_ENTER_MAINT_MODE:
708 enterMaintenanceMode(pMsg);
709 break;
710 case CMD_LEAVE_MAINT_MODE:
711 leaveMaintenanceMode(pMsg);
712 break;
713 case CMD_LOAD_USER_DB:
714 sendUserDB(pMsg->getId());
715 break;
716 case CMD_CREATE_USER:
717 createUser(pMsg);
718 break;
719 case CMD_UPDATE_USER:
720 updateUser(pMsg);
721 break;
722 case CMD_DETACH_LDAP_USER:
723 detachLdapUser(pMsg);
724 break;
725 case CMD_DELETE_USER:
726 deleteUser(pMsg);
727 break;
728 case CMD_LOCK_USER_DB:
729 lockUserDB(pMsg->getId(), TRUE);
730 break;
731 case CMD_UNLOCK_USER_DB:
732 lockUserDB(pMsg->getId(), FALSE);
733 break;
734 case CMD_SET_PASSWORD:
735 setPassword(pMsg);
736 break;
737 case CMD_VALIDATE_PASSWORD:
738 validatePassword(pMsg);
739 break;
740 case CMD_GET_NODE_DCI_LIST:
741 openNodeDCIList(pMsg);
742 break;
743 case CMD_UNLOCK_NODE_DCI_LIST:
744 closeNodeDCIList(pMsg);
745 break;
746 case CMD_CREATE_NEW_DCI:
747 case CMD_MODIFY_NODE_DCI:
748 case CMD_DELETE_NODE_DCI:
749 modifyNodeDCI(pMsg);
750 break;
751 case CMD_SET_DCI_STATUS:
752 changeDCIStatus(pMsg);
753 break;
754 case CMD_COPY_DCI:
755 copyDCI(pMsg);
756 break;
757 case CMD_APPLY_TEMPLATE:
758 applyTemplate(pMsg);
759 break;
760 case CMD_GET_DCI_DATA:
761 CALL_IN_NEW_THREAD(getCollectedData, pMsg);
762 break;
763 case CMD_GET_TABLE_DCI_DATA:
764 CALL_IN_NEW_THREAD(getTableCollectedData, pMsg);
765 break;
766 case CMD_CLEAR_DCI_DATA:
767 CALL_IN_NEW_THREAD(clearDCIData, pMsg);
768 break;
769 case CMD_FORCE_DCI_POLL:
770 CALL_IN_NEW_THREAD(forceDCIPoll, pMsg);
771 break;
772 case CMD_RECALCULATE_DCI_VALUES:
773 CALL_IN_NEW_THREAD(recalculateDCIValues, pMsg);
774 break;
775 case CMD_OPEN_EPP:
776 openEPP(pMsg);
777 break;
778 case CMD_CLOSE_EPP:
779 closeEPP(pMsg->getId());
780 break;
781 case CMD_SAVE_EPP:
782 saveEPP(pMsg);
783 break;
784 case CMD_EPP_RECORD:
785 processEPPRecord(pMsg);
786 break;
787 case CMD_GET_MIB_TIMESTAMP:
788 sendMIBTimestamp(pMsg->getId());
789 break;
790 case CMD_GET_MIB:
791 CALL_IN_NEW_THREAD(sendMib, pMsg);
792 break;
793 case CMD_CREATE_OBJECT:
794 CALL_IN_NEW_THREAD(createObject, pMsg);
795 break;
796 case CMD_BIND_OBJECT:
797 changeObjectBinding(pMsg, TRUE);
798 break;
799 case CMD_UNBIND_OBJECT:
800 changeObjectBinding(pMsg, FALSE);
801 break;
802 case CMD_ADD_CLUSTER_NODE:
803 addClusterNode(pMsg);
804 break;
805 case CMD_GET_ALL_ALARMS:
806 CALL_IN_NEW_THREAD(getAlarms, pMsg);
807 break;
808 case CMD_GET_ALARM_COMMENTS:
809 getAlarmComments(pMsg);
810 break;
811 case CMD_SET_ALARM_STATUS_FLOW:
812 updateAlarmStatusFlow(pMsg);
813 break;
814 case CMD_UPDATE_ALARM_COMMENT:
815 updateAlarmComment(pMsg);
816 break;
817 case CMD_DELETE_ALARM_COMMENT:
818 deleteAlarmComment(pMsg);
819 break;
820 case CMD_GET_ALARM:
821 getAlarm(pMsg);
822 break;
823 case CMD_GET_ALARM_EVENTS:
824 CALL_IN_NEW_THREAD(getAlarmEvents, pMsg);
825 break;
826 case CMD_ACK_ALARM:
827 acknowledgeAlarm(pMsg);
828 break;
829 case CMD_RESOLVE_ALARM:
830 resolveAlarm(pMsg, false);
831 break;
832 case CMD_TERMINATE_ALARM:
833 resolveAlarm(pMsg, true);
834 break;
835 case CMD_DELETE_ALARM:
836 deleteAlarm(pMsg);
837 break;
838 case CMD_BULK_RESOLVE_ALARMS:
839 bulkResolveAlarms(pMsg, false);
840 break;
841 case CMD_BULK_TERMINATE_ALARMS:
842 bulkResolveAlarms(pMsg, true);
843 break;
844 case CMD_OPEN_HELPDESK_ISSUE:
845 CALL_IN_NEW_THREAD(openHelpdeskIssue, pMsg);
846 break;
847 case CMD_GET_HELPDESK_URL:
848 getHelpdeskUrl(pMsg);
849 break;
850 case CMD_UNLINK_HELPDESK_ISSUE:
851 unlinkHelpdeskIssue(pMsg);
852 break;
853 case CMD_CREATE_ACTION:
854 createAction(pMsg);
855 break;
856 case CMD_MODIFY_ACTION:
857 updateAction(pMsg);
858 break;
859 case CMD_DELETE_ACTION:
860 deleteAction(pMsg);
861 break;
862 case CMD_LOAD_ACTIONS:
863 sendAllActions(pMsg->getId());
864 break;
865 case CMD_DELETE_OBJECT:
866 deleteObject(pMsg);
867 break;
868 case CMD_POLL_NODE:
869 forcedNodePoll(pMsg);
870 break;
871 case CMD_TRAP:
872 onTrap(pMsg);
873 break;
874 case CMD_WAKEUP_NODE:
875 onWakeUpNode(pMsg);
876 break;
877 case CMD_CREATE_TRAP:
878 editTrap(TRAP_CREATE, pMsg);
879 break;
880 case CMD_MODIFY_TRAP:
881 editTrap(TRAP_UPDATE, pMsg);
882 break;
883 case CMD_DELETE_TRAP:
884 editTrap(TRAP_DELETE, pMsg);
885 break;
886 case CMD_LOAD_TRAP_CFG:
887 sendAllTraps(pMsg->getId());
888 break;
889 case CMD_GET_TRAP_CFG_RO:
890 sendAllTraps2(pMsg->getId());
891 break;
892 case CMD_QUERY_PARAMETER:
893 CALL_IN_NEW_THREAD(queryParameter, pMsg);
894 break;
895 case CMD_QUERY_TABLE:
896 CALL_IN_NEW_THREAD(queryAgentTable, pMsg);
897 break;
898 case CMD_LOCK_PACKAGE_DB:
899 LockPackageDB(pMsg->getId(), TRUE);
900 break;
901 case CMD_UNLOCK_PACKAGE_DB:
902 LockPackageDB(pMsg->getId(), FALSE);
903 break;
904 case CMD_GET_PACKAGE_LIST:
905 SendAllPackages(pMsg->getId());
906 break;
907 case CMD_INSTALL_PACKAGE:
908 InstallPackage(pMsg);
909 break;
910 case CMD_REMOVE_PACKAGE:
911 RemovePackage(pMsg);
912 break;
913 case CMD_GET_PARAMETER_LIST:
914 getParametersList(pMsg);
915 break;
916 case CMD_DEPLOY_PACKAGE:
917 DeployPackage(pMsg);
918 break;
919 case CMD_GET_LAST_VALUES:
920 getLastValues(pMsg);
921 break;
922 case CMD_GET_DCI_VALUES:
923 getLastValuesByDciId(pMsg);
924 break;
925 case CMD_GET_TABLE_LAST_VALUES:
926 getTableLastValues(pMsg);
927 break;
928 case CMD_GET_THRESHOLD_SUMMARY:
929 getThresholdSummary(pMsg);
930 break;
931 case CMD_GET_USER_VARIABLE:
932 getUserVariable(pMsg);
933 break;
934 case CMD_SET_USER_VARIABLE:
935 setUserVariable(pMsg);
936 break;
937 case CMD_DELETE_USER_VARIABLE:
938 deleteUserVariable(pMsg);
939 break;
940 case CMD_ENUM_USER_VARIABLES:
941 enumUserVariables(pMsg);
942 break;
943 case CMD_COPY_USER_VARIABLE:
944 copyUserVariable(pMsg);
945 break;
946 case CMD_CHANGE_ZONE:
947 changeObjectZone(pMsg);
948 break;
949 case CMD_REQUEST_ENCRYPTION:
950 setupEncryption(pMsg);
951 break;
952 case CMD_GET_AGENT_CONFIG:
953 getAgentConfig(pMsg);
954 break;
955 case CMD_UPDATE_AGENT_CONFIG:
956 updateAgentConfig(pMsg);
957 break;
958 case CMD_EXECUTE_ACTION:
959 CALL_IN_NEW_THREAD(executeAction, pMsg);
960 break;
961 case CMD_GET_OBJECT_TOOLS:
962 getObjectTools(pMsg->getId());
963 break;
964 case CMD_EXEC_TABLE_TOOL:
965 execTableTool(pMsg);
966 break;
967 case CMD_GET_OBJECT_TOOL_DETAILS:
968 getObjectToolDetails(pMsg);
969 break;
970 case CMD_UPDATE_OBJECT_TOOL:
971 updateObjectTool(pMsg);
972 break;
973 case CMD_DELETE_OBJECT_TOOL:
974 deleteObjectTool(pMsg);
975 break;
976 case CMD_CHANGE_OBJECT_TOOL_STATUS:
977 changeObjectToolStatus(pMsg);
978 break;
979 case CMD_GENERATE_OBJECT_TOOL_ID:
980 generateObjectToolId(pMsg->getId());
981 break;
982 case CMD_CHANGE_SUBSCRIPTION:
983 changeSubscription(pMsg);
984 break;
985 case CMD_GET_SERVER_STATS:
986 sendServerStats(pMsg->getId());
987 break;
988 case CMD_GET_SCRIPT_LIST:
989 sendScriptList(pMsg->getId());
990 break;
991 case CMD_GET_SCRIPT:
992 sendScript(pMsg);
993 break;
994 case CMD_UPDATE_SCRIPT:
995 updateScript(pMsg);
996 break;
997 case CMD_RENAME_SCRIPT:
998 renameScript(pMsg);
999 break;
1000 case CMD_DELETE_SCRIPT:
1001 deleteScript(pMsg);
1002 break;
1003 case CMD_GET_SESSION_LIST:
1004 SendSessionList(pMsg->getId());
1005 break;
1006 case CMD_KILL_SESSION:
1007 KillSession(pMsg);
1008 break;
1009 case CMD_START_SNMP_WALK:
1010 StartSnmpWalk(pMsg);
1011 break;
1012 case CMD_RESOLVE_DCI_NAMES:
1013 resolveDCINames(pMsg);
1014 break;
1015 case CMD_GET_DCI_INFO:
1016 SendDCIInfo(pMsg);
1017 break;
1018 case CMD_GET_DCI_THRESHOLDS:
1019 sendDCIThresholds(pMsg);
1020 break;
1021 case CMD_GET_DCI_EVENTS_LIST:
1022 getDCIEventList(pMsg);
1023 break;
1024 case CMD_GET_DCI_SCRIPT_LIST:
1025 getDCIScriptList(pMsg);
1026 break;
1027 case CMD_GET_PERFTAB_DCI_LIST:
1028 sendPerfTabDCIList(pMsg);
1029 break;
1030 case CMD_PUSH_DCI_DATA:
1031 pushDCIData(pMsg);
1032 break;
1033 case CMD_GET_AGENT_CFG_LIST:
1034 sendAgentCfgList(pMsg->getId());
1035 break;
1036 case CMD_OPEN_AGENT_CONFIG:
1037 OpenAgentConfig(pMsg);
1038 break;
1039 case CMD_SAVE_AGENT_CONFIG:
1040 SaveAgentConfig(pMsg);
1041 break;
1042 case CMD_DELETE_AGENT_CONFIG:
1043 DeleteAgentConfig(pMsg);
1044 break;
1045 case CMD_SWAP_AGENT_CONFIGS:
1046 SwapAgentConfigs(pMsg);
1047 break;
1048 case CMD_GET_OBJECT_COMMENTS:
1049 SendObjectComments(pMsg);
1050 break;
1051 case CMD_UPDATE_OBJECT_COMMENTS:
1052 updateObjectComments(pMsg);
1053 break;
1054 case CMD_GET_ADDR_LIST:
1055 getAddrList(pMsg);
1056 break;
1057 case CMD_SET_ADDR_LIST:
1058 setAddrList(pMsg);
1059 break;
1060 case CMD_RESET_COMPONENT:
1061 resetComponent(pMsg);
1062 break;
1063 case CMD_EXPORT_CONFIGURATION:
1064 exportConfiguration(pMsg);
1065 break;
1066 case CMD_IMPORT_CONFIGURATION:
1067 CALL_IN_NEW_THREAD(importConfiguration, pMsg);
1068 break;
1069 case CMD_GET_GRAPH_LIST:
1070 sendGraphList(pMsg);
1071 break;
1072 case CMD_SAVE_GRAPH:
1073 saveGraph(pMsg);
1074 break;
1075 case CMD_DELETE_GRAPH:
1076 deleteGraph(pMsg);
1077 break;
1078 case CMD_ADD_CA_CERTIFICATE:
1079 addCACertificate(pMsg);
1080 break;
1081 case CMD_DELETE_CERTIFICATE:
1082 deleteCertificate(pMsg);
1083 break;
1084 case CMD_UPDATE_CERT_COMMENTS:
1085 updateCertificateComments(pMsg);
1086 break;
1087 case CMD_GET_CERT_LIST:
1088 getCertificateList(pMsg->getId());
1089 break;
1090 case CMD_QUERY_L2_TOPOLOGY:
1091 CALL_IN_NEW_THREAD(queryL2Topology, pMsg);
1092 break;
1093 case CMD_SEND_SMS:
1094 sendSMS(pMsg);
1095 break;
1096 case CMD_GET_COMMUNITY_LIST:
1097 SendCommunityList(pMsg->getId());
1098 break;
1099 case CMD_UPDATE_COMMUNITY_LIST:
1100 UpdateCommunityList(pMsg);
1101 break;
1102 case CMD_GET_USM_CREDENTIALS:
1103 sendUsmCredentials(pMsg->getId());
1104 break;
1105 case CMD_UPDATE_USM_CREDENTIALS:
1106 updateUsmCredentials(pMsg);
1107 break;
1108 case CMD_GET_PERSISTENT_STORAGE:
1109 getPersistantStorage(pMsg->getId());
1110 break;
1111 case CMD_SET_PSTORAGE_VALUE:
1112 setPstorageValue(pMsg);
1113 break;
1114 case CMD_DELETE_PSTORAGE_VALUE:
1115 deletePstorageValue(pMsg);
1116 break;
1117 case CMD_REGISTER_AGENT:
1118 registerAgent(pMsg);
1119 break;
1120 case CMD_GET_SERVER_FILE:
1121 CALL_IN_NEW_THREAD(getServerFile, pMsg);
1122 break;
1123 case CMD_GET_AGENT_FILE:
1124 CALL_IN_NEW_THREAD(getAgentFile, pMsg);
1125 break;
1126 case CMD_CANCEL_FILE_MONITORING:
1127 CALL_IN_NEW_THREAD(cancelFileMonitoring, pMsg);
1128 break;
1129 case CMD_TEST_DCI_TRANSFORMATION:
1130 testDCITransformation(pMsg);
1131 break;
1132 case CMD_EXECUTE_SCRIPT:
1133 CALL_IN_NEW_THREAD(executeScript, pMsg);
1134 break;
1135 case CMD_EXECUTE_LIBRARY_SCRIPT:
1136 CALL_IN_NEW_THREAD(executeLibraryScript, pMsg);
1137 break;
1138 case CMD_GET_JOB_LIST:
1139 sendJobList(pMsg->getId());
1140 break;
1141 case CMD_CANCEL_JOB:
1142 cancelJob(pMsg);
1143 break;
1144 case CMD_HOLD_JOB:
1145 holdJob(pMsg);
1146 break;
1147 case CMD_UNHOLD_JOB:
1148 unholdJob(pMsg);
1149 break;
1150 case CMD_DEPLOY_AGENT_POLICY:
1151 deployAgentPolicy(pMsg, false);
1152 break;
1153 case CMD_UNINSTALL_AGENT_POLICY:
1154 deployAgentPolicy(pMsg, true);
1155 break;
1156 case CMD_GET_CURRENT_USER_ATTR:
1157 getUserCustomAttribute(pMsg);
1158 break;
1159 case CMD_SET_CURRENT_USER_ATTR:
1160 setUserCustomAttribute(pMsg);
1161 break;
1162 case CMD_OPEN_SERVER_LOG:
1163 openServerLog(pMsg);
1164 break;
1165 case CMD_CLOSE_SERVER_LOG:
1166 closeServerLog(pMsg);
1167 break;
1168 case CMD_QUERY_LOG:
1169 CALL_IN_NEW_THREAD(queryServerLog, pMsg);
1170 break;
1171 case CMD_GET_LOG_DATA:
1172 CALL_IN_NEW_THREAD(getServerLogQueryData, pMsg);
1173 break;
1174 case CMD_FIND_NODE_CONNECTION:
1175 CALL_IN_NEW_THREAD(findNodeConnection, pMsg);
1176 break;
1177 case CMD_FIND_MAC_LOCATION:
1178 CALL_IN_NEW_THREAD(findMacAddress, pMsg);
1179 break;
1180 case CMD_FIND_IP_LOCATION:
1181 CALL_IN_NEW_THREAD(findIpAddress, pMsg);
1182 break;
1183 case CMD_FIND_HOSTNAME_LOCATION:
1184 CALL_IN_NEW_THREAD(findHostname, pMsg);
1185 break;
1186 case CMD_GET_IMAGE:
1187 sendLibraryImage(pMsg);
1188 break;
1189 case CMD_CREATE_IMAGE:
1190 updateLibraryImage(pMsg);
1191 break;
1192 case CMD_DELETE_IMAGE:
1193 deleteLibraryImage(pMsg);
1194 break;
1195 case CMD_MODIFY_IMAGE:
1196 updateLibraryImage(pMsg);
1197 break;
1198 case CMD_LIST_IMAGES:
1199 listLibraryImages(pMsg);
1200 break;
1201 case CMD_EXECUTE_SERVER_COMMAND:
1202 executeServerCommand(pMsg);
1203 break;
1204 case CMD_STOP_SERVER_COMMAND:
1205 stopServerCommand(pMsg);
1206 break;
1207 case CMD_LIST_SERVER_FILES:
1208 listServerFileStore(pMsg);
1209 break;
1210 case CMD_UPLOAD_FILE_TO_AGENT:
1211 uploadFileToAgent(pMsg);
1212 break;
1213 case CMD_UPLOAD_FILE:
1214 receiveFile(pMsg);
1215 break;
1216 case CMD_DELETE_FILE:
1217 deleteFile(pMsg);
1218 break;
1219 case CMD_OPEN_CONSOLE:
1220 openConsole(pMsg->getId());
1221 break;
1222 case CMD_CLOSE_CONSOLE:
1223 closeConsole(pMsg->getId());
1224 break;
1225 case CMD_ADM_REQUEST:
1226 CALL_IN_NEW_THREAD(processConsoleCommand, pMsg);
1227 break;
1228 case CMD_GET_VLANS:
1229 getVlans(pMsg);
1230 break;
1231 case CMD_GET_NETWORK_PATH:
1232 CALL_IN_NEW_THREAD(getNetworkPath, pMsg);
1233 break;
1234 case CMD_GET_NODE_COMPONENTS:
1235 getNodeComponents(pMsg);
1236 break;
1237 case CMD_GET_NODE_SOFTWARE:
1238 getNodeSoftware(pMsg);
1239 break;
1240 case CMD_GET_WINPERF_OBJECTS:
1241 getWinPerfObjects(pMsg);
1242 break;
1243 case CMD_LIST_MAPPING_TABLES:
1244 listMappingTables(pMsg);
1245 break;
1246 case CMD_GET_MAPPING_TABLE:
1247 getMappingTable(pMsg);
1248 break;
1249 case CMD_UPDATE_MAPPING_TABLE:
1250 updateMappingTable(pMsg);
1251 break;
1252 case CMD_DELETE_MAPPING_TABLE:
1253 deleteMappingTable(pMsg);
1254 break;
1255 case CMD_GET_WIRELESS_STATIONS:
1256 getWirelessStations(pMsg);
1257 break;
1258 case CMD_GET_SUMMARY_TABLES:
1259 getSummaryTables(pMsg->getId());
1260 break;
1261 case CMD_GET_SUMMARY_TABLE_DETAILS:
1262 getSummaryTableDetails(pMsg);
1263 break;
1264 case CMD_MODIFY_SUMMARY_TABLE:
1265 modifySummaryTable(pMsg);
1266 break;
1267 case CMD_DELETE_SUMMARY_TABLE:
1268 deleteSummaryTable(pMsg);
1269 break;
1270 case CMD_QUERY_SUMMARY_TABLE:
1271 querySummaryTable(pMsg);
1272 break;
1273 case CMD_QUERY_ADHOC_SUMMARY_TABLE:
1274 queryAdHocSummaryTable(pMsg);
1275 break;
1276 case CMD_GET_SUBNET_ADDRESS_MAP:
1277 getSubnetAddressMap(pMsg);
1278 break;
1279 case CMD_GET_EFFECTIVE_RIGHTS:
1280 getEffectiveRights(pMsg);
1281 break;
1282 case CMD_GET_FOLDER_SIZE:
1283 case CMD_GET_FOLDER_CONTENT:
1284 case CMD_FILEMGR_DELETE_FILE:
1285 case CMD_FILEMGR_RENAME_FILE:
1286 case CMD_FILEMGR_MOVE_FILE:
1287 case CMD_FILEMGR_CREATE_FOLDER:
1288 CALL_IN_NEW_THREAD(fileManagerControl, pMsg);
1289 break;
1290 case CMD_FILEMGR_UPLOAD:
1291 CALL_IN_NEW_THREAD(uploadUserFileToAgent, pMsg);
1292 break;
1293 case CMD_GET_SWITCH_FDB:
1294 CALL_IN_NEW_THREAD(getSwitchForwardingDatabase, pMsg);
1295 break;
1296 case CMD_GET_ROUTING_TABLE:
1297 CALL_IN_NEW_THREAD(getRoutingTable, pMsg);
1298 break;
1299 case CMD_GET_LOC_HISTORY:
1300 CALL_IN_NEW_THREAD(getLocationHistory, pMsg);
1301 break;
1302 case CMD_TAKE_SCREENSHOT:
1303 getScreenshot(pMsg);
1304 break;
1305 case CMD_COMPILE_SCRIPT:
1306 compileScript(pMsg);
1307 break;
1308 case CMD_CLEAN_AGENT_DCI_CONF:
1309 cleanAgentDciConfiguration(pMsg);
1310 break;
1311 case CMD_RESYNC_AGENT_DCI_CONF:
1312 resyncAgentDciConfiguration(pMsg);
1313 break;
1314 case CMD_LIST_SCHEDULE_CALLBACKS:
1315 getSchedulerTaskHandlers(pMsg);
1316 break;
1317 case CMD_LIST_SCHEDULES:
1318 getScheduledTasks(pMsg);
1319 break;
1320 case CMD_ADD_SCHEDULE:
1321 addScheduledTask(pMsg);
1322 break;
1323 case CMD_UPDATE_SCHEDULE:
1324 updateScheduledTask(pMsg);
1325 break;
1326 case CMD_REMOVE_SCHEDULE:
1327 removeScheduledTask(pMsg);
1328 break;
1329 case CMD_GET_REPOSITORIES:
1330 CALL_IN_NEW_THREAD(getRepositories, pMsg);
1331 break;
1332 case CMD_ADD_REPOSITORY:
1333 CALL_IN_NEW_THREAD(addRepository, pMsg);
1334 break;
1335 case CMD_MODIFY_REPOSITORY:
1336 CALL_IN_NEW_THREAD(modifyRepository, pMsg);
1337 break;
1338 case CMD_DELETE_REPOSITORY:
1339 CALL_IN_NEW_THREAD(deleteRepository, pMsg);
1340 break;
1341 case CMD_GET_AGENT_TUNNELS:
1342 getAgentTunnels(pMsg);
1343 break;
1344 case CMD_BIND_AGENT_TUNNEL:
1345 bindAgentTunnel(pMsg);
1346 break;
1347 case CMD_UNBIND_AGENT_TUNNEL:
1348 unbindAgentTunnel(pMsg);
1349 break;
1350 case CMD_GET_PREDICTION_ENGINES:
1351 getPredictionEngines(pMsg);
1352 break;
1353 case CMD_GET_PREDICTED_DATA:
1354 CALL_IN_NEW_THREAD(getPredictedData, pMsg);
1355 break;
1356 case CMD_EXPAND_MACROS:
1357 expandMacros(pMsg);
1358 break;
1359 #ifdef WITH_ZMQ
1360 case CMD_ZMQ_SUBSCRIBE_EVENT:
1361 zmqManageSubscription(pMsg, zmq::EVENT, true);
1362 break;
1363 case CMD_ZMQ_UNSUBSCRIBE_EVENT:
1364 zmqManageSubscription(pMsg, zmq::EVENT, false);
1365 break;
1366 case CMD_ZMQ_SUBSCRIBE_DATA:
1367 zmqManageSubscription(pMsg, zmq::DATA, true);
1368 break;
1369 case CMD_ZMQ_UNSUBSCRIBE_DATA:
1370 zmqManageSubscription(pMsg, zmq::DATA, false);
1371 break;
1372 case CMD_ZMQ_GET_EVT_SUBSCRIPTIONS:
1373 zmqListSubscriptions(pMsg, zmq::EVENT);
1374 break;
1375 case CMD_ZMQ_GET_DATA_SUBSCRIPTIONS:
1376 zmqListSubscriptions(pMsg, zmq::DATA);
1377 break;
1378 #endif
1379 default:
1380 if ((m_wCurrentCmd >> 8) == 0x11)
1381 {
1382 // Reporting Server range (0x1100 - 0x11FF)
1383 CALL_IN_NEW_THREAD(forwardToReportingServer, pMsg);
1384 break;
1385 }
1386
1387 // Pass message to loaded modules
1388 for(i = 0; i < g_dwNumModules; i++)
1389 {
1390 if (g_pModuleList[i].pfClientCommandHandler != NULL)
1391 {
1392 status = g_pModuleList[i].pfClientCommandHandler(m_wCurrentCmd, pMsg, this);
1393 if (status != NXMOD_COMMAND_IGNORED)
1394 {
1395 if (status == NXMOD_COMMAND_ACCEPTED_ASYNC)
1396 {
1397 pMsg = NULL; // Prevent deletion
1398 }
1399 break; // Message was processed by the module
1400 }
1401 }
1402 }
1403 if (i == g_dwNumModules)
1404 {
1405 NXCPMessage response;
1406
1407 response.setId(pMsg->getId());
1408 response.setCode(CMD_REQUEST_COMPLETED);
1409 response.setField(VID_RCC, RCC_NOT_IMPLEMENTED);
1410 sendMessage(&response);
1411 }
1412 break;
1413 }
1414 delete pMsg;
1415 m_state = (m_dwFlags & CSF_AUTHENTICATED) ? SESSION_STATE_IDLE : SESSION_STATE_INIT;
1416 }
1417 }
1418
1419 /**
1420 * Respond to client's keepalive message
1421 */
1422 void ClientSession::respondToKeepalive(UINT32 dwRqId)
1423 {
1424 NXCPMessage msg;
1425
1426 msg.setCode(CMD_REQUEST_COMPLETED);
1427 msg.setId(dwRqId);
1428 msg.setField(VID_RCC, RCC_SUCCESS);
1429 sendMessage(&msg);
1430 }
1431
1432 /**
1433 * Send message to client
1434 */
1435 bool ClientSession::sendMessage(NXCPMessage *msg)
1436 {
1437 if (isTerminated())
1438 return false;
1439
1440 NXCP_MESSAGE *rawMsg = msg->serialize((m_dwFlags & CSF_COMPRESSION_ENABLED) != 0);
1441
1442 if ((nxlog_get_debug_level() >= 6) && (msg->getCode() != CMD_ADM_MESSAGE))
1443 {
1444 TCHAR buffer[128];
1445 debugPrintf(6, _T("Sending%s message %s (%d bytes)"),
1446 (ntohs(rawMsg->flags) & MF_COMPRESSED) ? _T(" compressed") : _T(""), NXCPMessageCodeName(msg->getCode(), buffer), ntohl(rawMsg->size));
1447 if (nxlog_get_debug_level() >= 8)
1448 {
1449 String msgDump = NXCPMessage::dump(rawMsg, NXCP_VERSION);
1450 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR *)msgDump);
1451 }
1452 }
1453
1454 bool result;
1455 if (m_pCtx != NULL)
1456 {
1457 NXCP_ENCRYPTED_MESSAGE *enMsg = m_pCtx->encryptMessage(rawMsg);
1458 if (enMsg != NULL)
1459 {
1460 result = (SendEx(m_hSocket, (char *)enMsg, ntohl(enMsg->size), 0, m_mutexSocketWrite) == (int)ntohl(enMsg->size));
1461 free(enMsg);
1462 }
1463 else
1464 {
1465 result = false;
1466 }
1467 }
1468 else
1469 {
1470 result = (SendEx(m_hSocket, (const char *)rawMsg, ntohl(rawMsg->size), 0, m_mutexSocketWrite) == (int)ntohl(rawMsg->size));
1471 }
1472 free(rawMsg);
1473
1474 if (!result)
1475 {
1476 closesocket(m_hSocket);
1477 m_hSocket = -1;
1478 }
1479 return result;
1480 }
1481
1482 /**
1483 * Send raw message to client
1484 */
1485 void ClientSession::sendRawMessage(NXCP_MESSAGE *msg)
1486 {
1487 if (isTerminated())
1488 return;
1489
1490 UINT16 code = htons(msg->code);
1491 if ((code != CMD_ADM_MESSAGE) && (nxlog_get_debug_level() >= 6))
1492 {
1493 TCHAR buffer[128];
1494 debugPrintf(6, _T("Sending%s message %s (%d bytes)"),
1495 (ntohs(msg->flags) & MF_COMPRESSED) ? _T(" compressed") : _T(""), NXCPMessageCodeName(ntohs(msg->code), buffer), ntohl(msg->size));
1496 if (nxlog_get_debug_level() >= 8)
1497 {
1498 String msgDump = NXCPMessage::dump(msg, NXCP_VERSION);
1499 debugPrintf(8, _T("Message dump:\n%s"), (const TCHAR *)msgDump);
1500 }
1501 }
1502
1503 bool result;
1504 if (m_pCtx != NULL)
1505 {
1506 NXCP_ENCRYPTED_MESSAGE *enMsg = m_pCtx->encryptMessage(msg);
1507 if (enMsg != NULL)
1508 {
1509 result = (SendEx(m_hSocket, (char *)enMsg, ntohl(enMsg->size), 0, m_mutexSocketWrite) == (int)ntohl(enMsg->size));
1510 free(enMsg);
1511 }
1512 else
1513 {
1514 result = false;
1515 }
1516 }
1517 else
1518 {
1519 result = (SendEx(m_hSocket, (const char *)msg, ntohl(msg->size), 0, m_mutexSocketWrite) == (int)ntohl(msg->size));
1520 }
1521
1522 if (!result)
1523 {
1524 closesocket(m_hSocket);
1525 m_hSocket = -1;
1526 }
1527 }
1528
1529 /**
1530 * Send file to client
1531 */
1532 BOOL ClientSession::sendFile(const TCHAR *file, UINT32 dwRqId, long ofset)
1533 {
1534 return !isTerminated() ? SendFileOverNXCP(m_hSocket, dwRqId, file, m_pCtx,
1535 ofset, NULL, NULL, m_mutexSocketWrite, isCompressionEnabled() ? NXCP_STREAM_COMPRESSION_DEFLATE : NXCP_STREAM_COMPRESSION_NONE) : FALSE;
1536 }
1537
1538 /**
1539 * Send server information to client
1540 */
1541 void ClientSession::sendServerInfo(UINT32 dwRqId)
1542 {
1543 static UINT32 protocolVersions[] = {
1544 CLIENT_PROTOCOL_VERSION_BASE,
1545 CLIENT_PROTOCOL_VERSION_ALARMS,
1546 CLIENT_PROTOCOL_VERSION_PUSH,
1547 CLIENT_PROTOCOL_VERSION_TRAP,
1548 CLIENT_PROTOCOL_VERSION_MOBILE,
1549 CLIENT_PROTOCOL_VERSION_FULL
1550 };
1551 NXCPMessage msg;
1552 TCHAR szBuffer[MAX_CONFIG_VALUE];
1553 String strURL;
1554
1555 // Prepare response message
1556 msg.setCode(CMD_REQUEST_COMPLETED);
1557 msg.setId(dwRqId);
1558
1559 // Generate challenge for certificate authentication
1560 #ifdef _WITH_ENCRYPTION
1561 RAND_bytes(m_challenge, CLIENT_CHALLENGE_SIZE);
1562 #else
1563 memset(m_challenge, 0, CLIENT_CHALLENGE_SIZE);
1564 #endif
1565
1566 // Fill message with server info
1567 msg.setField(VID_RCC, RCC_SUCCESS);
1568 msg.setField(VID_SERVER_VERSION, NETXMS_VERSION_STRING);
1569 msg.setField(VID_SERVER_ID, g_serverId);
1570 msg.setField(VID_SUPPORTED_ENCRYPTION, (UINT32)0);
1571 msg.setField(VID_PROTOCOL_VERSION, (UINT32)CLIENT_PROTOCOL_VERSION_BASE);
1572 msg.setFieldFromInt32Array(VID_PROTOCOL_VERSION_EX, sizeof(protocolVersions) / sizeof(UINT32), protocolVersions);
1573 msg.setField(VID_CHALLENGE, m_challenge, CLIENT_CHALLENGE_SIZE);
1574 msg.setField(VID_TIMESTAMP, (UINT32)time(NULL));
1575
1576 #if defined(_WIN32)
1577 TIME_ZONE_INFORMATION tz;
1578 WCHAR wst[4], wdt[8], *curr;
1579 int i;
1580
1581 DWORD tzType = GetTimeZoneInformation(&tz);
1582
1583 // Create 3 letter abbreviation for standard name
1584 for(i = 0, curr = tz.StandardName; (*curr != 0) && (i < 3); curr++)
1585 if (iswupper(*curr))
1586 wst[i++] = *curr;
1587 while(i < 3)
1588 wst[i++] = L'X';
1589 wst[i] = 0;
1590
1591 // Create abbreviation for DST name
1592 for(i = 0, curr = tz.DaylightName; (*curr != 0) && (i < 7); curr++)
1593 if (iswupper(*curr))
1594 wdt[i++] = *curr;
1595 while(i < 3)
1596 wdt[i++] = L'X';
1597 wdt[i] = 0;
1598
1599 LONG effectiveBias;
1600 switch(tzType)
1601 {
1602 case TIME_ZONE_ID_STANDARD:
1603 effectiveBias = tz.Bias + tz.StandardBias;
1604 break;
1605 case TIME_ZONE_ID_DAYLIGHT:
1606 effectiveBias = tz.Bias + tz.DaylightBias;
1607 break;
1608 case TIME_ZONE_ID_UNKNOWN:
1609 effectiveBias = tz.Bias;
1610 break;
1611 default: // error
1612 effectiveBias = 0;
1613 debugPrintf(4, _T("GetTimeZoneInformation() call failed"));
1614 break;
1615 }
1616
1617 #ifdef UNICODE
1618 swprintf(szBuffer, 1024, L"%s%c%02d%s", wst, (effectiveBias > 0) ? '-' : '+',
1619 abs(effectiveBias) / 60, (tz.DaylightBias != 0) ? wdt : L"");
1620 #else
1621 sprintf(szBuffer, "%S%c%02d%S", wst, (effectiveBias > 0) ? '-' : '+',
1622 abs(effectiveBias) / 60, (tz.DaylightBias != 0) ? wdt : L"");
1623 #endif
1624
1625 #elif HAVE_TM_GMTOFF /* not Windows but have tm_gmtoff */
1626
1627 time_t t = time(NULL);
1628 int gmtOffset;
1629 #if HAVE_LOCALTIME_R
1630 struct tm tmbuff;
1631 struct tm *loc = localtime_r(&t, &tmbuff);
1632 #else
1633 struct tm *loc = localtime(&t);
1634 #endif
1635 gmtOffset = loc->tm_gmtoff / 3600;
1636 #ifdef UNICODE
1637 swprintf(szBuffer, 1024, L"%hs%hc%02d%hs", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1638 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
1639 #else
1640 sprintf(szBuffer, "%s%c%02d%s", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1641 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
1642 #endif
1643
1644 #else /* not Windows and no tm_gmtoff */
1645
1646 time_t t = time(NULL);
1647 #if HAVE_GMTIME_R
1648 struct tm tmbuff;
1649 struct tm *gmt = gmtime_r(&t, &tmbuff);
1650 #else
1651 struct tm *gmt = gmtime(&t);
1652 #endif
1653 gmt->tm_isdst = -1;
1654 int gmtOffset = (int)((t - mktime(gmt)) / 3600);
1655 #ifdef UNICODE
1656 swprintf(szBuffer, 1024, L"%hs%hc%02d%hs", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1657 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
1658 #else
1659 sprintf(szBuffer, "%s%c%02d%s", tzname[0], (gmtOffset >= 0) ? '+' : '-',
1660 abs(gmtOffset), (tzname[1] != NULL) ? tzname[1] : "");
1661 #endif
1662
1663 #endif
1664
1665 msg.setField(VID_TIMEZONE, szBuffer);
1666 debugPrintf(2, _T("Server time zone: %s"), szBuffer);
1667
1668 ConfigReadStr(_T("TileServerURL"), szBuffer, MAX_CONFIG_VALUE, _T("http://tile.openstreetmap.org/"));
1669 msg.setField(VID_TILE_SERVER_URL, szBuffer);
1670
1671 ConfigReadStr(_T("DefaultConsoleDateFormat"), szBuffer, MAX_CONFIG_VALUE, _T("dd.MM.yyyy"));
1672 msg.setField(VID_DATE_FORMAT, szBuffer);
1673
1674 ConfigReadStr(_T("DefaultConsoleTimeFormat"), szBuffer, MAX_CONFIG_VALUE, _T("HH:mm:ss"));
1675 msg.setField(VID_TIME_FORMAT, szBuffer);
1676
1677 ConfigReadStr(_T("DefaultConsoleShortTimeFormat"), szBuffer, MAX_CONFIG_VALUE, _T("HH:mm"));
1678 msg.setField(VID_SHORT_TIME_FORMAT, szBuffer);
1679
1680 FillComponentsMessage(&msg);
1681
1682 // Send response
1683 sendMessage(&msg);
1684 }
1685
1686 /**
1687 * Authenticate client
1688 */
1689 void ClientSession::login(NXCPMessage *pRequest)
1690 {
1691 NXCPMessage msg;
1692 TCHAR szLogin[MAX_USER_NAME], szPassword[1024];
1693 int nAuthType;
1694 bool changePasswd = false, intruderLockout = false;
1695 UINT32 dwResult;
1696 #ifdef _WITH_ENCRYPTION
1697 X509 *pCert;
1698 #endif
1699
1700 // Prepare response message
1701 msg.setCode(CMD_LOGIN_RESP);
1702 msg.setId(pRequest->getId());
1703
1704 // Get client info string
1705 if (pRequest->isFieldExist(VID_CLIENT_INFO))
1706 {
1707 TCHAR szClientInfo[32], szOSInfo[32], szLibVersion[16];
1708
1709 pRequest->getFieldAsString(VID_CLIENT_INFO, szClientInfo, 32);
1710 pRequest->getFieldAsString(VID_OS_INFO, szOSInfo, 32);
1711 pRequest->getFieldAsString(VID_LIBNXCL_VERSION, szLibVersion, 16);
1712 _sntprintf(m_clientInfo, 96, _T("%s (%s; libnxcl %s)"), szClientInfo, szOSInfo, szLibVersion);
1713 }
1714
1715 m_clientType = pRequest->getFieldAsUInt16(VID_CLIENT_TYPE);
1716 if ((m_clientType < 0) || (m_clientType > CLIENT_TYPE_APPLICATION))
1717 m_clientType = CLIENT_TYPE_DESKTOP;
1718
1719 if (m_clientType == CLIENT_TYPE_WEB)
1720 {
1721 _tcscpy(m_webServerAddress, m_workstation);
1722 if (pRequest->isFieldExist(VID_CLIENT_ADDRESS))
1723 {
1724 pRequest->getFieldAsString(VID_CLIENT_ADDRESS, m_workstation, 256);
1725 debugPrintf(5, _T("Real web client address is %s"), m_workstation);
1726 }
1727 }
1728
1729 if (pRequest->isFieldExist(VID_LANGUAGE))
1730 {
1731 pRequest->getFieldAsString(VID_LANGUAGE, m_language, 8);
1732 }
1733
1734 if (!(m_dwFlags & CSF_AUTHENTICATED))
1735 {
1736 UINT32 graceLogins = 0;
1737 bool closeOtherSessions = false;
1738 pRequest->getFieldAsString(VID_LOGIN_NAME, szLogin, MAX_USER_NAME);
1739 nAuthType = (int)pRequest->getFieldAsUInt16(VID_AUTH_TYPE);
1740 debugPrintf(6, _T("authentication type %d"), nAuthType);
1741 switch(nAuthType)
1742 {
1743 case NETXMS_AUTH_TYPE_PASSWORD:
1744 #ifdef UNICODE
1745 pRequest->getFieldAsString(VID_PASSWORD, szPassword, 256);
1746 #else
1747 pRequest->getFieldAsUtf8String(VID_PASSWORD, szPassword, 1024);
1748 #endif
1749 dwResult = AuthenticateUser(szLogin, szPassword, 0, NULL, NULL, &m_dwUserId,
1750 &m_dwSystemAccess, &changePasswd, &intruderLockout,
1751 &closeOtherSessions, false, &graceLogins);
1752 break;
1753 case NETXMS_AUTH_TYPE_CERTIFICATE:
1754 #ifdef _WITH_ENCRYPTION
1755 pCert = CertificateFromLoginMessage(pRequest);
1756 if (pCert != NULL)
1757 {
1758 size_t sigLen;
1759 const BYTE *signature = pRequest->getBinaryFieldPtr(VID_SIGNATURE, &sigLen);
1760 if (signature != NULL)
1761 {
1762 dwResult = AuthenticateUser(szLogin, reinterpret_cast<const TCHAR*>(signature), sigLen,
1763 pCert, m_challenge, &m_dwUserId, &m_dwSystemAccess, &changePasswd, &intruderLockout,
1764 &closeOtherSessions, false, &graceLogins);
1765 }
1766 else
1767 {
1768 dwResult = RCC_INVALID_REQUEST;
1769 }
1770 X509_free(pCert);
1771 }
1772 else
1773 {
1774 dwResult = RCC_BAD_CERTIFICATE;
1775 }
1776 #else
1777 dwResult = RCC_NOT_IMPLEMENTED;
1778 #endif
1779 break;
1780 case NETXMS_AUTH_TYPE_SSO_TICKET:
1781 char ticket[1024];
1782 pRequest->getFieldAsMBString(VID_PASSWORD, ticket, 1024);
1783 if (CASAuthenticate(ticket, szLogin))
1784 {
1785 debugPrintf(5, _T("SSO ticket %hs is valid, login name %s"), ticket, szLogin);
1786 dwResult = AuthenticateUser(szLogin, NULL, 0, NULL, NULL, &m_dwUserId,
1787 &m_dwSystemAccess, &changePasswd, &intruderLockout,
1788 &closeOtherSessions, true, &graceLogins);
1789 }
1790 else
1791 {
1792 debugPrintf(5, _T("SSO ticket %hs is invalid"), ticket);
1793 dwResult = RCC_ACCESS_DENIED;
1794 }
1795 break;
1796 default:
1797 dwResult = RCC_UNSUPPORTED_AUTH_TYPE;
1798 break;
1799 }
1800
1801 // Additional validation by loaded modules
1802 if (dwResult == RCC_SUCCESS)
1803 {
1804 for(UINT32 i = 0; i < g_dwNumModules; i++)
1805 {
1806 if (g_pModuleList[i].pfAdditionalLoginCheck != NULL)
1807 {
1808 dwResult = g_pModuleList[i].pfAdditionalLoginCheck(m_dwUserId, pRequest);
1809 if (dwResult != RCC_SUCCESS)
1810 {
1811 debugPrintf(4, _T("Login blocked by module %s (rcc=%d)"), g_pModuleList[i].szName, dwResult);
1812 break;
1813 }
1814 }
1815 }
1816 }
1817
1818 if (dwResult == RCC_SUCCESS)
1819 {
1820 m_dwFlags |= CSF_AUTHENTICATED;
1821 nx_strncpy(m_loginName, szLogin, MAX_USER_NAME);
1822 _sntprintf(m_sessionName, MAX_SESSION_NAME, _T("%s@%s"), szLogin, m_workstation);
1823 m_loginTime = time(NULL);
1824 msg.setField(VID_RCC, RCC_SUCCESS);
1825 msg.setField(VID_USER_SYS_RIGHTS, m_dwSystemAccess);
1826 msg.setField(VID_USER_ID, m_dwUserId);
1827 msg.setField(VID_SESSION_ID, (UINT32)m_id);
1828 msg.setField(VID_CHANGE_PASSWD_FLAG, (WORD)changePasswd);
1829 msg.setField(VID_DBCONN_STATUS, (UINT16)((g_flags & AF_DB_CONNECTION_LOST) ? 0 : 1));
1830 msg.setField(VID_ZONING_ENABLED, (UINT16)((g_flags & AF_ENABLE_ZONING) ? 1 : 0));
1831 msg.setField(VID_POLLING_INTERVAL, (INT32)DCObject::m_defaultPollingInterval);
1832 msg.setField(VID_RETENTION_TIME, (INT32)DCObject::m_defaultRetentionTime);
1833 msg.setField(VID_ALARM_STATUS_FLOW_STATE, (UINT16)ConfigReadInt(_T("StrictAlarmStatusFlow"), 0));
1834 msg.setField(VID_TIMED_ALARM_ACK_ENABLED, (UINT16)ConfigReadInt(_T("EnableTimedAlarmAck"), 0));
1835 msg.setField(VID_VIEW_REFRESH_INTERVAL, (UINT16)ConfigReadInt(_T("MinViewRefreshInterval"), 200));
1836 msg.setField(VID_HELPDESK_LINK_ACTIVE, (UINT16)((g_flags & AF_HELPDESK_LINK_ACTIVE) ? 1 : 0));
1837 msg.setField(VID_ALARM_LIST_DISP_LIMIT, ConfigReadULong(_T("AlarmListDisplayLimit"), 4096));
1838 msg.setField(VID_SERVER_COMMAND_TIMEOUT, ConfigReadULong(_T("ServerCommandOutputTimeout"), 60));
1839 msg.setField(VID_GRACE_LOGINS, graceLogins);
1840
1841 if (pRequest->getFieldAsBoolean(VID_ENABLE_COMPRESSION))
1842 {
1843 debugPrintf(3, _T("Protocol level compression is supported by client"));
1844 m_dwFlags |= CSF_COMPRESSION_ENABLED;
1845 msg.setField(VID_ENABLE_COMPRESSION, true);
1846 }
1847 else
1848 {
1849 debugPrintf(3, _T("Protocol level compression is not supported by client"));
1850 }
1851
1852 TCHAR buffer[MAX_DB_STRING];
1853 ConfigReadStr(_T("ServerName"), buffer, MAX_DB_STRING, _T(""));
1854 msg.setField(VID_SERVER_NAME, buffer);
1855
1856 ConfigReadStr(_T("ServerColor"), buffer, MAX_DB_STRING, _T(""));
1857 msg.setField(VID_SERVER_COLOR, buffer);
1858
1859 ConfigReadStr(_T("MessageOfTheDay"), buffer, MAX_DB_STRING, _T(""));
1860 msg.setField(VID_MESSAGE_OF_THE_DAY, buffer);
1861
1862 debugPrintf(3, _T("User %s authenticated (language=%s clientInfo=\"%s\")"), m_sessionName, m_language, m_clientInfo);
1863 writeAuditLog(AUDIT_SECURITY, true, 0, _T("User \"%s\" logged in (language: %s; client info: %s)"), szLogin, m_language, m_clientInfo);
1864
1865 if (closeOtherSessions)
1866 {
1867 debugPrintf(5, _T("Closing other sessions for user %s"), m_loginName);
1868 CloseOtherSessions(m_dwUserId, m_id);
1869 }
1870 }
1871 else
1872 {
1873 msg.setField(VID_RCC, dwResult);
1874 writeAuditLog(AUDIT_SECURITY, false, 0,
1875 _T("User \"%s\" login failed with error code %d (client info: %s)"),
1876 szLogin, dwResult, m_clientInfo);
1877 if (intruderLockout)
1878 {
1879 writeAuditLog(AUDIT_SECURITY, false, 0,
1880 _T("User account \"%s\" temporary disabled due to excess count of failed authentication attempts"), szLogin);
1881 }
1882 m_dwUserId = INVALID_INDEX; // reset user ID to avoid incorrect count of logged in sessions for that user
1883 }
1884 }
1885 else
1886 {
1887 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
1888 }
1889
1890 // Send response
1891 sendMessage(&msg);
1892 }
1893
1894 /**
1895 * Send alarm categories to client
1896 */
1897 void ClientSession::getAlarmCategories(UINT32 requestId)
1898 {
1899 NXCPMessage msg;
1900
1901 // Prepare response message
1902 msg.setCode(CMD_REQUEST_COMPLETED);
1903 msg.setId(requestId);
1904
1905 // Check access rights
1906 if (checkSysAccessRights(SYSTEM_ACCESS_EPP))
1907 {
1908 GetAlarmCategories(&msg);
1909 msg.setField(VID_RCC, RCC_SUCCESS);
1910 }
1911 else
1912 {
1913 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
1914 }
1915 sendMessage(&msg);
1916 }
1917
1918 /**
1919 * Update alarm category
1920 */
1921 void ClientSession::modifyAlarmCategory(NXCPMessage *pRequest)
1922 {
1923 NXCPMessage msg;
1924 msg.setCode(CMD_REQUEST_COMPLETED);
1925 msg.setId(pRequest->getId());
1926
1927 // Check access rights
1928 if (checkSysAccessRights(SYSTEM_ACCESS_EPP))
1929 {
1930 UINT32 id = 0;
1931 msg.setField(VID_RCC, UpdateAlarmCategory(pRequest, &id));
1932 msg.setField(VID_CATEGORY_ID, id);
1933 }
1934 else
1935 {
1936 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
1937 }
1938
1939 // Send response
1940 sendMessage(&msg);
1941 }
1942
1943 /**
1944 * Delete alarm category
1945 */
1946 void ClientSession::deleteAlarmCategory(NXCPMessage *request)
1947 {
1948 NXCPMessage msg;
1949 msg.setCode(CMD_REQUEST_COMPLETED);
1950 msg.setId(request->getId());
1951
1952 // Check access rights
1953 if (checkSysAccessRights(SYSTEM_ACCESS_EPP))
1954 {
1955 UINT32 categoryId = request->getFieldAsInt32(VID_CATEGORY_ID);
1956 if (!g_pEventPolicy->isCategoryInUse(categoryId))
1957 {
1958 msg.setField(VID_RCC, DeleteAlarmCategory(categoryId));
1959 }
1960 else
1961 {
1962 msg.setField(VID_RCC, RCC_CATEGORY_IN_USE);
1963 }
1964 }
1965 else
1966 {
1967 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
1968 }
1969
1970 // Send response
1971 sendMessage(&msg);
1972 }
1973
1974 /**
1975 * Send event configuration to client
1976 */
1977 void ClientSession::sendEventDB(NXCPMessage *pRequest)
1978 {
1979 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
1980 if (checkSysAccessRights(SYSTEM_ACCESS_VIEW_EVENT_DB) || checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) || checkSysAccessRights(SYSTEM_ACCESS_EPP))
1981 {
1982 if (!(g_flags & AF_DB_CONNECTION_LOST))
1983 {
1984 msg.setField(VID_RCC, RCC_SUCCESS);
1985 GetEventConfiguration(&msg);
1986 }
1987 }
1988 else
1989 {
1990 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
1991 }
1992 sendMessage(&msg);
1993 }
1994
1995 /**
1996 * Update event template
1997 */
1998 void ClientSession::modifyEventTemplate(NXCPMessage *pRequest)
1999 {
2000 NXCPMessage msg;
2001
2002 // Prepare reply message
2003 msg.setCode(CMD_REQUEST_COMPLETED);
2004 msg.setId(pRequest->getId());
2005 // Check access rights
2006 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
2007 {
2008 json_t *oldValue, *newValue;
2009 UINT32 rcc = UpdateEventObject(pRequest, &msg, &oldValue, &newValue);
2010 if (rcc == RCC_SUCCESS)
2011 {
2012 TCHAR name[MAX_EVENT_NAME];
2013 pRequest->getFieldAsString(VID_NAME, name, MAX_EVENT_NAME);
2014 writeAuditLogWithValues(AUDIT_SYSCFG, true, 0, oldValue, newValue, _T("Event template %s [%d] modified"), name, pRequest->getFieldAsUInt32(VID_EVENT_CODE));
2015 json_decref(oldValue);
2016 json_decref(newValue);
2017 }
2018 msg.setField(VID_RCC, rcc);
2019 }
2020 else
2021 {
2022 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2023 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on modify event template [%d]"), pRequest->getFieldAsUInt32(VID_EVENT_CODE)); // TODO change message
2024 }
2025
2026 // Send response
2027 sendMessage(&msg);
2028 }
2029
2030 /**
2031 * Delete event template
2032 */
2033 void ClientSession::deleteEventTemplate(NXCPMessage *pRequest)
2034 {
2035 NXCPMessage msg;
2036 UINT32 dwEventCode;
2037
2038 // Prepare reply message
2039 msg.setCode(CMD_REQUEST_COMPLETED);
2040 msg.setId(pRequest->getId());
2041
2042 dwEventCode = pRequest->getFieldAsUInt32(VID_EVENT_CODE);
2043
2044 // Check access rights
2045 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB) && (dwEventCode >= FIRST_USER_EVENT_ID))
2046 {
2047 UINT32 rcc = DeleteEventObject(dwEventCode);
2048 if (rcc == RCC_SUCCESS)
2049 writeAuditLog(AUDIT_SYSCFG, true, 0, _T("Event template [%d] deleted"), dwEventCode);
2050
2051 msg.setField(VID_RCC, rcc);
2052 }
2053 else
2054 {
2055 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2056 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on delete event template [%d]"), dwEventCode);
2057 }
2058
2059 // Send response
2060 sendMessage(&msg);
2061 }
2062
2063 /**
2064 * Generate event code for new event template
2065 */
2066 void ClientSession::generateEventCode(UINT32 dwRqId)
2067 {
2068 NXCPMessage msg;
2069
2070 // Prepare reply message
2071 msg.setCode(CMD_REQUEST_COMPLETED);
2072 msg.setId(dwRqId);
2073
2074 // Check access rights
2075 if (checkSysAccessRights(SYSTEM_ACCESS_EDIT_EVENT_DB))
2076 {
2077 msg.setField(VID_EVENT_CODE, CreateUniqueId(IDG_EVENT));
2078 }
2079 else
2080 {
2081 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2082 }
2083
2084 // Send response
2085 sendMessage(&msg);
2086 }
2087
2088 /**
2089 * Data for session object filter
2090 */
2091 struct SessionObjectFilterData
2092 {
2093 ClientSession *session;
2094 time_t baseTimeStamp;
2095 };
2096
2097 /**
2098 * Object filter for ClientSession::sendAllObjects
2099 */
2100 static bool SessionObjectFilter(NetObj *object, void *data)
2101 {
2102 return !object->isHidden() && !object->isSystem() && !object->isDeleted() &&
2103 (object->getTimeStamp() >= ((SessionObjectFilterData *)data)->baseTimeStamp) &&
2104 object->checkAccessRights(((SessionObjectFilterData *)data)->session->getUserId(), OBJECT_ACCESS_READ);
2105 }
2106
2107 /**
2108 * Send all objects to client
2109 */
2110 void ClientSession::sendAllObjects(NXCPMessage *pRequest)
2111 {
2112 NXCPMessage msg;
2113
2114 // Send confirmation message
2115 msg.setCode(CMD_REQUEST_COMPLETED);
2116 msg.setId(pRequest->getId());
2117 msg.setField(VID_RCC, RCC_SUCCESS);
2118 sendMessage(&msg);
2119 msg.deleteAllFields();
2120
2121 // Change "sync comments" flag
2122 if (pRequest->getFieldAsUInt16(VID_SYNC_COMMENTS))
2123 m_dwFlags |= CSF_SYNC_OBJECT_COMMENTS;
2124 else
2125 m_dwFlags &= ~CSF_SYNC_OBJECT_COMMENTS;
2126
2127 // Prepare message
2128 msg.setCode(CMD_OBJECT);
2129
2130 // Send objects, one per message
2131 SessionObjectFilterData data;
2132 data.session = this;
2133 data.baseTimeStamp = pRequest->getFieldAsTime(VID_TIMESTAMP);
2134 ObjectArray<NetObj> *objects = g_idxObjectById.getObjects(true, SessionObjectFilter, &data);
2135 MutexLock(m_mutexSendObjects);
2136 for(int i = 0; i < objects->size(); i++)
2137 {
2138 NetObj *object = objects->get(i);
2139 object->fillMessage(&msg);
2140 if (m_dwFlags & CSF_SYNC_OBJECT_COMMENTS)
2141 object->commentsToMessage(&msg);
2142 if (!object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2143 {
2144 // mask passwords
2145 msg.setField(VID_SHARED_SECRET, _T("********"));
2146 msg.setField(VID_SNMP_AUTH_PASSWORD, _T("********"));
2147 msg.setField(VID_SNMP_PRIV_PASSWORD, _T("********"));
2148 }
2149 sendMessage(&msg);
2150 msg.deleteAllFields();
2151 object->decRefCount();
2152 }
2153 delete objects;
2154
2155 // Send end of list notification
2156 msg.setCode(CMD_OBJECT_LIST_END);
2157 sendMessage(&msg);
2158
2159 MutexUnlock(m_mutexSendObjects);
2160 }
2161
2162 /**
2163 * Send selected objects to client
2164 */
2165 void ClientSession::sendSelectedObjects(NXCPMessage *pRequest)
2166 {
2167 NXCPMessage msg;
2168
2169 // Send confirmation message
2170 msg.setCode(CMD_REQUEST_COMPLETED);
2171 msg.setId(pRequest->getId());
2172 msg.setField(VID_RCC, RCC_SUCCESS);
2173 sendMessage(&msg);
2174 msg.deleteAllFields();
2175
2176 // Change "sync comments" flag
2177 if (pRequest->getFieldAsBoolean(VID_SYNC_COMMENTS))
2178 m_dwFlags |= CSF_SYNC_OBJECT_COMMENTS;
2179 else
2180 m_dwFlags &= ~CSF_SYNC_OBJECT_COMMENTS;
2181
2182 UINT32 dwTimeStamp = pRequest->getFieldAsUInt32(VID_TIMESTAMP);
2183 UINT32 numObjects = pRequest->getFieldAsUInt32(VID_NUM_OBJECTS);
2184 UINT32 *objects = (UINT32 *)malloc(sizeof(UINT32) * numObjects);
2185 pRequest->getFieldAsInt32Array(VID_OBJECT_LIST, numObjects, objects);
2186 UINT32 options = pRequest->getFieldAsUInt16(VID_FLAGS);
2187
2188 MutexLock(m_mutexSendObjects);
2189
2190 // Prepare message
2191 msg.setCode((options & OBJECT_SYNC_SEND_UPDATES) ? CMD_OBJECT_UPDATE : CMD_OBJECT);
2192
2193 // Send objects, one per message
2194 for(UINT32 i = 0; i < numObjects; i++)
2195 {
2196 NetObj *object = FindObjectById(objects[i]);
2197 if ((object != NULL) &&
2198 object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ) &&
2199 (object->getTimeStamp() >= dwTimeStamp) &&
2200 !object->isHidden() && !object->isSystem())
2201 {
2202 object->fillMessage(&msg);
2203 if (m_dwFlags & CSF_SYNC_OBJECT_COMMENTS)
2204 object->commentsToMessage(&msg);
2205 if (!object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2206 {
2207 // mask passwords
2208 msg.setField(VID_SHARED_SECRET, _T("********"));
2209 msg.setField(VID_SNMP_AUTH_PASSWORD, _T("********"));
2210 msg.setField(VID_SNMP_PRIV_PASSWORD, _T("********"));
2211 }
2212 sendMessage(&msg);
2213 msg.deleteAllFields();
2214 }
2215 }
2216
2217 MutexUnlock(m_mutexSendObjects);
2218 safe_free(objects);
2219
2220 if (options & OBJECT_SYNC_DUAL_CONFIRM)
2221 {
2222 msg.setCode(CMD_REQUEST_COMPLETED);
2223 msg.setField(VID_RCC, RCC_SUCCESS);
2224 sendMessage(&msg);
2225 }
2226 }
2227
2228 /**
2229 * Send all configuration variables to client
2230 */
2231 void ClientSession::getConfigurationVariables(UINT32 dwRqId)
2232 {
2233 UINT32 i, dwId, dwNumRecords;
2234 NXCPMessage msg;
2235 TCHAR szBuffer[MAX_CONFIG_VALUE];
2236
2237 // Prepare message
2238 msg.setCode(CMD_REQUEST_COMPLETED);
2239 msg.setId(dwRqId);
2240
2241 // Check user rights
2242 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
2243 {
2244 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
2245
2246 // Retrieve configuration variables from database
2247 DB_RESULT hResult = DBSelect(hdb, _T("SELECT var_name,var_value,need_server_restart,data_type,description,default_value FROM config WHERE is_visible=1"));
2248 if (hResult != NULL)
2249 {
2250 // Send events, one per message
2251 dwNumRecords = DBGetNumRows(hResult);
2252 msg.setField(VID_NUM_VARIABLES, dwNumRecords);
2253 for(i = 0, dwId = VID_VARLIST_BASE; i < dwNumRecords; i++, dwId += 10)
2254 {
2255 msg.setField(dwId, DBGetField(hResult, i, 0, szBuffer, MAX_DB_STRING));
2256 msg.setField(dwId + 1, DBGetField(hResult, i, 1, szBuffer, MAX_CONFIG_VALUE));
2257 msg.setField(dwId + 2, (WORD)DBGetFieldLong(hResult, i, 2));
2258 msg.setField(dwId + 3, DBGetField(hResult, i, 3, szBuffer, MAX_CONFIG_VALUE));
2259 msg.setField(dwId + 4, DBGetField(hResult, i, 4, szBuffer, MAX_CONFIG_VALUE));
2260 msg.setField(dwId + 5, DBGetField(hResult, i, 5, szBuffer, MAX_CONFIG_VALUE));
2261 }
2262 DBFreeResult(hResult);
2263
2264 hResult = DBSelect(hdb, _T("SELECT var_name,var_value,var_description FROM config_values"));
2265 if (hResult != NULL)
2266 {
2267 dwNumRecords = DBGetNumRows(hResult);
2268 msg.setField(VID_NUM_VALUES, dwNumRecords);
2269 for(i = 0; i < dwNumRecords; i++)
2270 {
2271 msg.setField(dwId++, DBGetField(hResult, i, 0, szBuffer, MAX_DB_STRING));
2272 msg.setField(dwId++, DBGetField(hResult, i, 1, szBuffer, MAX_CONFIG_VALUE));
2273 msg.setField(dwId++, DBGetField(hResult, i, 2, szBuffer, MAX_DB_STRING));
2274 }
2275 DBFreeResult(hResult);
2276
2277 msg.setField(VID_RCC, RCC_SUCCESS);
2278 }
2279 else
2280 {
2281 msg.setField(VID_RCC, RCC_DB_FAILURE);
2282 }
2283 }
2284 else
2285 {
2286 msg.setField(VID_RCC, RCC_DB_FAILURE);
2287 }
2288 DBConnectionPoolReleaseConnection(hdb);
2289 }
2290 else
2291 {
2292 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2293 }
2294
2295 // Send response
2296 sendMessage(&msg);
2297 }
2298
2299 /**
2300 * Get public configuration variable by name
2301 */
2302 void ClientSession::getPublicConfigurationVariable(NXCPMessage *request)
2303 {
2304 NXCPMessage msg;
2305 msg.setCode(CMD_REQUEST_COMPLETED);
2306 msg.setId(request->getId());
2307
2308 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
2309
2310 DB_STATEMENT hStmt = DBPrepare(hdb, _T("SELECT var_value FROM config WHERE var_name=? AND is_public='Y'"));
2311 if (hStmt != NULL)
2312 {
2313 TCHAR name[64];
2314 request->getFieldAsString(VID_NAME, name, 64);
2315 DBBind(hStmt, 1, DB_SQLTYPE_VARCHAR, name, DB_BIND_STATIC);
2316
2317 DB_RESULT hResult = DBSelectPrepared(hStmt);
2318 if (hResult != NULL)
2319 {
2320 if (DBGetNumRows(hResult) > 0)
2321 {
2322 TCHAR value[MAX_CONFIG_VALUE];
2323 msg.setField(VID_VALUE, DBGetField(hResult, 0, 0, value, MAX_CONFIG_VALUE));
2324 msg.setField(VID_RCC, RCC_SUCCESS);
2325 }
2326 else
2327 {
2328 msg.setField(VID_RCC, RCC_UNKNOWN_CONFIG_VARIABLE);
2329 }
2330 DBFreeResult(hResult);
2331 }
2332 else
2333 {
2334 msg.setField(VID_RCC, RCC_DB_FAILURE);
2335 }
2336 DBFreeStatement(hStmt);
2337 }
2338 else
2339 {
2340 msg.setField(VID_RCC, RCC_DB_FAILURE);
2341 }
2342
2343 sendMessage(&msg);
2344 }
2345
2346 /**
2347 * Set configuration variable's value
2348 */
2349 void ClientSession::setConfigurationVariable(NXCPMessage *pRequest)
2350 {
2351 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
2352
2353 TCHAR name[MAX_OBJECT_NAME];
2354 pRequest->getFieldAsString(VID_NAME, name, MAX_OBJECT_NAME);
2355
2356 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
2357 {
2358 TCHAR oldValue[MAX_CONFIG_VALUE], newValue[MAX_CONFIG_VALUE];
2359 pRequest->getFieldAsString(VID_VALUE, newValue, MAX_CONFIG_VALUE);
2360 ConfigReadStr(name, oldValue, MAX_CONFIG_VALUE, _T(""));
2361 if (ConfigWriteStr(name, newValue, true))
2362 {
2363 msg.setField(VID_RCC, RCC_SUCCESS);
2364 writeAuditLogWithValues(AUDIT_SYSCFG, true, 0, oldValue, newValue,
2365 _T("Server configuration variable \"%s\" changed from \"%s\" to \"%s\""), name, oldValue, newValue);
2366 }
2367 else
2368 {
2369 msg.setField(VID_RCC, RCC_DB_FAILURE);
2370 }
2371 }
2372 else
2373 {
2374 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on setting server configuration variable \"%s\""), name);
2375 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2376 }
2377
2378 // Send response
2379 sendMessage(&msg);
2380 }
2381
2382 /**
2383 * Set configuration variable's values to default
2384 */
2385 void ClientSession::setDefaultConfigurationVariableValues(NXCPMessage *pRequest)
2386 {
2387 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
2388 UINT32 rcc = RCC_SUCCESS;
2389
2390 if (checkSysAccessRights(SYSTEM_ACCESS_SERVER_CONFIG))
2391 {
2392 DB_HANDLE hdb = DBConnectionPoolAcquireConnection();
2393 DB_STATEMENT stmt = DBPrepare(hdb, _T("SELECT default_value FROM config WHERE var_name=?"));
2394 if (stmt != NULL)
2395 {
2396 int numVars = pRequest->getFieldAsInt32(VID_NUM_VARIABLES);
2397 UINT32 fieldId = VID_VARLIST_BASE;
2398 TCHAR varName[64], defValue[MAX_CONFIG_VALUE];
2399 for(int i = 0; i < numVars; i++)
2400 {
2401 pRequest->getFieldAsString(fieldId++, varName, 64);
2402 DBBind(stmt, 1, DB_SQLTYPE_VARCHAR, varName, DB_BIND_STATIC);
2403
2404 DB_RESULT result = DBSelectPrepared(stmt);
2405 if (result != NULL)
2406 {
2407 DBGetField(result, 0, 0, defValue, MAX_CONFIG_VALUE);
2408 ConfigWriteStr(varName, defValue, false);
2409 }
2410 else
2411 {
2412 rcc = RCC_DB_FAILURE;
2413 break;
2414 }
2415 }
2416 DBFreeStatement(stmt);
2417 }
2418 else
2419 {
2420 rcc = RCC_DB_FAILURE;
2421 }
2422 DBConnectionPoolReleaseConnection(hdb);
2423 }
2424 else
2425 {
2426 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied for setting server configuration variables to default"));
2427 rcc = RCC_ACCESS_DENIED;
2428 }
2429 // Send response
2430 msg.setField(VID_RCC, rcc);
2431 sendMessage(&msg);
2432
2433 }
2434
2435 /**
2436 * Delete configuration variable
2437 */
2438 void ClientSession::deleteConfigurationVariable(NXCPMessage *pRequest)
2439 {
2440 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
2441
2442 TCHAR name[MAX_OBJECT_NAME];
2443 pRequest->getFieldAsString(VID_NAME, name, MAX_OBJECT_NAME);
2444
2445 if ((m_dwUserId == 0) || (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG))
2446 {
2447 if (ConfigDelete(name))
2448 {
2449 msg.setField(VID_RCC, RCC_SUCCESS);
2450 writeAuditLog(AUDIT_SYSCFG, true, 0, _T("Server configuration variable \"%s\" deleted"), name);
2451 }
2452 else
2453 {
2454 msg.setField(VID_RCC, RCC_DB_FAILURE);
2455 }
2456 }
2457 else
2458 {
2459 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on delete server configuration variable \"%s\""), name);
2460 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2461 }
2462
2463 // Send response
2464 sendMessage(&msg);
2465 }
2466
2467 /**
2468 * Set configuration clob
2469 */
2470 void ClientSession::setConfigCLOB(NXCPMessage *pRequest)
2471 {
2472 NXCPMessage msg(CMD_REQUEST_COMPLETED, pRequest->getId());
2473
2474 TCHAR name[MAX_OBJECT_NAME];
2475 pRequest->getFieldAsString(VID_NAME, name, MAX_OBJECT_NAME);
2476 if (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG)
2477 {
2478 TCHAR *newValue = pRequest->getFieldAsString(VID_VALUE);
2479 if (newValue != NULL)
2480 {
2481 TCHAR *oldValue = ConfigReadCLOB(name, _T(""));
2482 if (ConfigWriteCLOB(name, newValue, TRUE))
2483 {
2484 msg.setField(VID_RCC, RCC_SUCCESS);
2485 writeAuditLogWithValues(AUDIT_SYSCFG, true, 0, oldValue, newValue,
2486 _T("Server configuration variable (long) \"%s\" changed"), name);
2487 }
2488 else
2489 {
2490 msg.setField(VID_RCC, RCC_DB_FAILURE);
2491 }
2492 free(oldValue);
2493 free(newValue);
2494 }
2495 else
2496 {
2497 msg.setField(VID_RCC, RCC_INVALID_REQUEST);
2498 }
2499 }
2500 else
2501 {
2502 writeAuditLog(AUDIT_SYSCFG, false, 0, _T("Access denied on setting server configuration variable \"%s\""), name);
2503 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2504 }
2505
2506 sendMessage(&msg);
2507 }
2508
2509 /**
2510 * Get value of configuration clob
2511 */
2512 void ClientSession::getConfigCLOB(NXCPMessage *pRequest)
2513 {
2514 NXCPMessage msg;
2515 TCHAR name[MAX_OBJECT_NAME], *value;
2516
2517 msg.setId(pRequest->getId());
2518 msg.setCode(CMD_REQUEST_COMPLETED);
2519
2520 if (m_dwSystemAccess & SYSTEM_ACCESS_SERVER_CONFIG)
2521 {
2522 pRequest->getFieldAsString(VID_NAME, name, MAX_OBJECT_NAME);
2523 value = ConfigReadCLOB(name, NULL);
2524 if (value != NULL)
2525 {
2526 msg.setField(VID_VALUE, value);
2527 msg.setField(VID_RCC, RCC_SUCCESS);
2528 free(value);
2529 }
2530 else
2531 {
2532 msg.setField(VID_RCC, RCC_UNKNOWN_VARIABLE);
2533 }
2534 }
2535 else
2536 {
2537 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2538 }
2539
2540 sendMessage(&msg);
2541 }
2542
2543 /**
2544 * Close session
2545 */
2546 void ClientSession::kill()
2547 {
2548 notify(NX_NOTIFY_SESSION_KILLED);
2549
2550 // We shutdown socket connection, which will cause
2551 // read thread to stop, and other threads will follow
2552 shutdown(m_hSocket, SHUT_RDWR);
2553 }
2554
2555 /**
2556 * Handler for new events
2557 */
2558 void ClientSession::onNewEvent(Event *pEvent)
2559 {
2560 if (isAuthenticated() && isSubscribedTo(NXC_CHANNEL_EVENTS) && (m_dwSystemAccess & SYSTEM_ACCESS_VIEW_EVENT_LOG))
2561 {
2562 NetObj *object = FindObjectById(pEvent->getSourceId());
2563 // If can't find object - just send to all events, if object found send to thous who have rights
2564 if ((object == NULL) || object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
2565 {
2566 NXCPMessage msg(CMD_EVENTLOG_RECORDS, 0);
2567 pEvent->prepareMessage(&msg);
2568 postMessage(&msg);
2569 }
2570 }
2571 }
2572
2573 /**
2574 * Send object update (executed in thread pool)
2575 */
2576 void ClientSession::sendObjectUpdate(NetObj *object)
2577 {
2578 NXCPMessage msg(CMD_OBJECT_UPDATE, 0);
2579 if (!object->isDeleted())
2580 {
2581 object->fillMessage(&msg);
2582 if (m_dwFlags & CSF_SYNC_OBJECT_COMMENTS)
2583 object->commentsToMessage(&msg);
2584 }
2585 else
2586 {
2587 msg.setField(VID_OBJECT_ID, object->getId());
2588 msg.setField(VID_IS_DELETED, (UINT16)1);
2589 }
2590 MutexLock(m_mutexSendObjects);
2591 sendMessage(&msg);
2592 MutexUnlock(m_mutexSendObjects);
2593 object->decRefCount();
2594 decRefCount();
2595 }
2596
2597 /**
2598 * Handler for object changes
2599 */
2600 void ClientSession::onObjectChange(NetObj *object)
2601 {
2602 if (isAuthenticated() && isSubscribedTo(NXC_CHANNEL_OBJECTS) &&
2603 (object->isDeleted() || object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ)))
2604 {
2605 object->incRefCount();
2606 incRefCount();
2607 ThreadPoolExecute(g_mainThreadPool, this, &ClientSession::sendObjectUpdate, object);
2608 }
2609 }
2610
2611 /**
2612 * Send notification message to server
2613 */
2614 void ClientSession::notify(UINT32 dwCode, UINT32 dwData)
2615 {
2616 NXCPMessage msg;
2617
2618 msg.setCode(CMD_NOTIFY);
2619 msg.setField(VID_NOTIFICATION_CODE, dwCode);
2620 msg.setField(VID_NOTIFICATION_DATA, dwData);
2621 postMessage(&msg);
2622 }
2623
2624 /**
2625 * Set information about conflicting nodes to VID_VALUE field
2626 */
2627 static void SetNodesConflictString(NXCPMessage *msg, UINT32 zoneUIN, InetAddress ipAddr)
2628 {
2629 if (!ipAddr.isValid())
2630 return;
2631
2632 Node *sameNode = FindNodeByIP(zoneUIN, ipAddr);
2633 Subnet *sameSubnet = FindSubnetByIP(zoneUIN, ipAddr);
2634 if (sameNode != NULL)
2635 {
2636 msg->setField(VID_VALUE, sameNode->getName());
2637 }
2638 else if (sameSubnet != NULL)
2639 {
2640 msg->setField(VID_VALUE, sameSubnet->getName());
2641 }
2642 else
2643 {
2644 msg->setField(VID_VALUE, _T(""));
2645 }
2646 }
2647
2648 /**
2649 * Modify object
2650 */
2651 void ClientSession::modifyObject(NXCPMessage *pRequest)
2652 {
2653 UINT32 dwObjectId, dwResult = RCC_SUCCESS;
2654 NetObj *object;
2655 NXCPMessage msg;
2656
2657 // Prepare reply message
2658 msg.setCode(CMD_REQUEST_COMPLETED);
2659 msg.setId(pRequest->getId());
2660
2661 dwObjectId = pRequest->getFieldAsUInt32(VID_OBJECT_ID);
2662 object = FindObjectById(dwObjectId);
2663 if (object != NULL)
2664 {
2665 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
2666 {
2667 json_t *oldValue = object->toJson();
2668
2669 // If user attempts to change object's ACL, check
2670 // if he has OBJECT_ACCESS_ACL permission
2671 if (pRequest->isFieldExist(VID_ACL_SIZE))
2672 if (!object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_ACL))
2673 dwResult = RCC_ACCESS_DENIED;
2674
2675 // If user attempts to rename object, check object's name
2676 if (pRequest->isFieldExist(VID_OBJECT_NAME))
2677 {
2678 TCHAR name[256];
2679 pRequest->getFieldAsString(VID_OBJECT_NAME, name, 256);
2680 if (!IsValidObjectName(name, TRUE))
2681 dwResult = RCC_INVALID_OBJECT_NAME;
2682 }
2683
2684 // If allowed, change object and set completion code
2685 if (dwResult == RCC_SUCCESS)
2686 {
2687 dwResult = object->modifyFromMessage(pRequest);
2688 if (dwResult == RCC_SUCCESS)
2689 {
2690 object->postModify();
2691 }
2692 else if (dwResult == RCC_ALREADY_EXIST)
2693 {
2694 // Add information about conflicting nodes
2695 InetAddress ipAddr;
2696
2697 if (pRequest->isFieldExist(VID_IP_ADDRESS))
2698 {
2699 ipAddr = pRequest->getFieldAsInetAddress(VID_IP_ADDRESS);
2700 } else if (pRequest->isFieldExist(VID_PRIMARY_NAME))
2701 {
2702 TCHAR primaryName[MAX_DNS_NAME];
2703 pRequest->getFieldAsString(VID_PRIMARY_NAME, primaryName, MAX_DNS_NAME);
2704 ipAddr = InetAddress::resolveHostName(primaryName);
2705 }
2706 SetNodesConflictString(&msg, ((Node*)object)->getZoneUIN(), ipAddr);
2707 }
2708 }
2709 msg.setField(VID_RCC, dwResult);
2710
2711 if (dwResult == RCC_SUCCESS)
2712 {
2713 json_t *newValue = object->toJson();
2714 writeAuditLogWithValues(AUDIT_OBJECTS, true, dwObjectId, oldValue, newValue,
2715 _T("Object %s modified from client"), object->getName());
2716 json_decref(newValue);
2717 }
2718 json_decref(oldValue);
2719 }
2720 else
2721 {
2722 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2723 writeAuditLog(AUDIT_OBJECTS, false, dwObjectId, _T("Access denied on object modification"));
2724 }
2725 }
2726 else
2727 {
2728 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
2729 }
2730
2731 // Send response
2732 sendMessage(&msg);
2733 }
2734
2735 /**
2736 * Send users database to client
2737 */
2738 void ClientSession::sendUserDB(UINT32 dwRqId)
2739 {
2740 NXCPMessage msg;
2741 msg.setCode(CMD_REQUEST_COMPLETED);
2742 msg.setId(dwRqId);
2743 msg.setField(VID_RCC, RCC_SUCCESS);
2744 sendMessage(&msg);
2745 msg.deleteAllFields();
2746
2747 // Send user database
2748 Iterator<UserDatabaseObject> *users = OpenUserDatabase();
2749 while(users->hasNext())
2750 {
2751 UserDatabaseObject *object = users->next();
2752 msg.setCode(object->isGroup() ? CMD_GROUP_DATA : CMD_USER_DATA);
2753 object->fillMessage(&msg);
2754 sendMessage(&msg);
2755 msg.deleteAllFields();
2756 }
2757 CloseUserDatabase(users);
2758
2759 // Send end-of-database notification
2760 msg.setCode(CMD_USER_DB_EOF);
2761 sendMessage(&msg);
2762 }
2763
2764 /**
2765 * Create new user
2766 */
2767 void ClientSession::createUser(NXCPMessage *pRequest)
2768 {
2769 NXCPMessage msg;
2770
2771 // Prepare response message
2772 msg.setCode(CMD_REQUEST_COMPLETED);
2773 msg.setId(pRequest->getId());
2774
2775 // Check user rights
2776 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2777 {
2778 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2779 }
2780 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2781 {
2782 // User database have to be locked before any
2783 // changes to user database can be made
2784 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2785 }
2786 else
2787 {
2788 UINT32 dwResult, dwUserId;
2789 TCHAR szUserName[MAX_USER_NAME];
2790
2791 pRequest->getFieldAsString(VID_USER_NAME, szUserName, MAX_USER_NAME);
2792 if (IsValidObjectName(szUserName))
2793 {
2794 bool isGroup = pRequest->getFieldAsBoolean(VID_IS_GROUP);
2795 dwResult = CreateNewUser(szUserName, isGroup, &dwUserId);
2796 msg.setField(VID_RCC, dwResult);
2797 if (dwResult == RCC_SUCCESS)
2798 {
2799 msg.setField(VID_USER_ID, dwUserId); // Send id of new user to client
2800 writeAuditLog(AUDIT_SECURITY, true, 0, _T("%s %s created"), isGroup ? _T("Group") : _T("User"), szUserName);
2801 }
2802 }
2803 else
2804 {
2805 msg.setField(VID_RCC, RCC_INVALID_OBJECT_NAME);
2806 }
2807 }
2808
2809 // Send response
2810 sendMessage(&msg);
2811 }
2812
2813 /**
2814 * Update existing user's data
2815 */
2816 void ClientSession::updateUser(NXCPMessage *pRequest)
2817 {
2818 NXCPMessage msg;
2819
2820 // Prepare response message
2821 msg.setCode(CMD_REQUEST_COMPLETED);
2822 msg.setId(pRequest->getId());
2823
2824 // Check user rights
2825 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2826 {
2827 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2828 }
2829 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2830 {
2831 // User database have to be locked before any
2832 // changes to user database can be made
2833 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2834 }
2835 else
2836 {
2837 json_t *oldData = NULL, *newData = NULL;
2838 UINT32 result = ModifyUserDatabaseObject(pRequest, &oldData, &newData);
2839 if (result == RCC_SUCCESS)
2840 {
2841 TCHAR name[MAX_DB_STRING];
2842 UINT32 id = pRequest->getFieldAsUInt32(VID_USER_ID);
2843 ResolveUserId(id, name, MAX_DB_STRING);
2844 writeAuditLogWithValues(AUDIT_SECURITY, true, 0, oldData, newData,
2845 _T("%s %s modified"), (id & GROUP_FLAG) ? _T("Group") : _T("User"), name);
2846 }
2847 msg.setField(VID_RCC, result);
2848 json_decref(oldData);
2849 json_decref(newData);
2850 }
2851
2852 // Send response
2853 sendMessage(&msg);
2854 }
2855
2856 /**
2857 * Delete user
2858 */
2859 void ClientSession::detachLdapUser(NXCPMessage *pRequest)
2860 {
2861 NXCPMessage msg;
2862
2863 // Prepare response message
2864 msg.setCode(CMD_REQUEST_COMPLETED);
2865 msg.setId(pRequest->getId());
2866 UINT32 id = pRequest->getFieldAsUInt32(VID_USER_ID);
2867
2868 // Check user rights
2869 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2870 {
2871 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2872 }
2873 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2874 {
2875 // User database have to be locked before any
2876 // changes to user database can be made
2877 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2878 }
2879 else
2880 {
2881 UINT32 result = DetachLdapUser(id);
2882 if (result == RCC_SUCCESS)
2883 {
2884 TCHAR name[MAX_DB_STRING];
2885 ResolveUserId(id, name, MAX_DB_STRING);
2886 writeAuditLog(AUDIT_SECURITY, true, 0,
2887 _T("%s %s detached from LDAP account"), (id & GROUP_FLAG) ? _T("Group") : _T("User"), name);
2888 }
2889 msg.setField(VID_RCC, result);
2890 }
2891
2892 // Send response
2893 sendMessage(&msg);
2894 }
2895
2896 /**
2897 * Delete user
2898 */
2899 void ClientSession::deleteUser(NXCPMessage *pRequest)
2900 {
2901 NXCPMessage msg;
2902 UINT32 dwUserId;
2903
2904 // Prepare response message
2905 msg.setCode(CMD_REQUEST_COMPLETED);
2906 msg.setId(pRequest->getId());
2907
2908 // Check user rights
2909 if (!(m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS))
2910 {
2911 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2912 }
2913 else if (!(m_dwFlags & CSF_USER_DB_LOCKED))
2914 {
2915 // User database have to be locked before any
2916 // changes to user database can be made
2917 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
2918 }
2919 else
2920 {
2921 // Get Id of user to be deleted
2922 dwUserId = pRequest->getFieldAsUInt32(VID_USER_ID);
2923
2924 if ((dwUserId != 0) && (dwUserId != GROUP_EVERYONE))
2925 {
2926 if (!IsLoggedIn(dwUserId))
2927 {
2928 TCHAR name[MAX_DB_STRING];
2929 ResolveUserId(dwUserId, name, MAX_DB_STRING);
2930 UINT32 rcc = DeleteUserDatabaseObject(dwUserId);
2931 msg.setField(VID_RCC, rcc);
2932 if(rcc == RCC_SUCCESS)
2933 {
2934 writeAuditLog(AUDIT_SECURITY, true, 0,
2935 _T("%s %s [%d] deleted"), (dwUserId & GROUP_FLAG) ? _T("Group") : _T("User"), name, dwUserId);
2936 }
2937 }
2938 else
2939 {
2940 // logger in users cannot be deleted
2941 msg.setField(VID_RCC, RCC_USER_LOGGED_IN);
2942 }
2943 }
2944 else
2945 {
2946 // System administrator account and everyone group cannot be deleted
2947 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2948 }
2949 }
2950
2951 // Send response
2952 sendMessage(&msg);
2953 }
2954
2955 /**
2956 * Lock/unlock user database
2957 */
2958 void ClientSession::lockUserDB(UINT32 dwRqId, BOOL bLock)
2959 {
2960 NXCPMessage msg;
2961 TCHAR szBuffer[256];
2962
2963 // Prepare response message
2964 msg.setCode(CMD_REQUEST_COMPLETED);
2965 msg.setId(dwRqId);
2966
2967 if (m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS)
2968 {
2969 if (bLock)
2970 {
2971 if (!LockComponent(CID_USER_DB, m_id, m_sessionName, NULL, szBuffer))
2972 {
2973 msg.setField(VID_RCC, RCC_COMPONENT_LOCKED);
2974 msg.setField(VID_LOCKED_BY, szBuffer);
2975 }
2976 else
2977 {
2978 m_dwFlags |= CSF_USER_DB_LOCKED;
2979 msg.setField(VID_RCC, RCC_SUCCESS);
2980 }
2981 }
2982 else
2983 {
2984 if (m_dwFlags & CSF_USER_DB_LOCKED)
2985 {
2986 UnlockComponent(CID_USER_DB);
2987 m_dwFlags &= ~CSF_USER_DB_LOCKED;
2988 }
2989 msg.setField(VID_RCC, RCC_SUCCESS);
2990 }
2991 }
2992 else
2993 {
2994 // Current user has no rights for user account management
2995 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
2996 }
2997
2998 // Send response
2999 sendMessage(&msg);
3000 }
3001
3002 /**
3003 * Change management status for the object
3004 */
3005 void ClientSession::changeObjectMgmtStatus(NXCPMessage *pRequest)
3006 {
3007 NXCPMessage msg;
3008 UINT32 dwObjectId;
3009 NetObj *object;
3010
3011 // Prepare response message
3012 msg.setCode(CMD_REQUEST_COMPLETED);
3013 msg.setId(pRequest->getId());
3014
3015 // Get object id and check access rights
3016 dwObjectId = pRequest->getFieldAsUInt32(VID_OBJECT_ID);
3017 object = FindObjectById(dwObjectId);
3018 if (object != NULL)
3019 {
3020 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
3021 {
3022 if ((object->getObjectClass() != OBJECT_TEMPLATE) &&
3023 (object->getObjectClass() != OBJECT_TEMPLATEGROUP) &&
3024 (object->getObjectClass() != OBJECT_TEMPLATEROOT))
3025 {
3026 BOOL bIsManaged = (BOOL)pRequest->getFieldAsUInt16(VID_MGMT_STATUS);
3027 object->setMgmtStatus(bIsManaged);
3028 msg.setField(VID_RCC, RCC_SUCCESS);
3029 WriteAuditLog(AUDIT_OBJECTS, TRUE, m_dwUserId, m_workstation, m_id, object->getId(),
3030 _T("Object %s set to %s state"), object->getName(), bIsManaged ? _T("managed") : _T("unmanaged"));
3031 }
3032 else
3033 {
3034 msg.setField(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3035 }
3036 }
3037 else
3038 {
3039 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3040 }
3041 }
3042 else
3043 {
3044 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3045 }
3046
3047 // Send response
3048 sendMessage(&msg);
3049 }
3050
3051 /**
3052 * Enter maintenance mode for object
3053 */
3054 void ClientSession::enterMaintenanceMode(NXCPMessage *request)
3055 {
3056 NXCPMessage msg;
3057 msg.setCode(CMD_REQUEST_COMPLETED);
3058 msg.setId(request->getId());
3059
3060 // Get object id and check access rights
3061 NetObj *object = FindObjectById(request->getFieldAsUInt32(VID_OBJECT_ID));
3062 if (object != NULL)
3063 {
3064 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MAINTENANCE))
3065 {
3066 if ((object->getObjectClass() == OBJECT_CONTAINER) ||
3067 (object->getObjectClass() == OBJECT_CLUSTER) ||
3068 (object->getObjectClass() == OBJECT_NODE) ||
3069 (object->getObjectClass() == OBJECT_MOBILEDEVICE) ||
3070 (object->getObjectClass() == OBJECT_ACCESSPOINT) ||
3071 (object->getObjectClass() == OBJECT_CHASSIS) ||
3072 (object->getObjectClass() == OBJECT_ZONE) ||
3073 (object->getObjectClass() == OBJECT_SUBNET) ||
3074 (object->getObjectClass() == OBJECT_NETWORK) ||
3075 (object->getObjectClass() == OBJECT_SERVICEROOT)||
3076 (object->getObjectClass() == OBJECT_SENSOR))
3077 {
3078 object->enterMaintenanceMode();
3079 msg.setField(VID_RCC, RCC_SUCCESS);
3080 WriteAuditLog(AUDIT_OBJECTS, TRUE, m_dwUserId, m_workstation, m_id, object->getId(),
3081 _T("Requested maintenance mode enter for object %s [%d]"), object->getName(), object->getId());
3082 }
3083 else
3084 {
3085 msg.setField(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3086 }
3087 }
3088 else
3089 {
3090 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3091 WriteAuditLog(AUDIT_OBJECTS, FALSE, m_dwUserId, m_workstation, m_id, object->getId(),
3092 _T("Access denied on maintenance mode enter request for object %s [%d]"), object->getName(), object->getId());
3093 }
3094 }
3095 else
3096 {
3097 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3098 }
3099
3100 sendMessage(&msg);
3101 }
3102
3103 /**
3104 * Leave maintenance mode for object
3105 */
3106 void ClientSession::leaveMaintenanceMode(NXCPMessage *request)
3107 {
3108 NXCPMessage msg;
3109 msg.setCode(CMD_REQUEST_COMPLETED);
3110 msg.setId(request->getId());
3111
3112 // Get object id and check access rights
3113 NetObj *object = FindObjectById(request->getFieldAsUInt32(VID_OBJECT_ID));
3114 if (object != NULL)
3115 {
3116 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MAINTENANCE))
3117 {
3118 if ((object->getObjectClass() == OBJECT_CONTAINER) ||
3119 (object->getObjectClass() == OBJECT_CLUSTER) ||
3120 (object->getObjectClass() == OBJECT_NODE) ||
3121 (object->getObjectClass() == OBJECT_MOBILEDEVICE) ||
3122 (object->getObjectClass() == OBJECT_ACCESSPOINT) ||
3123 (object->getObjectClass() == OBJECT_CHASSIS) ||
3124 (object->getObjectClass() == OBJECT_ZONE) ||
3125 (object->getObjectClass() == OBJECT_SUBNET) ||
3126 (object->getObjectClass() == OBJECT_NETWORK) ||
3127 (object->getObjectClass() == OBJECT_SERVICEROOT) ||
3128 (object->getObjectClass() == OBJECT_SENSOR))
3129 {
3130 object->leaveMaintenanceMode();
3131 msg.setField(VID_RCC, RCC_SUCCESS);
3132 WriteAuditLog(AUDIT_OBJECTS, TRUE, m_dwUserId, m_workstation, m_id, object->getId(),
3133 _T("Requested maintenance mode exit for object %s [%d]"), object->getName(), object->getId());
3134 }
3135 else
3136 {
3137 msg.setField(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3138 }
3139 }
3140 else
3141 {
3142 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3143 WriteAuditLog(AUDIT_OBJECTS, FALSE, m_dwUserId, m_workstation, m_id, object->getId(),
3144 _T("Access denied on maintenance mode exit request for object %s [%d]"), object->getName(), object->getId());
3145 }
3146 }
3147 else
3148 {
3149 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3150 }
3151
3152 sendMessage(&msg);
3153 }
3154
3155 /**
3156 * Validate password for currently logged in user
3157 */
3158 void ClientSession::validatePassword(NXCPMessage *request)
3159 {
3160 NXCPMessage msg;
3161 msg.setCode(CMD_REQUEST_COMPLETED);
3162 msg.setId(request->getId());
3163
3164 #ifdef UNICODE
3165 TCHAR password[256];
3166 request->getFieldAsString(VID_PASSWORD, password, 256);
3167 #else
3168 char password[256];
3169 request->getFieldAsUtf8String(VID_PASSWORD, password, 256);
3170 #endif
3171
3172 bool isValid = false;
3173 msg.setField(VID_RCC, ValidateUserPassword(m_dwUserId, m_loginName, password, &isValid));
3174 msg.setField(VID_PASSWORD_IS_VALID, (INT16)(isValid ? 1 : 0));
3175
3176 sendMessage(&msg);
3177 }
3178
3179 /**
3180 * Set user's password
3181 */
3182 void ClientSession::setPassword(NXCPMessage *request)
3183 {
3184 NXCPMessage msg;
3185 msg.setCode(CMD_REQUEST_COMPLETED);
3186 msg.setId(request->getId());
3187
3188 UINT32 userId = request->getFieldAsUInt32(VID_USER_ID);
3189 if ((m_dwSystemAccess & SYSTEM_ACCESS_MANAGE_USERS) || (userId == m_dwUserId)) // User can change password for itself
3190 {
3191 TCHAR newPassword[1024], oldPassword[1024];
3192 #ifdef UNICODE
3193 request->getFieldAsString(VID_PASSWORD, newPassword, 256);
3194 if (request->isFieldExist(VID_OLD_PASSWORD))
3195 request->getFieldAsString(VID_OLD_PASSWORD, oldPassword, 256);
3196 #else
3197 request->getFieldAsUtf8String(VID_PASSWORD, newPassword, 1024);
3198 if (request->isFieldExist(VID_OLD_PASSWORD))
3199 request->getFieldAsUtf8String(VID_OLD_PASSWORD, oldPassword, 1024);
3200 #endif
3201 else
3202 oldPassword[0] = 0;
3203
3204 UINT32 rcc = SetUserPassword(userId, newPassword, oldPassword, userId == m_dwUserId);
3205 msg.setField(VID_RCC, rcc);
3206
3207 if (rcc == RCC_SUCCESS)
3208 {
3209 TCHAR userName[MAX_DB_STRING];
3210 ResolveUserId(userId, userName, MAX_DB_STRING);
3211 WriteAuditLog(AUDIT_SECURITY, TRUE, m_dwUserId, m_workstation, m_id, 0, _T("Changed password for user %s"), userName);
3212 }
3213 }
3214 else
3215 {
3216 // Current user has no rights to change password for specific user
3217 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3218 }
3219
3220 // Send response
3221 sendMessage(&msg);
3222 }
3223
3224 /**
3225 * Send node's DCIs to client and lock data collection settings
3226 */
3227 void ClientSession::openNodeDCIList(NXCPMessage *request)
3228 {
3229 NXCPMessage msg;
3230 UINT32 dwObjectId;
3231 NetObj *object;
3232 BOOL bSuccess = FALSE;
3233 TCHAR szLockInfo[MAX_SESSION_NAME];
3234
3235 // Prepare response message
3236 msg.setCode(CMD_REQUEST_COMPLETED);
3237 msg.setId(request->getId());
3238
3239 // Get node id and check object class and access rights
3240 dwObjectId = request->getFieldAsUInt32(VID_OBJECT_ID);
3241 object = FindObjectById(dwObjectId);
3242 if (object != NULL)
3243 {
3244 if (object->isDataCollectionTarget() || (object->getObjectClass() == OBJECT_TEMPLATE))
3245 {
3246 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3247 {
3248 // Try to lock DCI list
3249 if (((Template *)object)->lockDCIList(m_id, m_sessionName, szLockInfo))
3250 {
3251 bSuccess = TRUE;
3252 msg.setField(VID_RCC, RCC_SUCCESS);
3253
3254 // modify list of open nodes DCI lists
3255 m_pOpenDCIList = (UINT32 *)realloc(m_pOpenDCIList, sizeof(UINT32) * (m_dwOpenDCIListSize + 1));
3256 m_pOpenDCIList[m_dwOpenDCIListSize] = dwObjectId;
3257 m_dwOpenDCIListSize++;
3258 }
3259 else
3260 {
3261 msg.setField(VID_RCC, RCC_COMPONENT_LOCKED);
3262 msg.setField(VID_LOCKED_BY, szLockInfo);
3263 }
3264 }
3265 else
3266 {
3267 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3268 }
3269 }
3270 else
3271 {
3272 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3273 }
3274 }
3275 else
3276 {
3277 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3278 }
3279
3280 // Send response
3281 sendMessage(&msg);
3282
3283 // If DCI list was successfully locked, send it to client
3284 if (bSuccess)
3285 ((Template *)object)->sendItemsToClient(this, request->getId());
3286 }
3287
3288 /**
3289 * Unlock node's data collection settings
3290 */
3291 void ClientSession::closeNodeDCIList(NXCPMessage *request)
3292 {
3293 NXCPMessage msg;
3294 UINT32 dwObjectId;
3295 NetObj *object;
3296
3297 // Prepare response message
3298 msg.setCode(CMD_REQUEST_COMPLETED);
3299 msg.setId(request->getId());
3300
3301 // Get node id and check object class and access rights
3302 dwObjectId = request->getFieldAsUInt32(VID_OBJECT_ID);
3303 object = FindObjectById(dwObjectId);
3304 if (object != NULL)
3305 {
3306 if (object->isDataCollectionTarget() || (object->getObjectClass() == OBJECT_TEMPLATE))
3307 {
3308 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3309 {
3310 BOOL bSuccess;
3311
3312 // Try to unlock DCI list
3313 bSuccess = ((Template *)object)->unlockDCIList(m_id);
3314 msg.setField(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_OUT_OF_STATE_REQUEST);
3315
3316 // modify list of open nodes DCI lists
3317 if (bSuccess)
3318 {
3319 UINT32 i;
3320
3321 for(i = 0; i < m_dwOpenDCIListSize; i++)
3322 if (m_pOpenDCIList[i] == dwObjectId)
3323 {
3324 m_dwOpenDCIListSize--;
3325 memmove(&m_pOpenDCIList[i], &m_pOpenDCIList[i + 1], sizeof(UINT32) * (m_dwOpenDCIListSize - i));
3326 break;
3327 }
3328 }
3329 }
3330 else
3331 {
3332 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3333 }
3334 }
3335 else
3336 {
3337 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3338 }
3339 }
3340 else
3341 {
3342 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3343 }
3344
3345 // Send response
3346 sendMessage(&msg);
3347 }
3348
3349 /**
3350 * Create, modify, or delete data collection item for node
3351 */
3352 void ClientSession::modifyNodeDCI(NXCPMessage *request)
3353 {
3354 NXCPMessage msg;
3355 UINT32 dwObjectId;
3356 NetObj *object;
3357
3358 // Prepare response message
3359 msg.setCode(CMD_REQUEST_COMPLETED);
3360 msg.setId(request->getId());
3361
3362 // Get node id and check object class and access rights
3363 dwObjectId = request->getFieldAsUInt32(VID_OBJECT_ID);
3364 object = FindObjectById(dwObjectId);
3365 if (object != NULL)
3366 {
3367 if (object->isDataCollectionTarget() || (object->getObjectClass() == OBJECT_TEMPLATE))
3368 {
3369 if (((Template *)object)->isLockedBySession(m_id))
3370 {
3371 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
3372 {
3373 UINT32 i, dwItemId, dwNumMaps, *pdwMapId, *pdwMapIndex;
3374 DCObject *dcObject;
3375 BOOL bSuccess = FALSE;
3376
3377 int dcObjectType = (int)request->getFieldAsUInt16(VID_DCOBJECT_TYPE);
3378 switch(request->getCode())
3379 {
3380 case CMD_CREATE_NEW_DCI:
3381 // Create dummy DCI
3382 switch(dcObjectType)
3383 {
3384 case DCO_TYPE_ITEM:
3385 dcObject = new DCItem(CreateUniqueId(IDG_ITEM), _T("no name"), DS_INTERNAL, DCI_DT_INT,
3386 ConfigReadInt(_T("DefaultDCIPollingInterval"), 60),
3387 ConfigReadInt(_T("DefaultDCIRetentionTime"), 30), (Node *)object);
3388 break;
3389 case DCO_TYPE_TABLE:
3390 dcObject = new DCTable(CreateUniqueId(IDG_ITEM), _T("no name"), DS_INTERNAL,
3391 ConfigReadInt(_T("DefaultDCIPollingInterval"), 60),
3392 ConfigReadInt(_T("DefaultDCIRetentionTime"), 30), (Node *)object);
3393 break;
3394 default:
3395 dcObject = NULL;
3396 break;
3397 }
3398 if (dcObject != NULL)
3399 {
3400 dcObject->setStatus(ITEM_STATUS_DISABLED, false);
3401 if ((bSuccess = ((Template *)object)->addDCObject(dcObject)))
3402 {
3403 msg.setField(VID_RCC, RCC_SUCCESS);
3404 // Return new item id to client
3405 msg.setField(VID_DCI_ID, dcObject->getId());
3406 }
3407 else // Unable to add item to node
3408 {
3409 delete dcObject;
3410 msg.setField(VID_RCC, RCC_DUPLICATE_DCI);
3411 }
3412 }
3413 else
3414 {
3415 msg.setField(VID_RCC, RCC_INVALID_ARGUMENT);
3416 }
3417 break;
3418 case CMD_MODIFY_NODE_DCI:
3419 dwItemId = request->getFieldAsUInt32(VID_DCI_ID);
3420 bSuccess = ((Template *)object)->updateDCObject(dwItemId, request, &dwNumMaps, &pdwMapIndex, &pdwMapId);
3421 if (bSuccess)
3422 {
3423 msg.setField(VID_RCC, RCC_SUCCESS);
3424
3425 // Send index to id mapping for newly created thresholds to client
3426 if (dcObjectType == DCO_TYPE_ITEM)
3427 {
3428 msg.setField(VID_DCI_NUM_MAPS, dwNumMaps);
3429 for(i = 0; i < dwNumMaps; i++)
3430 {
3431 pdwMapId[i] = htonl(pdwMapId[i]);
3432 pdwMapIndex[i] = htonl(pdwMapIndex[i]);
3433 }
3434 msg.setField(VID_DCI_MAP_IDS, (BYTE *)pdwMapId, sizeof(UINT32) * dwNumMaps);
3435 msg.setField(VID_DCI_MAP_INDEXES, (BYTE *)pdwMapIndex, sizeof(UINT32) * dwNumMaps);
3436 safe_free(pdwMapId);
3437 safe_free(pdwMapIndex);
3438 }
3439 }
3440 else
3441 {
3442 msg.setField(VID_RCC, RCC_INVALID_DCI_ID);
3443 }
3444 break;
3445 case CMD_DELETE_NODE_DCI:
3446 dwItemId = request->getFieldAsUInt32(VID_DCI_ID);
3447 bSuccess = ((Template *)object)->deleteDCObject(dwItemId, true);
3448 msg.setField(VID_RCC, bSuccess ? RCC_SUCCESS : RCC_INVALID_DCI_ID);
3449 break;
3450 }
3451 if (bSuccess)
3452 ((Template *)object)->setDCIModificationFlag();
3453 }
3454 else // User doesn't have MODIFY rights on object
3455 {
3456 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3457 }
3458 }
3459 else // Nodes DCI list not locked by this session
3460 {
3461 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3462 }
3463 }
3464 else // Object is not a node
3465 {
3466 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3467 }
3468 }
3469 else // No object with given ID
3470 {
3471 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3472 }
3473
3474 // Send response
3475 sendMessage(&msg);
3476 }
3477
3478 /**
3479 * Change status for one or more DCIs
3480 */
3481 void ClientSession::changeDCIStatus(NXCPMessage *request)
3482 {
3483 NXCPMessage msg;
3484 NetObj *object;
3485
3486 // Prepare response message
3487 msg.setCode(CMD_REQUEST_COMPLETED);
3488 msg.setId(request->getId());
3489
3490 // Get node id and check object class and access rights
3491 object = FindObjectById(request->getFieldAsUInt32(VID_OBJECT_ID));
3492 if (object != NULL)
3493 {
3494 if (object->isDataCollectionTarget() || (object->getObjectClass() == OBJECT_TEMPLATE))
3495 {
3496 if (((Template *)object)->isLockedBySession(m_id))
3497 {
3498 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
3499 {
3500 UINT32 dwNumItems, *pdwItemList;
3501 int iStatus;
3502
3503 iStatus = request->getFieldAsUInt16(VID_DCI_STATUS);
3504 dwNumItems = request->getFieldAsUInt32(VID_NUM_ITEMS);
3505 pdwItemList = (UINT32 *)malloc(sizeof(UINT32) * dwNumItems);
3506 request->getFieldAsInt32Array(VID_ITEM_LIST, dwNumItems, pdwItemList);
3507 if (((Template *)object)->setItemStatus(dwNumItems, pdwItemList, iStatus))
3508 msg.setField(VID_RCC, RCC_SUCCESS);
3509 else
3510 msg.setField(VID_RCC, RCC_INVALID_DCI_ID);
3511 free(pdwItemList);
3512 }
3513 else // User doesn't have MODIFY rights on object
3514 {
3515 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3516 }
3517 }
3518 else // Nodes DCI list not locked by this session
3519 {
3520 msg.setField(VID_RCC, RCC_OUT_OF_STATE_REQUEST);
3521 }
3522 }
3523 else // Object is not a node
3524 {
3525 msg.setField(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3526 }
3527 }
3528 else // No object with given ID
3529 {
3530 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3531 }
3532
3533 // Send response
3534 sendMessage(&msg);
3535 }
3536
3537 /**
3538 * Recalculate values for DCI
3539 */
3540 void ClientSession::recalculateDCIValues(NXCPMessage *request)
3541 {
3542 NXCPMessage msg(CMD_REQUEST_COMPLETED, request->getId());
3543
3544 NetObj *object = FindObjectById(request->getFieldAsUInt32(VID_OBJECT_ID));
3545 if (object != NULL)
3546 {
3547 if (object->isDataCollectionTarget())
3548 {
3549 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_MODIFY))
3550 {
3551 UINT32 dciId = request->getFieldAsUInt32(VID_DCI_ID);
3552 debugPrintf(4, _T("recalculateDCIValues: request for DCI %d at target %s [%d]"), dciId, object->getName(), object->getId());
3553 DCObject *dci = static_cast<DataCollectionTarget*>(object)->getDCObjectById(dciId);
3554 if (dci != NULL)
3555 {
3556 if (dci->getType() == DCO_TYPE_ITEM)
3557 {
3558 debugPrintf(4, _T("recalculateDCIValues: DCI \"%s\" [%d] at target %s [%d]"), dci->getDescription(), dciId, object->getName(), object->getId());
3559 DCIRecalculationJob *job = new DCIRecalculationJob(static_cast<DataCollectionTarget*>(object), static_cast<DCItem*>(dci), m_dwUserId);
3560 if (AddJob(job))
3561 {
3562 msg.setField(VID_RCC, RCC_SUCCESS);
3563 msg.setField(VID_JOB_ID, job->getId());
3564 writeAuditLog(AUDIT_OBJECTS, true, object->getId(), _T("Data recalculation for DCI \"%s\" [%d] on object \"%s\" [%d] started (job ID %d)"),
3565 dci->getDescription(), dci->getId(), object->getName(), object->getId(), job->getId());
3566 }
3567 else
3568 {
3569 delete job;
3570 msg.setField(VID_RCC, RCC_INTERNAL_ERROR);
3571 }
3572 }
3573 else
3574 {
3575 msg.setField(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3576 }
3577 }
3578 else
3579 {
3580 msg.setField(VID_RCC, RCC_INVALID_DCI_ID);
3581 debugPrintf(4, _T("recalculateDCIValues: DCI %d at target %s [%d] not found"), dciId, object->getName(), object->getId());
3582 }
3583 }
3584 else // User doesn't have MODIFY rights on object
3585 {
3586 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3587 writeAuditLog(AUDIT_OBJECTS, false, object->getId(), _T("Access denied on recalculating DCI data"));
3588 }
3589 }
3590 else // Object is not a node
3591 {
3592 msg.setField(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3593 }
3594 }
3595 else // No object with given ID
3596 {
3597 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3598 }
3599
3600 sendMessage(&msg);
3601 }
3602
3603 /**
3604 * Clear all collected data for DCI
3605 */
3606 void ClientSession::clearDCIData(NXCPMessage *request)
3607 {
3608 NXCPMessage msg(CMD_REQUEST_COMPLETED, request->getId());
3609
3610 // Get node id and check object class and access rights
3611 NetObj *object = FindObjectById(request->getFieldAsUInt32(VID_OBJECT_ID));
3612 if (object != NULL)
3613 {
3614 if (object->isDataCollectionTarget())
3615 {
3616 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_DELETE))
3617 {
3618 UINT32 dciId = request->getFieldAsUInt32(VID_DCI_ID);
3619 debugPrintf(4, _T("ClearDCIData: request for DCI %d at node %d"), dciId, object->getId());
3620 DCObject *dci = ((Template *)object)->getDCObjectById(dciId);
3621 if (dci != NULL)
3622 {
3623 msg.setField(VID_RCC, dci->deleteAllData() ? RCC_SUCCESS : RCC_DB_FAILURE);
3624 debugPrintf(4, _T("ClearDCIData: DCI %d at node %d"), dciId, object->getId());
3625 writeAuditLog(AUDIT_OBJECTS, true, object->getId(), _T("Collected data for DCI \"%s\" [%d] on object \"%s\" [%d] cleared"),
3626 dci->getDescription(), dci->getId(), object->getName(), object->getId());
3627 }
3628 else
3629 {
3630 msg.setField(VID_RCC, RCC_INVALID_DCI_ID);
3631 debugPrintf(4, _T("ClearDCIData: DCI %d at node %d not found"), dciId, object->getId());
3632 }
3633 }
3634 else // User doesn't have DELETE rights on object
3635 {
3636 writeAuditLog(AUDIT_OBJECTS, false, object->getId(), _T("Access denied on clear DCI data"));
3637 msg.setField(VID_RCC, RCC_ACCESS_DENIED);
3638 }
3639 }
3640 else // Object is not a node
3641 {
3642 msg.setField(VID_RCC, RCC_INCOMPATIBLE_OPERATION);
3643 }
3644 }
3645 else // No object with given ID
3646 {
3647 msg.setField(VID_RCC, RCC_INVALID_OBJECT_ID);
3648 }
3649
3650 // Send response
3651 sendMessage(&msg);
3652 }
3653
3654 /**
3655 * Force DCI data poll for given DCI
3656 */
3657 void ClientSession::forceDCIPoll(NXCPMessage *request)
3658 {
3659 NXCPMessage msg;
3660 NetObj *object;
3661 UINT32 dwItemId;
3662
3663 // Prepare response message
3664 msg.setCode(CMD_REQUEST_COMPLETED);
3665 msg.setId(request->getId());
3666
3667 // Get node id and check object class and access rights
3668 object = FindObjectById(request->getFieldAsUInt32(VID_OBJECT_ID));
3669 if (object != NULL)
3670 {
3671 if (object->isDataCollectionTarget())
3672 {
3673 if (object->checkAccessRights(m_dwUserId, OBJECT_ACCESS_READ))
3674 {
3675 dwItemId = request->getFieldAsUInt32(VID_DCI_ID);
3676 debugPrintf(4, _T("ForceDCIPoll: request for DCI %d at node %d"), dwItemId, object->getId());
3677 DCObject *dci = ((Template *)object)->getDCObjectById(dwItemId);
3678 if (dci != NULL)
3679 {
3680 dci->requestForcePoll(this);
3681 msg.setField(VID_RCC, RCC_SUCCESS);
3682 debugPrintf(4, _T("ForceDCIPoll: DCI %d at node %d"), dwItemId, object->