license changed to LGPL for libnxcl, libnxsnmp, libnxlp, libnxsl, and libnxmap
[public/netxms.git] / src / libnxcl / main.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Client Library
4 ** Copyright (C) 2003-2010 Victor Kirhenshtein
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published by
8 ** the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: main.cpp
21 **
22 **/
23
24 #include "libnxcl.h"
25
26
27 //
28 // Global variables
29 //
30
31 NXC_DEBUG_CALLBACK g_pDebugCallBack = NULL;
32
33
34 //
35 // Print debug messages
36 //
37
38 void DebugPrintf(const TCHAR *format, ...)
39 {
40 va_list args;
41 TCHAR buffer[4096];
42
43 if (g_pDebugCallBack == NULL)
44 return;
45
46 va_start(args, format);
47 _vsntprintf(buffer, 4096, format, args);
48 va_end(args);
49 g_pDebugCallBack(buffer);
50 }
51
52
53 //
54 // Initialization function
55 //
56
57 BOOL LIBNXCL_EXPORTABLE NXCInitialize(void)
58 {
59 return InitCryptoLib(0xFFFF);
60 }
61
62
63 //
64 // Shutdown function
65 //
66
67 void LIBNXCL_EXPORTABLE NXCShutdown(void)
68 {
69 }
70
71
72 //
73 // Get library version
74 //
75
76 DWORD LIBNXCL_EXPORTABLE NXCGetVersion(void)
77 {
78 return (NETXMS_VERSION_MAJOR << 24) | (NETXMS_VERSION_MINOR << 16) | NETXMS_VERSION_BUILD;
79 }
80
81
82 //
83 // Set event handler
84 //
85
86 void LIBNXCL_EXPORTABLE NXCSetEventHandler(NXC_SESSION hSession, NXC_EVENT_HANDLER pHandler)
87 {
88 ((NXCL_Session *)hSession)->m_pEventHandler = pHandler;
89 }
90
91
92 //
93 // Set callback for debug messages
94 //
95
96 void LIBNXCL_EXPORTABLE NXCSetDebugCallback(NXC_DEBUG_CALLBACK pFunc)
97 {
98 g_pDebugCallBack = pFunc;
99 }
100
101
102 //
103 // Set command timeout
104 //
105
106 void LIBNXCL_EXPORTABLE NXCSetCommandTimeout(NXC_SESSION hSession, DWORD dwTimeout)
107 {
108 if ((dwTimeout >= 1000) && (dwTimeout <= 60000))
109 ((NXCL_Session *)hSession)->m_dwCommandTimeout = dwTimeout;
110 }
111
112
113 //
114 // Get server ID
115 //
116
117 void LIBNXCL_EXPORTABLE NXCGetServerID(NXC_SESSION hSession, BYTE *pbsId)
118 {
119 memcpy(pbsId, ((NXCL_Session *)hSession)->m_bsServerId, 8);
120 }
121
122
123 //
124 // Subscribe to channel
125 //
126
127 DWORD LIBNXCL_EXPORTABLE NXCSubscribe(NXC_SESSION hSession, DWORD dwChannels)
128 {
129 return ((NXCL_Session *)hSession)->SetSubscriptionStatus(dwChannels, 1);
130 }
131
132
133 //
134 // Unsubscribe from channel
135 //
136
137 DWORD LIBNXCL_EXPORTABLE NXCUnsubscribe(NXC_SESSION hSession, DWORD dwChannels)
138 {
139 return ((NXCL_Session *)hSession)->SetSubscriptionStatus(dwChannels, 0);
140 }
141
142
143 //
144 // Set client data
145 //
146
147 void LIBNXCL_EXPORTABLE NXCSetClientData(NXC_SESSION hSession, void *pData)
148 {
149 if (hSession != NULL)
150 ((NXCL_Session *)hSession)->SetClientData(pData);
151 }
152
153
154 //
155 // Get client data
156 //
157
158 void LIBNXCL_EXPORTABLE *NXCGetClientData(NXC_SESSION hSession)
159 {
160 return (hSession != NULL) ? ((NXCL_Session *)hSession)->GetClientData() : NULL;
161 }
162
163
164 //
165 // Check if password needs to be changed
166 //
167
168 BOOL LIBNXCL_EXPORTABLE NXCNeedPasswordChange(NXC_SESSION hSession)
169 {
170 return ((NXCL_Session *)hSession)->NeedPasswordChange();
171 }
172
173
174 //
175 // Check if server has problems with backend database connection
176 //
177
178 BOOL LIBNXCL_EXPORTABLE NXCIsDBConnLost(NXC_SESSION hSession)
179 {
180 return ((NXCL_Session *)hSession)->IsDBConnLost();
181 }
182
183
184 //
185 // Check if password needs to be changed
186 //
187
188 void LIBNXCL_EXPORTABLE NXCStartWatchdog(NXC_SESSION hSession)
189 {
190 ((NXCL_Session *)hSession)->StartWatchdogThread();
191 }
192
193
194 //
195 // Get last lock information (owner of already locked component)
196 //
197
198 void LIBNXCL_EXPORTABLE NXCGetLastLockOwner(NXC_SESSION hSession, TCHAR *pszBuffer,
199 int nBufSize)
200 {
201 if (hSession != NULL)
202 nx_strncpy(pszBuffer, ((NXCL_Session *)hSession)->getLastLock(), nBufSize);
203 else
204 nx_strncpy(pszBuffer, _T("INVALID SESSION HANDLE"), nBufSize);
205 }
206
207
208 //
209 // Send SMS via server
210 //
211
212 DWORD LIBNXCL_EXPORTABLE NXCSendSMS(NXC_SESSION hSession, TCHAR *phone, TCHAR *message)
213 {
214 CSCPMessage msg;
215 DWORD dwRqId;
216
217 CHECK_SESSION_HANDLE();
218
219 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
220
221 msg.SetCode(CMD_SEND_SMS);
222 msg.SetId(dwRqId);
223 msg.SetVariable(VID_RCPT_ADDR, phone);
224 msg.SetVariable(VID_MESSAGE, message);
225 ((NXCL_Session *)hSession)->SendMsg(&msg);
226
227 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
228 }
229
230
231 //
232 // Check connection status by sending keepalive message
233 //
234
235 DWORD LIBNXCL_EXPORTABLE NXCCheckConnection(NXC_SESSION hSession)
236 {
237 CSCPMessage msg;
238 DWORD dwRqId;
239
240 CHECK_SESSION_HANDLE();
241
242 dwRqId = ((NXCL_Session *)hSession)->CreateRqId();
243
244 msg.SetCode(CMD_KEEPALIVE);
245 msg.SetId(dwRqId);
246 if (!((NXCL_Session *)hSession)->SendMsg(&msg))
247 return RCC_COMM_FAILURE;
248
249 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
250 }
251
252
253 //
254 // Get server's time zone
255 //
256
257 const TCHAR LIBNXCL_EXPORTABLE *NXCGetServerTimeZone(NXC_SESSION hSession)
258 {
259 const TCHAR *ptr;
260
261 ptr = ((NXCL_Session *)hSession)->getServerTimeZone();
262 return (*ptr == 0) ? NULL : ptr;
263 }
264
265
266 //
267 // Generate Message ID
268 //
269
270 DWORD LIBNXCL_EXPORTABLE NXCGenerateMessageId(NXC_SESSION hSession)
271 {
272 return ((NXCL_Session *)hSession)->CreateRqId();
273 }
274
275
276 //
277 // Send prepared NXCP message
278 //
279
280 BOOL LIBNXCL_EXPORTABLE NXCSendMessage(NXC_SESSION hSession, CSCPMessage *msg)
281 {
282 CHECK_SESSION_HANDLE();
283 return ((NXCL_Session *)hSession)->SendMsg(msg);
284 }
285
286
287 //
288 // Wait for message
289 //
290
291 CSCPMessage LIBNXCL_EXPORTABLE *NXCWaitForMessage(NXC_SESSION hSession, WORD wCode, DWORD dwRqId)
292 {
293 return (hSession != NULL) ? ((NXCL_Session *)hSession)->WaitForMessage(wCode, dwRqId) : NULL;
294 }
295
296
297 //
298 // Wait for CMD_REQUEST_COMPLETED message and return value of VID_RCC
299 //
300
301 DWORD LIBNXCL_EXPORTABLE NXCWaitForRCC(NXC_SESSION hSession, DWORD dwRqId)
302 {
303 CHECK_SESSION_HANDLE();
304 return ((NXCL_Session *)hSession)->WaitForRCC(dwRqId);
305 }
306
307
308 //
309 // Get text for error
310 //
311
312 const TCHAR LIBNXCL_EXPORTABLE *NXCGetErrorText(DWORD dwError)
313 {
314 static const TCHAR *pszErrorText[] =
315 {
316 _T("Request completed successfully"),
317 _T("Component locked"),
318 _T("Access denied"),
319 _T("Invalid request"),
320 _T("Request timed out"),
321 _T("Request is out of state"),
322 _T("Database failure"),
323 _T("Invalid object ID"),
324 _T("Object already exist"),
325 _T("Communication failure"),
326 _T("System failure"),
327 _T("Invalid user ID"),
328 _T("Invalid argument"),
329 _T("Duplicate DCI"),
330 _T("Invalid DCI ID"),
331 _T("Out of memory"),
332 _T("Input/Output error"),
333 _T("Incompatible operation"),
334 _T("Object creation failed"),
335 _T("Loop in object relationship detected"),
336 _T("Invalid object name"),
337 _T("Invalid alarm ID"),
338 _T("Invalid action ID"),
339 _T("Operation in progress"),
340 _T("Copy operation failed for one or more DCI(s)"),
341 _T("Invalid or unknown event code"),
342 _T("No interfaces suitable for sending magic packet"),
343 _T("No MAC address on interface"),
344 _T("Command not implemented"),
345 _T("Invalid trap configuration record ID"),
346 _T("Requested data collection item is not supported by agent"),
347 _T("Client and server versions mismatch"),
348 _T("Error parsing package information file"),
349 _T("Package with specified properties already installed on server"),
350 _T("Package file already exist on server"),
351 _T("Server resource busy"),
352 _T("Invalid package ID"),
353 _T("Invalid IP address"),
354 _T("Action is used in event processing policy"),
355 _T("Variable not found"),
356 _T("Server uses incompatible version of communication protocol"),
357 _T("Address already in use"),
358 _T("Unable to select cipher"),
359 _T("Invalid public key"),
360 _T("Invalid session key"),
361 _T("Encryption is not supported by peer"),
362 _T("Server internal error"),
363 _T("Execution of external command failed"),
364 _T("Invalid object tool ID"),
365 _T("SNMP protocol error"),
366 _T("Incorrect regular expression"),
367 _T("Parameter is not supported by agent"),
368 _T("File I/O operation failed"),
369 _T("MIB file is corrupted"),
370 _T("File transfer operation already in progress"),
371 _T("Invalid job ID"),
372 _T("Invalid script ID"),
373 _T("Invalid script name"),
374 _T("Unknown map name"),
375 _T("Invalid map ID"),
376 _T("Account disabled"),
377 _T("No more grace logins"),
378 _T("Server connection broken"),
379 _T("Invalid agent configuration ID"),
380 _T("Server has lost connection with backend database"),
381 _T("Alarm is still open in helpdesk system"),
382 _T("Alarm is not in \"outstanding\" state"),
383 _T("DCI data source is not a push agent"),
384 _T("Error parsing configuration import file"),
385 _T("Configuration cannot be imported because of validation errors"),
386 _T("Invalid graph ID"),
387 _T("Local cryptographic provider failure"),
388 _T("Unsupported authentication type"),
389 _T("Bad certificate"),
390 _T("Invalid certificate ID"),
391 _T("SNMP failure"),
392 _T("Node has no support for layer 2 topology discovery"),
393 _T("Invalid situation ID"),
394 _T("Named instance not found"),
395 _T("Invalid event ID"),
396 _T("Operation cannot be completed due to agent error"),
397 _T("Unknown variable"),
398 _T("Requested resource not available"),
399 _T("Job cannot be cancelled"),
400 _T("Invalid policy ID"),
401 _T("Unknown log name"),
402 _T("Invalid log handle"),
403 _T("New password is too weak"),
404 _T("Password was used before"),
405 _T("Invalid session handle")
406 };
407 return ((dwError >= 0) && (dwError <= RCC_INVALID_SESSION_HANDLE)) ? pszErrorText[dwError] : _T("No text message for this error");
408 }
409
410
411 //
412 // Decrypt password
413 //
414
415 BOOL LIBNXCL_EXPORTABLE NXCDecryptPassword(const TCHAR *login, const TCHAR *encryptedPasswd, TCHAR *decryptedPasswd)
416 {
417 if (_tcslen(encryptedPasswd) != 44)
418 return FALSE;
419
420 #ifdef UNICODE
421 char *mbencrypted = MBStringFromWideString(encryptedPasswd);
422 char *mblogin = MBStringFromWideString(login);
423 #else
424 const char *mbencrypted = encryptedPasswd;
425 const char *mblogin = login;
426 #endif
427
428 BYTE encrypted[32], decrypted[32], key[16];
429 size_t encSize;
430 base64_decode(mbencrypted, strlen(mbencrypted), (char *)encrypted, &encSize);
431 if (encSize != 32)
432 return FALSE;
433
434 CalculateMD5Hash((BYTE *)mblogin, strlen(mblogin), key);
435 ICEDecryptData(encrypted, 32, decrypted, key);
436 decrypted[31] = 0;
437
438 #ifdef UNICODE
439 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, (char *)decrypted, -1, decryptedPasswd, 32);
440 decryptedPasswd[31] = 0;
441 free(mbencrypted);
442 free(mblogin);
443 #else
444 nx_strncpy(decryptedPasswd, (char *)decrypted, 32);
445 #endif
446
447 return TRUE;
448 }
449
450
451 //
452 // DLL entry point
453 //
454
455 #if defined(_WIN32) && !defined(UNDER_CE)
456
457 BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
458 {
459 if (dwReason == DLL_PROCESS_ATTACH)
460 DisableThreadLibraryCalls(hInstance);
461 return TRUE;
462 }
463
464 #endif /* _WIN32 */