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