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