1 /*
2 ** Zabbix
3 ** Copyright (C) 2001-2021 Zabbix SIA
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 **/
19
20 #include "checks_ssh.h"
21
22 /* the size of temporary buffer used to read from data channel */
23 #define DATA_BUFFER_SIZE 4096
24
25 #if defined(HAVE_SSH2)
26 #include <libssh2.h>
27 #elif defined (HAVE_SSH)
28 #include <libssh/libssh.h>
29 #endif
30
31 #if defined(HAVE_SSH2) || defined(HAVE_SSH)
32 #include "comms.h"
33 #include "log.h"
34
35 #define SSH_RUN_KEY "ssh.run"
36 #endif
37
38 #if defined(HAVE_SSH2)
39 static const char *password;
40
kbd_callback(const char * name,int name_len,const char * instruction,int instruction_len,int num_prompts,const LIBSSH2_USERAUTH_KBDINT_PROMPT * prompts,LIBSSH2_USERAUTH_KBDINT_RESPONSE * responses,void ** abstract)41 static void kbd_callback(const char *name, int name_len, const char *instruction,
42 int instruction_len, int num_prompts,
43 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
44 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses, void **abstract)
45 {
46 (void)name;
47 (void)name_len;
48 (void)instruction;
49 (void)instruction_len;
50
51 if (num_prompts == 1)
52 {
53 responses[0].text = zbx_strdup(NULL, password);
54 responses[0].length = strlen(password);
55 }
56
57 (void)prompts;
58 (void)abstract;
59 }
60
waitsocket(int socket_fd,LIBSSH2_SESSION * session)61 static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
62 {
63 struct timeval tv;
64 int rc, dir;
65 fd_set fd, *writefd = NULL, *readfd = NULL;
66
67 tv.tv_sec = 10;
68 tv.tv_usec = 0;
69
70 FD_ZERO(&fd);
71 FD_SET(socket_fd, &fd);
72
73 /* now make sure we wait in the correct direction */
74 dir = libssh2_session_block_directions(session);
75
76 if (0 != (dir & LIBSSH2_SESSION_BLOCK_INBOUND))
77 readfd = &fd;
78
79 if (0 != (dir & LIBSSH2_SESSION_BLOCK_OUTBOUND))
80 writefd = &fd;
81
82 rc = select(socket_fd + 1, readfd, writefd, NULL, &tv);
83
84 return rc;
85 }
86
87 /* example ssh.run["ls /"] */
ssh_run(DC_ITEM * item,AGENT_RESULT * result,const char * encoding)88 static int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
89 {
90 zbx_socket_t s;
91 LIBSSH2_SESSION *session;
92 LIBSSH2_CHANNEL *channel;
93 int auth_pw = 0, rc, ret = NOTSUPPORTED, exitcode;
94 char tmp_buf[DATA_BUFFER_SIZE], *userauthlist, *publickey = NULL, *privatekey = NULL, *ssherr,
95 *output, *buffer = NULL;
96 size_t offset = 0, buf_size = DATA_BUFFER_SIZE;
97
98 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
99
100 if (FAIL == zbx_tcp_connect(&s, CONFIG_SOURCE_IP, item->interface.addr, item->interface.port, 0,
101 ZBX_TCP_SEC_UNENCRYPTED, NULL, NULL))
102 {
103 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot connect to SSH server: %s", zbx_socket_strerror()));
104 goto close;
105 }
106
107 /* initializes an SSH session object */
108 if (NULL == (session = libssh2_session_init()))
109 {
110 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot initialize SSH session"));
111 goto tcp_close;
112 }
113
114 /* set blocking mode on session */
115 libssh2_session_set_blocking(session, 1);
116
117 /* Create a session instance and start it up. This will trade welcome */
118 /* banners, exchange keys, and setup crypto, compression, and MAC layers */
119 if (0 != libssh2_session_startup(session, s.socket))
120 {
121 libssh2_session_last_error(session, &ssherr, NULL, 0);
122 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot establish SSH session: %s", ssherr));
123 goto session_free;
124 }
125
126 /* check what authentication methods are available */
127 if (NULL != (userauthlist = libssh2_userauth_list(session, item->username, strlen(item->username))))
128 {
129 if (NULL != strstr(userauthlist, "password"))
130 auth_pw |= 1;
131 if (NULL != strstr(userauthlist, "keyboard-interactive"))
132 auth_pw |= 2;
133 if (NULL != strstr(userauthlist, "publickey"))
134 auth_pw |= 4;
135 }
136 else
137 {
138 libssh2_session_last_error(session, &ssherr, NULL, 0);
139 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot obtain authentication methods: %s", ssherr));
140 goto session_close;
141 }
142
143 zabbix_log(LOG_LEVEL_DEBUG, "%s() supported authentication methods:'%s'", __func__, userauthlist);
144
145 switch (item->authtype)
146 {
147 case ITEM_AUTHTYPE_PASSWORD:
148 if (auth_pw & 1)
149 {
150 /* we could authenticate via password */
151 if (0 != libssh2_userauth_password(session, item->username, item->password))
152 {
153 libssh2_session_last_error(session, &ssherr, NULL, 0);
154 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Password authentication failed: %s",
155 ssherr));
156 goto session_close;
157 }
158 else
159 zabbix_log(LOG_LEVEL_DEBUG, "%s() password authentication succeeded", __func__);
160 }
161 else if (auth_pw & 2)
162 {
163 /* or via keyboard-interactive */
164 password = item->password;
165 if (0 != libssh2_userauth_keyboard_interactive(session, item->username, &kbd_callback))
166 {
167 libssh2_session_last_error(session, &ssherr, NULL, 0);
168 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Keyboard-interactive authentication"
169 " failed: %s", ssherr));
170 goto session_close;
171 }
172 else
173 zabbix_log(LOG_LEVEL_DEBUG, "%s() keyboard-interactive authentication succeeded",
174 __func__);
175 }
176 else
177 {
178 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Unsupported authentication method."
179 " Supported methods: %s", userauthlist));
180 goto session_close;
181 }
182 break;
183 case ITEM_AUTHTYPE_PUBLICKEY:
184 if (auth_pw & 4)
185 {
186 if (NULL == CONFIG_SSH_KEY_LOCATION)
187 {
188 SET_MSG_RESULT(result, zbx_strdup(NULL, "Authentication by public key failed."
189 " SSHKeyLocation option is not set"));
190 goto session_close;
191 }
192
193 /* or by public key */
194 publickey = zbx_dsprintf(publickey, "%s/%s", CONFIG_SSH_KEY_LOCATION, item->publickey);
195 privatekey = zbx_dsprintf(privatekey, "%s/%s", CONFIG_SSH_KEY_LOCATION,
196 item->privatekey);
197
198 if (SUCCEED != zbx_is_regular_file(publickey))
199 {
200 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot access public key file %s",
201 publickey));
202 goto session_close;
203 }
204
205 if (SUCCEED != zbx_is_regular_file(privatekey))
206 {
207 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot access private key file %s",
208 privatekey));
209 goto session_close;
210 }
211
212 rc = libssh2_userauth_publickey_fromfile(session, item->username, publickey,
213 privatekey, item->password);
214
215 if (0 != rc)
216 {
217 libssh2_session_last_error(session, &ssherr, NULL, 0);
218 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Public key authentication failed:"
219 " %s", ssherr));
220 goto session_close;
221 }
222 else
223 zabbix_log(LOG_LEVEL_DEBUG, "%s() authentication by public key succeeded",
224 __func__);
225 }
226 else
227 {
228 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Unsupported authentication method."
229 " Supported methods: %s", userauthlist));
230 goto session_close;
231 }
232 break;
233 }
234
235 /* exec non-blocking on the remove host */
236 while (NULL == (channel = libssh2_channel_open_session(session)))
237 {
238 switch (libssh2_session_last_error(session, NULL, NULL, 0))
239 {
240 /* marked for non-blocking I/O but the call would block. */
241 case LIBSSH2_ERROR_EAGAIN:
242 waitsocket(s.socket, session);
243 continue;
244 default:
245 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot establish generic session channel"));
246 goto session_close;
247 }
248 }
249
250 dos2unix(item->params); /* CR+LF (Windows) => LF (Unix) */
251 /* request a shell on a channel and execute command */
252 while (0 != (rc = libssh2_channel_exec(channel, item->params)))
253 {
254 switch (rc)
255 {
256 case LIBSSH2_ERROR_EAGAIN:
257 waitsocket(s.socket, session);
258 continue;
259 default:
260 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot request a shell"));
261 goto channel_close;
262 }
263 }
264
265 buffer = (char *)zbx_malloc(buffer, buf_size);
266
267 while (0 != (rc = libssh2_channel_read(channel, tmp_buf, sizeof(tmp_buf))))
268 {
269 if (rc < 0)
270 {
271 if (LIBSSH2_ERROR_EAGAIN == rc)
272 waitsocket(s.socket, session);
273
274 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot read data from SSH server"));
275 goto channel_close;
276 }
277
278 if (MAX_EXECUTE_OUTPUT_LEN <= offset + rc)
279 {
280 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Command output exceeded limit of %d KB",
281 MAX_EXECUTE_OUTPUT_LEN / ZBX_KIBIBYTE));
282 goto channel_close;
283 }
284
285 zbx_str_memcpy_alloc(&buffer, &buf_size, &offset, tmp_buf, rc);
286 }
287
288 output = convert_to_utf8(buffer, offset, encoding);
289 zbx_rtrim(output, ZBX_WHITESPACE);
290 zbx_replace_invalid_utf8(output);
291
292 SET_TEXT_RESULT(result, output);
293 output = NULL;
294
295 ret = SYSINFO_RET_OK;
296 channel_close:
297 /* close an active data channel */
298 exitcode = 127;
299 while (LIBSSH2_ERROR_EAGAIN == (rc = libssh2_channel_close(channel)))
300 waitsocket(s.socket, session);
301
302 zbx_free(buffer);
303
304 if (0 != rc)
305 {
306 libssh2_session_last_error(session, &ssherr, NULL, 0);
307 zabbix_log(LOG_LEVEL_WARNING, "%s() cannot close generic session channel: %s", __func__, ssherr);
308 }
309 else
310 exitcode = libssh2_channel_get_exit_status(channel);
311
312 zabbix_log(LOG_LEVEL_DEBUG, "%s() exitcode:%d bytecount:" ZBX_FS_SIZE_T, __func__, exitcode, offset);
313
314 libssh2_channel_free(channel);
315 channel = NULL;
316
317 session_close:
318 libssh2_session_disconnect(session, "Normal Shutdown");
319
320 session_free:
321 libssh2_session_free(session);
322
323 tcp_close:
324 zbx_tcp_close(&s);
325
326 close:
327 zbx_free(publickey);
328 zbx_free(privatekey);
329 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
330
331 return ret;
332 }
333 #elif defined(HAVE_SSH)
334
335 /* example ssh.run["ls /"] */
ssh_run(DC_ITEM * item,AGENT_RESULT * result,const char * encoding)336 static int ssh_run(DC_ITEM *item, AGENT_RESULT *result, const char *encoding)
337 {
338 ssh_session session;
339 ssh_channel channel;
340 ssh_key privkey = NULL, pubkey = NULL;
341 int rc, userauth, ret = NOTSUPPORTED;
342 char *output, *publickey = NULL, *privatekey = NULL, *buffer = NULL;
343 char tmp_buf[DATA_BUFFER_SIZE], userauthlist[64];
344 size_t offset = 0, buf_size = DATA_BUFFER_SIZE;
345
346 zabbix_log(LOG_LEVEL_DEBUG, "In %s()", __func__);
347
348 /* initializes an SSH session object */
349 if (NULL == (session = ssh_new()))
350 {
351 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot initialize SSH session"));
352 zabbix_log(LOG_LEVEL_DEBUG, "Cannot initialize SSH session");
353
354 goto close;
355 }
356
357 /* set blocking mode on session */
358 ssh_set_blocking(session, 1);
359
360 /* create a session instance and start it up */
361 if (0 != ssh_options_set(session, SSH_OPTIONS_HOST, item->interface.addr) ||
362 0 != ssh_options_set(session, SSH_OPTIONS_PORT, &item->interface.port) ||
363 0 != ssh_options_set(session, SSH_OPTIONS_USER, item->username))
364 {
365 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot set SSH session options: %s",
366 ssh_get_error(session)));
367 goto session_free;
368 }
369
370 if (SSH_OK != ssh_connect(session))
371 {
372 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot establish SSH session: %s", ssh_get_error(session)));
373 goto session_free;
374 }
375
376 /* check which authentication methods are available */
377 if (SSH_AUTH_ERROR == ssh_userauth_none(session, NULL))
378 {
379 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Error during authentication: %s", ssh_get_error(session)));
380 goto session_close;
381 }
382
383 userauthlist[0] = '\0';
384
385 if (0 != (userauth = ssh_userauth_list(session, NULL)))
386 {
387 if (0 != (userauth & SSH_AUTH_METHOD_NONE))
388 offset += zbx_snprintf(userauthlist + offset, sizeof(userauthlist) - offset, "none, ");
389 if (0 != (userauth & SSH_AUTH_METHOD_PASSWORD))
390 offset += zbx_snprintf(userauthlist + offset, sizeof(userauthlist) - offset, "password, ");
391 if (0 != (userauth & SSH_AUTH_METHOD_INTERACTIVE))
392 offset += zbx_snprintf(userauthlist + offset, sizeof(userauthlist) - offset,
393 "keyboard-interactive, ");
394 if (0 != (userauth & SSH_AUTH_METHOD_PUBLICKEY))
395 offset += zbx_snprintf(userauthlist + offset, sizeof(userauthlist) - offset, "publickey, ");
396 if (0 != (userauth & SSH_AUTH_METHOD_HOSTBASED))
397 offset += zbx_snprintf(userauthlist + offset, sizeof(userauthlist) - offset, "hostbased, ");
398 if (2 <= offset)
399 userauthlist[offset-2] = '\0';
400 }
401
402 zabbix_log(LOG_LEVEL_DEBUG, "%s() supported authentication methods: %s", __func__, userauthlist);
403
404 switch (item->authtype)
405 {
406 case ITEM_AUTHTYPE_PASSWORD:
407 if (0 != (userauth & SSH_AUTH_METHOD_PASSWORD))
408 {
409 /* we could authenticate via password */
410 if (SSH_AUTH_SUCCESS != ssh_userauth_password(session, NULL, item->password))
411 {
412 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Password authentication failed: %s",
413 ssh_get_error(session)));
414 goto session_close;
415 }
416 else
417 zabbix_log(LOG_LEVEL_DEBUG, "%s() password authentication succeeded", __func__);
418 }
419 else if (0 != (userauth & SSH_AUTH_METHOD_INTERACTIVE))
420 {
421 /* or via keyboard-interactive */
422 while (SSH_AUTH_INFO == (rc = ssh_userauth_kbdint(session, item->username, NULL)))
423 {
424 if (1 == ssh_userauth_kbdint_getnprompts(session) &&
425 0 != ssh_userauth_kbdint_setanswer(session, 0, item->password))
426 {
427 zabbix_log(LOG_LEVEL_DEBUG,"Cannot set answer: %s",
428 ssh_get_error(session));
429 }
430 }
431
432 if (SSH_AUTH_SUCCESS != rc)
433 {
434 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Keyboard-interactive authentication"
435 " failed: %s", ssh_get_error(session)));
436 goto session_close;
437 }
438 else
439 {
440 zabbix_log(LOG_LEVEL_DEBUG, "%s() keyboard-interactive authentication"
441 " succeeded", __func__);
442 }
443 }
444 else
445 {
446 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Unsupported authentication method."
447 " Supported methods: %s", userauthlist));
448 goto session_close;
449 }
450 break;
451 case ITEM_AUTHTYPE_PUBLICKEY:
452 if (0 != (userauth & SSH_AUTH_METHOD_PUBLICKEY))
453 {
454 if (NULL == CONFIG_SSH_KEY_LOCATION)
455 {
456 SET_MSG_RESULT(result, zbx_strdup(NULL, "Authentication by public key failed."
457 " SSHKeyLocation option is not set"));
458 goto session_close;
459 }
460
461 /* or by public key */
462 publickey = zbx_dsprintf(publickey, "%s/%s", CONFIG_SSH_KEY_LOCATION, item->publickey);
463 privatekey = zbx_dsprintf(privatekey, "%s/%s", CONFIG_SSH_KEY_LOCATION,
464 item->privatekey);
465
466 if (SUCCEED != zbx_is_regular_file(publickey))
467 {
468 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot access public key file %s",
469 publickey));
470 goto session_close;
471 }
472
473 if (SUCCEED != zbx_is_regular_file(privatekey))
474 {
475 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot access private key file %s",
476 privatekey));
477 goto session_close;
478 }
479
480 if (SSH_OK != ssh_pki_import_pubkey_file(publickey, &pubkey))
481 {
482 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Failed to import public key: %s",
483 ssh_get_error(session)));
484 goto session_close;
485 }
486
487 if (SSH_AUTH_SUCCESS != ssh_userauth_try_publickey(session, NULL, pubkey))
488 {
489 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Public key try failed: %s",
490 ssh_get_error(session)));
491 goto session_close;
492 }
493
494 if (SSH_OK != (rc = ssh_pki_import_privkey_file(privatekey, item->password, NULL, NULL,
495 &privkey)))
496 {
497 if (SSH_EOF == rc)
498 {
499 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot import private key"
500 " file \"%s\" because it does not exist or permission"
501 " denied", privatekey));
502 goto session_close;
503 }
504
505 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Cannot import private key \"%s\"",
506 privatekey));
507
508 zabbix_log(LOG_LEVEL_DEBUG, "%s() failed to import private key \"%s\", rc:%d",
509 __func__, privatekey, rc);
510
511 goto session_close;
512 }
513
514 if (SSH_AUTH_SUCCESS != ssh_userauth_publickey(session, NULL, privkey))
515 {
516 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Public key authentication failed:"
517 " %s", ssh_get_error(session)));
518 goto session_close;
519 }
520 else
521 zabbix_log(LOG_LEVEL_DEBUG, "%s() authentication by public key succeeded",
522 __func__);
523 }
524 else
525 {
526 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Unsupported authentication method."
527 " Supported methods: %s", userauthlist));
528 goto session_close;
529 }
530 break;
531 }
532
533 if (NULL == (channel = ssh_channel_new(session)))
534 {
535 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot create generic session channel"));
536 goto session_close;
537 }
538
539 while (SSH_OK != (rc = ssh_channel_open_session(channel)))
540 {
541 if (SSH_AGAIN != rc)
542 {
543 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot establish generic session channel"));
544 goto channel_free;
545 }
546 }
547
548 /* request a shell on a channel and execute command */
549 dos2unix(item->params); /* CR+LF (Windows) => LF (Unix) */
550
551 while (SSH_OK != (rc = ssh_channel_request_exec(channel, item->params)))
552 {
553 if (SSH_AGAIN != rc)
554 {
555 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot request a shell"));
556 goto channel_free;
557 }
558 }
559
560 buffer = (char *)zbx_malloc(buffer, buf_size);
561 offset = 0;
562
563 while (0 != (rc = ssh_channel_read(channel, tmp_buf, sizeof(tmp_buf), 0)))
564 {
565 if (rc < 0)
566 {
567 if (SSH_AGAIN == rc)
568 continue;
569
570 SET_MSG_RESULT(result, zbx_strdup(NULL, "Cannot read data from SSH server"));
571 goto channel_close;
572 }
573
574 if (MAX_EXECUTE_OUTPUT_LEN <= offset + rc)
575 {
576 SET_MSG_RESULT(result, zbx_dsprintf(NULL, "Command output exceeded limit of %d KB",
577 MAX_EXECUTE_OUTPUT_LEN / ZBX_KIBIBYTE));
578 goto channel_close;
579 }
580
581 zbx_str_memcpy_alloc(&buffer, &buf_size, &offset, tmp_buf, rc);
582 }
583
584 output = convert_to_utf8(buffer, offset, encoding);
585 zbx_rtrim(output, ZBX_WHITESPACE);
586 zbx_replace_invalid_utf8(output);
587
588 SET_TEXT_RESULT(result, output);
589 output = NULL;
590
591 ret = SYSINFO_RET_OK;
592 channel_close:
593 ssh_channel_close(channel);
594 zbx_free(buffer);
595 channel_free:
596 ssh_channel_free(channel);
597 session_close:
598 if (NULL != privkey)
599 ssh_key_free(privkey);
600 if (NULL != pubkey)
601 ssh_key_free(pubkey);
602 ssh_disconnect(session);
603 session_free:
604 ssh_free(session);
605 close:
606 zbx_free(publickey);
607 zbx_free(privatekey);
608 zabbix_log(LOG_LEVEL_DEBUG, "End of %s():%s", __func__, zbx_result_string(ret));
609
610 return ret;
611 }
612 #endif
613
614 #if defined(HAVE_SSH2) || defined(HAVE_SSH)
get_value_ssh(DC_ITEM * item,AGENT_RESULT * result)615 int get_value_ssh(DC_ITEM *item, AGENT_RESULT *result)
616 {
617 AGENT_REQUEST request;
618 int ret = NOTSUPPORTED;
619 const char *port, *encoding, *dns;
620
621 init_request(&request);
622
623 if (SUCCEED != parse_item_key(item->key, &request))
624 {
625 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid item key format."));
626 goto out;
627 }
628
629 if (0 != strcmp(SSH_RUN_KEY, get_rkey(&request)))
630 {
631 SET_MSG_RESULT(result, zbx_strdup(NULL, "Unsupported item key for this item type."));
632 goto out;
633 }
634
635 if (4 < get_rparams_num(&request))
636 {
637 SET_MSG_RESULT(result, zbx_strdup(NULL, "Too many parameters."));
638 goto out;
639 }
640
641 if (NULL != (dns = get_rparam(&request, 1)) && '\0' != *dns)
642 {
643 strscpy(item->interface.dns_orig, dns);
644 item->interface.addr = item->interface.dns_orig;
645 }
646
647 if (NULL != (port = get_rparam(&request, 2)) && '\0' != *port)
648 {
649 if (FAIL == is_ushort(port, &item->interface.port))
650 {
651 SET_MSG_RESULT(result, zbx_strdup(NULL, "Invalid third parameter."));
652 goto out;
653 }
654 }
655 else
656 item->interface.port = ZBX_DEFAULT_SSH_PORT;
657
658 encoding = get_rparam(&request, 3);
659
660 ret = ssh_run(item, result, ZBX_NULL2EMPTY_STR(encoding));
661 out:
662 free_request(&request);
663
664 return ret;
665 }
666 #endif /* defined(HAVE_SSH2) || defined(HAVE_SSH) */
667