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