max agent message size increased to 256MB
[public/netxms.git] / src / agent / subagents / ssh / session.cpp
CommitLineData
12acf3d3
VK
1/*
2** NetXMS SSH subagent
3** Copyright (C) 2004-2016 Victor Kirhenshtein
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 "ssh_subagent.h"
24
25/**
26 * SSH session constructor
27 */
28SSHSession::SSHSession(const InetAddress& addr, UINT16 port)
29{
30 m_addr = addr;
31 m_port = port;
32 m_session = NULL;
33}
34
35/**
36 * SSH session destructor
37 */
38SSHSession::~SSHSession()
39{
40 disconnect();
41}
42
43/**
44 * Connect to server
45 */
46bool SSHSession::connect(const TCHAR *user, const TCHAR *password)
47{
48 if (m_session != NULL)
49 return false; // already connected
50
51 m_session = ssh_new();
52 if (m_session == NULL)
53 return false; // cannot create session
54
55 bool success = false;
56
57 char hostname[64];
58 ssh_options_set(m_session, SSH_OPTIONS_HOST, m_addr.toStringA(hostname));
59 ssh_options_set(m_session, SSH_OPTIONS_PORT, &m_port);
60 long timeout = 2;
61 ssh_options_set(m_session, SSH_OPTIONS_TIMEOUT, &timeout);
62#ifdef UNICODE
63 char mbuser[256];
64 WideCharToMultiByte(CP_UTF8, 0, user, -1, mbuser, 256, NULL, NULL);
65 ssh_options_set(m_session, SSH_OPTIONS_USER, mbuser);
66#else
67 ssh_options_set(m_session, SSH_OPTIONS_USER, user);
68#endif
69
70 if (ssh_connect(m_session) == SSH_OK)
71 {
72#ifdef UNICODE
73 char mbpassword[256];
74 WideCharToMultiByte(CP_UTF8, 0, password, -1, mbpassword, 256, NULL, NULL);
75 if (ssh_userauth_password(m_session, NULL, mbpassword) == SSH_AUTH_SUCCESS)
76#else
77 if (ssh_userauth_password(m_session, NULL, password) == SSH_AUTH_SUCCESS)
78#endif
79 {
80 success = true;
81 }
82 else
83 {
84 nxlog_debug(6, _T("SSH: login as %s on %s:%d failed"), user, (const TCHAR *)m_addr.toString(), m_port);
85 }
86 }
87 else
88 {
89 nxlog_debug(6, _T("SSH: connect to %s:%d failed"), (const TCHAR *)m_addr.toString(), m_port);
90 }
91
92 if (!success)
93 {
94 if (ssh_is_connected(m_session))
95 ssh_disconnect(m_session);
96 ssh_free(m_session);
97 m_session = NULL;
98 }
99 return success;
100}
101
102/**
103 * Disconnect from server
104 */
105void SSHSession::disconnect()
106{
107 if (m_session == NULL)
108 return;
109
110 if (ssh_is_connected(m_session))
111 ssh_disconnect(m_session);
112 ssh_free(m_session);
113 m_session = NULL;
114}
115
116/**
117 * Execute command and capture output
118 */
119StringList *SSHSession::execute(const TCHAR *command)
120{
121 if ((m_session == NULL) || !ssh_is_connected(m_session))
122 return NULL;
123
124 ssh_channel channel = ssh_channel_new(m_session);
125 if (channel == NULL)
126 return NULL;
127
128 StringList *output = NULL;
129 if (ssh_channel_open_session(channel) == SSH_OK)
130 {
131#ifdef UNICODE
132 char *mbcmd = UTF8StringFromWideString(command);
133 if (ssh_channel_request_exec(channel, mbcmd) == SSH_OK)
134#else
135 if (ssh_channel_request_exec(channel, command) == SSH_OK)
136#endif
137 {
138 output = new StringList();
139 char buffer[8192];
140 int nbytes = ssh_channel_read(channel, buffer, sizeof(buffer) - 1, 0);
141 int offset = 0;
142 while(nbytes > 0)
143 {
144 buffer[nbytes + offset] = 0;
145 char *curr = buffer;
146 char *eol = strchr(curr, '\n');
147 while(eol != NULL)
148 {
149 *eol = 0;
241541f4
VK
150 char *cr = strchr(curr, '\r');
151 if (cr != NULL)
152 *cr = 0;
12acf3d3
VK
153 output->addMBString(curr);
154 curr = eol + 1;
155 eol = strchr(curr, '\n');
156 }
157 offset = strlen(curr);
158 if (offset > 0)
159 memmove(buffer, curr, offset);
160 nbytes = ssh_channel_read(channel, &buffer[offset], sizeof(buffer) - offset - 1, 0);
161 }
162 if (nbytes == 0)
163 {
164 if (offset > 0)
165 {
166 buffer[offset] = 0;
241541f4
VK
167 char *cr = strchr(buffer, '\r');
168 if (cr != NULL)
169 *cr = 0;
12acf3d3
VK
170 output->addMBString(buffer);
171 }
172 ssh_channel_send_eof(channel);
173 }
174 else
175 {
176 delete_and_null(output);
177 }
178 }
179 else
180 {
181 nxlog_debug(6, _T("SSH: command \"%s\" execution on %s:%d failed"), command, (const TCHAR *)m_addr.toString(), m_port);
182 }
183 ssh_channel_close(channel);
184 }
185 else
186 {
187 nxlog_debug(6, _T("SSH: cannot open channel on %s:%d"), (const TCHAR *)m_addr.toString(), m_port);
188 }
189 ssh_channel_free(channel);
190 return output;
191}