GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/sshclients.c
Date: 2025-09-14 13:10:38
Exec Total Coverage
Lines: 285 739 38.6%
Functions: 20 42 47.6%
Branches: 92 421 21.9%

Line Branch Exec Source
1 /* GATE PROJECT LICENSE:
2 +----------------------------------------------------------------------------+
3 | Copyright(c) 2018-2025, Stefan Meislinger <sm@opengate.at> |
4 | All rights reserved. |
5 | |
6 | Redistribution and use in source and binary forms, with or without |
7 | modification, are permitted provided that the following conditions are met:|
8 | |
9 | 1. Redistributions of source code must retain the above copyright notice, |
10 | this list of conditions and the following disclaimer. |
11 | 2. Redistributions in binary form must reproduce the above copyright |
12 | notice, this list of conditions and the following disclaimer in the |
13 | documentation and/or other materials provided with the distribution. |
14 | |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"|
16 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 | ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
19 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
20 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
21 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
22 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
23 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
24 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
25 | THE POSSIBILITY OF SUCH DAMAGE. |
26 +----------------------------------------------------------------------------+
27 */
28 #include "gate/net/sshclients.h"
29 #include "gate/net/nameresolvers.h"
30 #include "gate/results.h"
31 #include "gate/debugging.h"
32
33 #if defined(GATE_EXTLIB_LIBSSH2)
34 # define GATE_NET_SSHCLIENTS_LIBSSH2_IMPL 1
35
36 # if !defined(GATE_NET_LIBSSH2_STATIC) && defined(GATE_SYS_WIN) && !defined(GATE_SYS_WINSTORE)
37 # define GATE_NET_LIBSSH2_STATIC 1
38 # endif
39
40 #else
41 # define GATE_NET_SSHCLIENTS_NO_IMPL 1
42 #endif
43
44
45 #if defined(GATE_NET_SSHCLIENTS_LIBSSH2_IMPL)
46
47 #if defined(_WINDLL)
48 # undef _WINDLL
49 #endif
50
51 #include <libssh2.h>
52 #include <libssh2_sftp.h>
53 #include <stdlib.h>
54
55 #include "gate/libraries.h"
56 #include "gate/platforms.h"
57 #include "gate/net/sockets.h"
58 #include "gate/net/sslsessions.h"
59
60 # if defined(GATE_SYS_WINCE)
61 # pragma comment(lib, "ws2.lib")
62 # endif
63
64
65 #define GATE_SSH2_SESSION_TIMEOUT_DEFAULT 15000
66
67 typedef struct libssh2_functions
68 {
69 int (*ssh2_init) (int flags);
70 void (*ssh2_exit) (void);
71 void (*ssh2_free) (LIBSSH2_SESSION* session, void* ptr);
72 char* (*ssh2_userauth_list) (LIBSSH2_SESSION* session, const char* user, unsigned int user_len);
73 int (*ssh2_userauth_password_ex)(LIBSSH2_SESSION* session, const char* username, unsigned int username_len, const char* password, unsigned int password_len, LIBSSH2_PASSWD_CHANGEREQ_FUNC((*passwd_change_cb)));
74 int (*ssh2_userauth_keyboard_interactive_ex)(LIBSSH2_SESSION* session, const char* user, unsigned int user_len, LIBSSH2_USERAUTH_KBDINT_RESPONSE_FUNC((*response_callback)));
75 int (*ssh2_userauth_publickey_frommemory)(LIBSSH2_SESSION* session, const char* user, size_t user_len, const char* publickeydata, size_t publickeydata_len, const char* privatekeydata, size_t privatekeydata_len, const char* passphrase);
76 int (*ssh2_userauth_publickey_fromfile_ex)(LIBSSH2_SESSION* session, const char* user, unsigned int user_len, const char* publickey, const char* privatekey, const char* passphrase);
77 int (*ssh2_session_disconnect_ex)(LIBSSH2_SESSION* session, int reason, const char* description, const char* lang);
78 LIBSSH2_SESSION* (*ssh2_session_init_ex) (LIBSSH2_ALLOC_FUNC((*my_alloc)), LIBSSH2_FREE_FUNC((*my_free)), LIBSSH2_REALLOC_FUNC((*my_realloc)), void* abstract);
79 int (*ssh2_session_free) (LIBSSH2_SESSION* session);
80 /* int (*ssh2_session_startup) (LIBSSH2_SESSION* session, int sock); */
81 int (*ssh2_session_handshake) (LIBSSH2_SESSION* session, libssh2_socket_t sock);
82 void (*ssh2_session_set_blocking)(LIBSSH2_SESSION* session, int blocking);
83 int (*ssh2_session_last_errno) (LIBSSH2_SESSION* session);
84 int (*ssh2_session_last_error) (LIBSSH2_SESSION* session, char** errmsg, int* errmsg_len, int want_buf);
85 void (*ssh2_session_set_timeout) (LIBSSH2_SESSION* session, long timeout);
86
87 int (*ssh2_sftp_close_handle) (LIBSSH2_SFTP_HANDLE* hnd);
88 int (*ssh2_sftp_fstat_ex) (LIBSSH2_SFTP_HANDLE* hnd, LIBSSH2_SFTP_ATTRIBUTES* attrs, int setstat);
89 LIBSSH2_SFTP* (*ssh2_sftp_init) (LIBSSH2_SESSION* session);
90 unsigned long (*ssh2_sftp_last_error) (LIBSSH2_SFTP* sftp);
91 int (*ssh2_sftp_mkdir_ex) (LIBSSH2_SFTP* sftp, const char* path, unsigned int path_len, long mode);
92 LIBSSH2_SFTP_HANDLE*(*ssh2_sftp_open_ex) (LIBSSH2_SFTP* sftp, const char* filename, unsigned int filename_len, unsigned long flags, long mode, int open_type);
93 ssize_t (*ssh2_sftp_read) (LIBSSH2_SFTP_HANDLE* hnd, char* buffer, size_t buffer_maxlen);
94 int (*ssh2_sftp_readdir_ex) (LIBSSH2_SFTP_HANDLE* hnd, char* buffer, size_t buffer_maxlen, char* longentry, size_t longentry_maxlen, LIBSSH2_SFTP_ATTRIBUTES* attrs);
95 int (*ssh2_sftp_rename_ex) (LIBSSH2_SFTP* sftp, const char* source_filename, unsigned int source_filename_len, const char* dest_filename, unsigned int dest_filename_len, long flags);
96 int (*ssh2_sftp_rmdir_ex) (LIBSSH2_SFTP* sftp, const char* path, unsigned int path_len);
97 void (*ssh2_sftp_seek64) (LIBSSH2_SFTP_HANDLE* handle, libssh2_uint64_t offset);
98 int (*ssh2_sftp_stat_ex) (LIBSSH2_SFTP* sftp, const char* path, unsigned int path_len, int stat_type, LIBSSH2_SFTP_ATTRIBUTES* attrs);
99 int (*ssh2_sftp_shutdown) (LIBSSH2_SFTP* sftp);
100 int (*ssh2_sftp_statvfs) (LIBSSH2_SFTP* sftp, const char* path, size_t path_len, LIBSSH2_SFTP_STATVFS* st);
101 int (*ssh2_sftp_symlink_ex) (LIBSSH2_SFTP* sftp, const char* path, unsigned int path_len, char* target, unsigned int target_len, int link_type);
102 size_t (*ssh2_sftp_tell) (LIBSSH2_SFTP_HANDLE* handle);
103 libssh2_uint64_t (*ssh2_sftp_tell64) (LIBSSH2_SFTP_HANDLE* handle);
104 int (*ssh2_sftp_unlink_ex) (LIBSSH2_SFTP* sftp, const char* filename, unsigned int filename_len);
105 ssize_t (*ssh2_sftp_write) (LIBSSH2_SFTP_HANDLE* hnd, const char* buffer, size_t count);
106
107 LIBSSH2_CHANNEL* (*ssh2_channel_open_ex) (LIBSSH2_SESSION* session, const char* channel_type, unsigned int channel_type_len, unsigned int window_size, unsigned int packet_size, const char* message, unsigned int message_len);
108 int (*ssh2_channel_close) (LIBSSH2_CHANNEL* channel);
109 int (*ssh2_channel_free) (LIBSSH2_CHANNEL* channel);
110 ssize_t (*ssh2_channel_read_ex) (LIBSSH2_CHANNEL* channel, int stream_id, char* buf, size_t buflen);
111 ssize_t (*ssh2_channel_write_ex) (LIBSSH2_CHANNEL* channel, int stream_id, char const* buf, size_t buflen);
112 int (*ssh2_channel_process_startup) (LIBSSH2_CHANNEL* channel, const char* request, unsigned int request_len, const char* message, unsigned int message_len);
113 int (*ssh2_channel_eof) (LIBSSH2_CHANNEL* channel);
114 int (*ssh2_channel_send_eof) (LIBSSH2_CHANNEL* channel);
115 int (*ssh2_channel_wait_eof) (LIBSSH2_CHANNEL* channel);
116 int (*ssh2_channel_setenv_ex) (LIBSSH2_CHANNEL* channel, char const* varname, unsigned int varname_len, const char* value, unsigned int value_len);
117 int (*ssh2_channel_get_exit_signal) (LIBSSH2_CHANNEL* channel, char** exitsignal, size_t* exitsignal_len, char** errmsg, size_t* errmsg_len, char** langtag, size_t* langtag_len);
118 int (*ssh2_channel_get_exit_status) (LIBSSH2_CHANNEL* channel);
119 void (*ssh2_channel_set_blocking) (LIBSSH2_CHANNEL* channel, int blocking);
120 } libssh2_functions_t;
121
122 static libssh2_functions_t lib;
123 static volatile gate_bool_t lib_loaded;
124
125 1 static gate_bool_t load_libssh2()
126 {
127 gate_result_t result;
128 1 result = gate_ssl_init(true);
129
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(result))
130 {
131 return false;
132 }
133
134 #if defined(GATE_NET_LIBSSH2_STATIC)
135
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (!lib_loaded)
136 {
137 1 lib.ssh2_init = &libssh2_init;
138 1 lib.ssh2_exit = &libssh2_exit;
139 1 lib.ssh2_free = &libssh2_free;
140 1 lib.ssh2_userauth_list = &libssh2_userauth_list;
141 1 lib.ssh2_userauth_password_ex = &libssh2_userauth_password_ex;
142 1 lib.ssh2_userauth_keyboard_interactive_ex = &libssh2_userauth_keyboard_interactive_ex;
143 1 lib.ssh2_userauth_publickey_frommemory = &libssh2_userauth_publickey_frommemory;
144 1 lib.ssh2_userauth_publickey_fromfile_ex = &libssh2_userauth_publickey_fromfile_ex;
145 1 lib.ssh2_session_set_blocking = &libssh2_session_set_blocking;
146 1 lib.ssh2_session_disconnect_ex = &libssh2_session_disconnect_ex;
147 1 lib.ssh2_session_free = &libssh2_session_free;
148 1 lib.ssh2_session_init_ex = &libssh2_session_init_ex;
149 /* lib.ssh2_session_startup = &libssh2_session_startup; */
150 1 lib.ssh2_session_handshake = &libssh2_session_handshake;
151 1 lib.ssh2_session_last_errno = &libssh2_session_last_errno;
152 1 lib.ssh2_session_last_error = &libssh2_session_last_error;
153 1 lib.ssh2_session_set_timeout = &libssh2_session_set_timeout;
154 1 lib.ssh2_sftp_close_handle = &libssh2_sftp_close_handle;
155
156 1 lib.ssh2_sftp_fstat_ex = &libssh2_sftp_fstat_ex;
157 1 lib.ssh2_sftp_init = &libssh2_sftp_init;
158 1 lib.ssh2_sftp_last_error = &libssh2_sftp_last_error;
159 1 lib.ssh2_sftp_mkdir_ex = &libssh2_sftp_mkdir_ex;
160 1 lib.ssh2_sftp_open_ex = &libssh2_sftp_open_ex;
161 1 lib.ssh2_sftp_read = &libssh2_sftp_read;
162 1 lib.ssh2_sftp_readdir_ex = &libssh2_sftp_readdir_ex;
163 1 lib.ssh2_sftp_rename_ex = &libssh2_sftp_rename_ex;
164 1 lib.ssh2_sftp_rmdir_ex = &libssh2_sftp_rmdir_ex;
165 1 lib.ssh2_sftp_seek64 = &libssh2_sftp_seek64;
166 1 lib.ssh2_sftp_shutdown = &libssh2_sftp_shutdown;
167 1 lib.ssh2_sftp_stat_ex = &libssh2_sftp_stat_ex;
168 1 lib.ssh2_sftp_statvfs = &libssh2_sftp_statvfs;
169 1 lib.ssh2_sftp_symlink_ex = &libssh2_sftp_symlink_ex;
170 1 lib.ssh2_sftp_tell = &libssh2_sftp_tell;
171 1 lib.ssh2_sftp_tell64 = &libssh2_sftp_tell64;
172 1 lib.ssh2_sftp_unlink_ex = &libssh2_sftp_unlink_ex;
173 1 lib.ssh2_sftp_write = &libssh2_sftp_write;
174
175 1 lib.ssh2_channel_open_ex = &libssh2_channel_open_ex;
176 1 lib.ssh2_channel_close = &libssh2_channel_close;
177 1 lib.ssh2_channel_free = &libssh2_channel_free;
178 1 lib.ssh2_channel_read_ex = &libssh2_channel_read_ex;
179 1 lib.ssh2_channel_write_ex = &libssh2_channel_write_ex;
180 1 lib.ssh2_channel_process_startup = &libssh2_channel_process_startup;
181 1 lib.ssh2_channel_eof = &libssh2_channel_eof;
182 1 lib.ssh2_channel_send_eof = &libssh2_channel_send_eof;
183 1 lib.ssh2_channel_wait_eof = &libssh2_channel_wait_eof;
184 1 lib.ssh2_channel_setenv_ex = &libssh2_channel_setenv_ex;
185 1 lib.ssh2_channel_get_exit_signal = &libssh2_channel_get_exit_signal;
186 1 lib.ssh2_channel_get_exit_status = &libssh2_channel_get_exit_status;
187 1 lib.ssh2_channel_set_blocking = &libssh2_channel_set_blocking;
188
189 1 lib_loaded = true;
190 }
191 #else
192 gate_library_t lib_ssh2 = NULL;
193 static gate_string_t libssh2_name =
194 #if defined(GATE_SYS_DARWIN)
195 GATE_STRING_INIT_STATIC("libssh2.dylib")
196 #elif defined(GATE_SYS_POSIX)
197 GATE_STRING_INIT_STATIC("libssh2.so")
198 #else
199 GATE_STRING_INIT_STATIC("libssh2")
200 #endif
201 ;
202
203 if (!lib_loaded)
204 {
205 do
206 {
207 result = gate_library_open(&libssh2_name, &lib_ssh2, 0);
208 GATE_BREAK_IF_FAILED(result);
209
210 result |= gate_library_get_function_name(lib_ssh2, "libssh2_init", &lib.ssh2_init);
211 result |= gate_library_get_function_name(lib_ssh2, "libssh2_exit", &lib.ssh2_exit);
212 result |= gate_library_get_function_name(lib_ssh2, "libssh2_free", &lib.ssh2_free);
213 result |= gate_library_get_function_name(lib_ssh2, "libssh2_userauth_list", &lib.ssh2_userauth_list);
214 result |= gate_library_get_function_name(lib_ssh2, "libssh2_userauth_password_ex", &lib.ssh2_userauth_password_ex);
215 result |= gate_library_get_function_name(lib_ssh2, "libssh2_userauth_keyboard_interactive_ex", &lib.ssh2_userauth_keyboard_interactive_ex);
216 result |= gate_library_get_function_name(lib_ssh2, "libssh2_userauth_publickey_frommemory", &lib.ssh2_userauth_publickey_frommemory);
217 result |= gate_library_get_function_name(lib_ssh2, "libssh2_userauth_publickey_fromfile_ex", &lib.ssh2_userauth_publickey_fromfile_ex);
218 result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_set_blocking", &lib.ssh2_session_set_blocking);
219 result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_disconnect_ex", &lib.ssh2_session_disconnect_ex);
220 result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_free", &lib.ssh2_session_free);
221 result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_init_ex", &lib.ssh2_session_init_ex);
222 /* result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_startup", &lib.ssh2_session_startup); */
223 result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_handshake", &lib.ssh2_session_handshake);
224 result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_last_errno", &lib.ssh2_session_last_errno);
225 result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_last_error", &lib.ssh2_session_last_error);
226 result |= gate_library_get_function_name(lib_ssh2, "libssh2_session_set_timeout", &lib.ssh2_session_set_timeout);
227
228 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_close_handle", &lib.ssh2_sftp_close_handle);
229 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_fstat_ex", &lib.ssh2_sftp_fstat_ex);
230 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_init", &lib.ssh2_sftp_init);
231 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_last_error", &lib.ssh2_sftp_last_error);
232 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_mkdir_ex", &lib.ssh2_sftp_mkdir_ex);
233 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_open_ex", &lib.ssh2_sftp_open_ex);
234 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_read", &lib.ssh2_sftp_read);
235 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_readdir_ex", &lib.ssh2_sftp_readdir_ex);
236 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_rename_ex", &lib.ssh2_sftp_rename_ex);
237 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_rmdir_ex", &lib.ssh2_sftp_rmdir_ex);
238 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_seek64", &lib.ssh2_sftp_seek64);
239 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_shutdown", &lib.ssh2_sftp_shutdown);
240 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_stat_ex", &lib.ssh2_sftp_stat_ex);
241 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_statvfs", &lib.ssh2_sftp_statvfs);
242 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_symlink_ex", &lib.ssh2_sftp_symlink_ex);
243 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_tell", &lib.ssh2_sftp_tell);
244 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_tell64", &lib.ssh2_sftp_tell64);
245 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_unlink_ex", &lib.ssh2_sftp_unlink_ex);
246 result |= gate_library_get_function_name(lib_ssh2, "libssh2_sftp_write", &lib.ssh2_sftp_write);
247
248 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_open_ex", &lib.ssh2_channel_open_ex);
249 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_close", &lib.ssh2_channel_close);
250 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_free", &lib.ssh2_channel_free);
251 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_read_ex", &lib.ssh2_channel_read_ex);
252 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_write_ex", &lib.ssh2_channel_write_ex);
253 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_process_startup", &lib.ssh2_channel_process_startup);
254
255 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_eof", &lib.ssh2_channel_eof);
256 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_send_eof", &lib.ssh2_channel_send_eof);
257 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_wait_eof", &lib.ssh2_channel_wait_eof);
258 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_setenv_ex", &lib.ssh2_channel_setenv_ex);
259 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_get_exit_signal", &lib.ssh2_channel_get_exit_signal);
260 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_get_exit_status", &lib.ssh2_channel_get_exit_status);
261 result |= gate_library_get_function_name(lib_ssh2, "libssh2_channel_set_blocking", &lib.ssh2_channel_set_blocking);
262
263 GATE_BREAK_IF_FAILED(result);
264
265 /* success case: */
266 lib_ssh2 = NULL; /* do not unload library */
267 lib_loaded = true;
268 } while (0);
269
270 if (lib_ssh2)
271 {
272 gate_library_close(lib_ssh2);
273 }
274 }
275 #endif
276 1 return lib_loaded;
277 }
278
279
280 95 static void* gate_libssh2_alloc(size_t count, void** ptr_abstract)
281 {
282 (void)ptr_abstract;
283 95 return gate_mem_alloc(count);
284 }
285
286 95 static void gate_libssh2_free(void* ptr, void** ptr_abstract)
287 {
288 (void)ptr_abstract;
289
1/2
✓ Branch 0 taken 95 times.
✗ Branch 1 not taken.
95 if (ptr)
290 {
291 95 gate_mem_dealloc(ptr);
292 }
293 95 }
294
295 static void* gate_libssh2_realloc(void* ptr, size_t count, void** ptr_abstract)
296 {
297 (void)ptr_abstract;
298 return gate_mem_realloc(ptr, count);
299 }
300
301 1 gate_result_t gate_sshclient_create(gate_sshclient_t* client, gate_string_t const* server, gate_uint16_t port)
302 {
303 gate_result_t ret;
304 int errcode;
305 1 gate_bool_t init_ok = false;
306 1 LIBSSH2_SESSION* session = NULL;
307 1 gate_string_t host = GATE_STRING_INIT_EMPTY;
308
309 do
310 {
311 1 gate_mem_clear(client, sizeof(gate_sshclient_t));
312
313
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
1 if (!load_libssh2())
314 {
315 GATE_DEBUG_TRACE("load_libssh2() failed");
316 ret = GATE_RESULT_NOTAVAILABLE;
317 break;
318 }
319
320 1 ret = gate_platform_lock();
321
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
322 do
323 {
324 1 errcode = lib.ssh2_init(0);
325
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (errcode != 0)
326 {
327 GATE_DEBUG_TRACE("ssh2_init() failed");
328 ret = GATE_RESULT_FAILED;
329 break;
330 }
331 } while (0);
332 1 gate_platform_unlock();
333
334
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
335
336 1 ret = gate_socket_parse_address(server, &host, &client->port, &client->socket_family);
337
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
338
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (port)
339 {
340 1 client->port = port;
341 }
342
343
2/4
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
1 if (!gate_net_is_ipv4_address(&host) && !gate_net_is_ipv6_address(&host))
344 {
345 gate_socket_endpoint_t ep;
346 1 gate_size_t ep_count = 1;
347 1 gate_result_t result = gate_net_resolve_host(&host, GATE_SOCKET_FAMILY_INET4, &ep, &ep_count);
348 1 gate_string_t newhost = GATE_STRING_INIT_EMPTY;
349
2/4
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
1 if (GATE_FAILED(result) || (ep_count < 1))
350 {
351 ret = GATE_RESULT_BADADDRESS;
352 break;
353 }
354 1 result = gate_socket_print_endpoint(&ep, &newhost);
355
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(result);
356 1 gate_string_release(&host);
357 1 gate_mem_copy(&host, &newhost, sizeof(gate_string_t));
358 }
359
360 1 gate_string_to_buffer(&host, client->server, sizeof(client->server));
361
362 1 init_ok = true;
363
364 1 session = lib.ssh2_session_init_ex(&gate_libssh2_alloc, &gate_libssh2_free, &gate_libssh2_realloc, client);
365
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!session)
366 {
367 GATE_DEBUG_TRACE("ssh2_session_init_ex() failed");
368 ret = GATE_RESULT_OUTOFMEMORY;
369 break;
370 }
371
372 1 lib.ssh2_session_set_blocking(session, 1);
373 1 lib.ssh2_session_set_timeout(session, GATE_SSH2_SESSION_TIMEOUT_DEFAULT);
374
375 /* success state reached */
376 1 client->handles[0] = session;
377 1 client->handles[1] = (void*)GATE_SOCKET_INVALID; /* no socket connected */
378 1 ret = GATE_RESULT_OK;
379 } while (0);
380
381 1 gate_string_release(&host);
382
383 1 return ret;
384 }
385
386 static gate_string_t const authlist_entry_password = GATE_STRING_INIT_STATIC("password");
387 static gate_string_t const authlist_entry_keyboard = GATE_STRING_INIT_STATIC("keyboard-interactive");
388
389 static void gate_sshclient_kbd_callback(
390 const char* name, int name_len,
391 const char* instruction, int instruction_len,
392 int num_prompts,
393 const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts,
394 LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses,
395 void** abstract)
396 {
397 gate_sshclient_t** pptr_client = (gate_sshclient_t**)abstract;
398 gate_string_t const* pass = (pptr_client && *pptr_client) ? (gate_string_t const*)((*pptr_client)->handles[2]) : NULL;
399 char* buffer = NULL;
400 (void)name;
401 (void)name_len;
402 (void)instruction;
403 (void)instruction_len;
404 (void)prompts;
405
406 if ((num_prompts == 1) && (pass != NULL))
407 {
408 gate_size_t pass_length = gate_string_length(pass);
409
410 buffer = (char*)malloc(pass_length + 3);
411 if (buffer)
412 {
413 gate_size_t len_copied = gate_string_to_buffer(pass, buffer, pass_length + 1);
414
415 buffer[len_copied] = 0;
416 responses->text = buffer;
417 responses->length = (unsigned int)len_copied;
418 }
419 }
420 } /* kbd_callback */
421
422 #define GATE_DEBUG_TRACE_SSH2_ERROR(session_ptr, origin_msg) do { \
423 char* ssh2_msg = NULL; \
424 int ssh2_msg_len = 0; \
425 int const ssh2_errno = lib.ssh2_session_last_error(session_ptr, &ssh2_msg, &ssh2_msg_len, 0); \
426 GATE_DEBUG_TRACE(origin_msg); \
427 GATE_DEBUG_TRACE_MSG_VALUE(ssh2_msg, ssh2_errno); \
428 } while(0)
429
430 1 static gate_result_t gate_sshclient_init_connection(gate_sshclient_t* client)
431 {
432 1 gate_result_t ret = GATE_RESULT_FAILED;
433 1 gate_socket_t socket_handle = GATE_SOCKET_INVALID;
434 gate_socket_endpoint_t ep;
435 1 gate_string_t host = GATE_STRING_INIT_EMPTY;
436 1 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
437 int ssh2_result;
438
439 do
440 {
441
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!session)
442 {
443 GATE_DEBUG_TRACE("Invalid state: no client session created");
444 ret = GATE_RESULT_INVALIDSTATE;
445 break;
446 }
447
448
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (client->handles[1] != (void*)GATE_SOCKET_INVALID)
449 {
450 GATE_DEBUG_TRACE("Invalid state: socket already opened, cannot connect");
451 ret = GATE_RESULT_INVALIDSTATE;
452 break;
453 }
454
455 1 ret = gate_socket_create_ex(client->socket_family, GATE_SOCKET_MSGTYPE_STREAM, GATE_SOCKET_PROTOCOL_TCP, &socket_handle);
456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
457
458 1 gate_mem_clear(&ep, sizeof(ep));
459
460
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (client->socket_family)
461 {
462 1 case GATE_SOCKET_FAMILY_INET4:
463 {
464 1 ep.ip4.family = GATE_SOCKET_FAMILY_INET4;
465 1 ep.ip4.port = client->port;
466
467 1 gate_string_create_static(&host, client->server);
468 1 ret = gate_socket_parse_ip4(&host, &ep.ip4.address);
469 1 break;
470 }
471 case GATE_SOCKET_FAMILY_INET6:
472 {
473 ep.ip6.family = GATE_SOCKET_FAMILY_INET6;
474 ep.ip6.port = client->port;
475 ep.ip6.scope = 0;
476
477 gate_string_create_static(&host, client->server);
478 ret = gate_socket_parse_ip6(&host, &ep.ip6.address);
479 break;
480 }
481 default:
482 {
483 ret = GATE_RESULT_NOTSUPPORTED;
484 break;
485 }
486 }
487
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
488
489 1 gate_socket_set(socket_handle, GATE_SOCKET_OPTION_BLOCKING, 1);
490 1 gate_socket_set(socket_handle, GATE_SOCKET_OPTION_RECEIVETIMEOUT, GATE_SSH2_SESSION_TIMEOUT_DEFAULT);
491 1 gate_socket_set(socket_handle, GATE_SOCKET_OPTION_SENDTIMEOUT, GATE_SSH2_SESSION_TIMEOUT_DEFAULT);
492
493 1 ret = gate_socket_connect(socket_handle, &ep);
494
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
495 1 GATE_DEBUG_TRACE_VALUE((int)socket_handle);
496
497 1 lib.ssh2_session_set_blocking(session, 1);
498 1 lib.ssh2_session_set_timeout(session, GATE_SSH2_SESSION_TIMEOUT_DEFAULT);
499
500 /* ssh2_result = lib.ssh2_session_startup(session, (int)socket_handle); */
501 1 ssh2_result = lib.ssh2_session_handshake(session, (libssh2_socket_t)socket_handle);
502
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ssh2_result != 0)
503 {
504 GATE_DEBUG_TRACE_SSH2_ERROR(session, "ssh2_session_handshake() failed");
505 ret = GATE_RESULT_FAILED;
506 break;
507 }
508
509 /* success state */
510 1 client->handles[1] = (void*)socket_handle;
511 1 socket_handle = GATE_SOCKET_INVALID;
512 1 ret = GATE_RESULT_OK;
513 } while (0);
514
515
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (socket_handle != GATE_SOCKET_INVALID)
516 {
517 gate_socket_close(socket_handle);
518 }
519
520 1 gate_string_release(&host);
521
522
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(ret, "gate_sshclient_init_connection() failed");
523 1 return ret;
524 }
525
526
527 1 static gate_result_t gate_sshclient_authenticate(gate_sshclient_t* client, gate_string_t const* user, gate_string_t const* pass)
528 {
529 1 gate_result_t ret = GATE_RESULT_FAILED;
530 1 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
531 char* userauthlist;
532 1 gate_string_t lst = GATE_STRING_INIT_EMPTY;
533 int ssh2_result;
534
535 do
536 {
537 1 userauthlist = lib.ssh2_userauth_list(session, user->str, (unsigned)user->length);
538
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (userauthlist)
539 {
540 1 gate_string_create_static(&lst, userauthlist);
541 }
542
543
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
1 if (gate_string_contains(&lst, &authlist_entry_password))
544 {
545 /* direct password usage */
546 4 ssh2_result = lib.ssh2_userauth_password_ex(session,
547 2 user->str, (unsigned)user->length,
548 1 pass->str, (unsigned)pass->length, NULL);
549
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ssh2_result != 0)
550 {
551 ret = GATE_RESULT_ACCESSDENIED;
552 break;
553 }
554 1 ret = GATE_RESULT_OK;
555 }
556 else if (gate_string_contains(&lst, &authlist_entry_keyboard))
557 {
558 /* user keyboard simulation to inject password */
559 client->handles[2] = (void*)pass;
560 ssh2_result = lib.ssh2_userauth_keyboard_interactive_ex(session,
561 user->str, (unsigned)user->length,
562 &gate_sshclient_kbd_callback);
563 client->handles[2] = NULL;
564 if (ssh2_result != 0)
565 {
566 ret = GATE_RESULT_ACCESSDENIED;
567 break;
568 }
569 ret = GATE_RESULT_OK;
570 }
571 else
572 {
573 ret = GATE_RESULT_NOTSUPPORTED;
574 }
575
576 } while (0);
577
578 1 gate_string_release(&lst);
579
580
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(ret, "gate_sshclient_authenticate() failed");
581 1 return ret;
582 }
583
584 1 gate_result_t gate_sshclient_connect(gate_sshclient_t* client,
585 gate_string_t const* user, gate_string_t const* password,
586 gate_enumint_t flags)
587 {
588 1 gate_result_t ret = GATE_RESULT_FAILED;
589 1 gate_socket_t socket_handle = GATE_SOCKET_INVALID;
590
591 do
592 {
593 1 ret = gate_sshclient_init_connection(client);
594
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
595
596 1 ret = gate_sshclient_authenticate(client, user, password);
597
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
598 {
599 /* authentication failed -> release socket */
600 socket_handle = (gate_socket_t)client->handles[1];
601 client->handles[1] = (void*)GATE_SOCKET_INVALID;
602 gate_socket_close(socket_handle);
603 break;
604 }
605
606 /* success state */
607 1 ret = GATE_RESULT_OK;
608 } while (0);
609
610
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(ret, "gate_sshclient_connect() failed");
611 1 return ret;
612 }
613
614
615 gate_result_t gate_sshclient_connect_keys(
616 gate_sshclient_t* client, gate_string_t const* user,
617 gate_string_t const* pubkey, gate_string_t const* privkey, gate_string_t const* passphrase,
618 gate_enumint_t flags)
619 {
620 gate_result_t ret = GATE_RESULT_FAILED;
621 gate_socket_t socket_handle = GATE_SOCKET_INVALID;
622
623 ret = gate_sshclient_init_connection(client);
624 GATE_RETURN_IF_FAILED(ret);
625
626 do
627 {
628 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
629 char const* str_user = gate_string_ptr(user, 0);
630 gate_size_t len_user = gate_string_length(user);
631 char const* str_pubkey = gate_string_ptr(pubkey, 0);
632 gate_size_t len_pubkey = gate_string_length(pubkey);
633 char const* str_privkey = gate_string_ptr(privkey, 0);
634 gate_size_t len_privkey = gate_string_length(privkey);
635 char pass[1024];
636 char const* ptr_passphrase = NULL;
637 int ssh_error;
638
639 if (gate_string_to_buffer(passphrase, pass, sizeof(pass)) > 0)
640 {
641 ptr_passphrase = &pass[0];
642 }
643
644 ssh_error = lib.ssh2_userauth_publickey_frommemory(session,
645 str_user, len_user,
646 str_pubkey, len_pubkey,
647 str_privkey, len_privkey,
648 ptr_passphrase);
649
650 if (ssh_error != 0)
651 {
652 /* authentication failed -> release socket */
653 socket_handle = (gate_socket_t)client->handles[1];
654 client->handles[1] = (void*)GATE_SOCKET_INVALID;
655 gate_socket_close(socket_handle);
656 switch (ssh_error)
657 {
658 case LIBSSH2_ERROR_ALLOC: ret = GATE_RESULT_OUTOFMEMORY;
659 case LIBSSH2_ERROR_SOCKET_SEND: ret = GATE_RESULT_INVALIDOUTPUT;
660 case LIBSSH2_ERROR_SOCKET_TIMEOUT: ret = GATE_RESULT_TIMEOUT;
661 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: ret = GATE_RESULT_INVALIDINPUT;
662 case LIBSSH2_ERROR_AUTHENTICATION_FAILED: ret = GATE_RESULT_ACCESSDENIED;
663 default: ret = GATE_RESULT_FAILED;
664 }
665 break;
666 }
667
668 /* success state */
669 ret = GATE_RESULT_OK;
670 } while (0);
671
672 GATE_DEBUG_TRACE_FAILED(ret, "gate_sshclient_connect_keys() failed");
673 return ret;
674 }
675
676
677 2 gate_result_t gate_sshclient_disconnect(gate_sshclient_t* client)
678 {
679 2 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
680 2 gate_socket_t socket_handle = (gate_socket_t)client->handles[1];
681
682
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (session)
683 {
684 2 lib.ssh2_session_disconnect_ex(session, SSH_DISCONNECT_BY_APPLICATION, "", "");
685 }
686
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (socket_handle != GATE_SOCKET_INVALID)
687 {
688 1 gate_socket_close(socket_handle);
689 1 client->handles[1] = (void*)GATE_SOCKET_INVALID;
690 }
691 2 return GATE_RESULT_OK;
692 }
693
694 1 gate_result_t gate_sshclient_open_sftp(gate_sshclient_t* client, gate_sshclient_sftp_t* sftp)
695 {
696
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SESSION* session = client ? (LIBSSH2_SESSION*)client->handles[0] : NULL;
697 LIBSSH2_SFTP* ptr_sftp;
698
699
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!session)
700 {
701 GATE_DEBUG_TRACE("missing client session");
702 return GATE_RESULT_NULLPOINTER;
703
704 }
705
706 1 ptr_sftp = lib.ssh2_sftp_init(session);
707
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_sftp)
708 {
709 GATE_DEBUG_TRACE("ssh2_sftp_init() failed");
710 return GATE_RESULT_FAILED;
711 }
712
713
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sftp)
714 {
715 1 *sftp = (gate_sshclient_sftp_t)ptr_sftp;
716 }
717 else
718 {
719 lib.ssh2_sftp_shutdown(ptr_sftp);
720 }
721
722 1 return GATE_RESULT_OK;
723 }
724
725 1 gate_result_t gate_sshclient_release(gate_sshclient_t* client)
726 {
727 1 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
728
729 1 gate_sshclient_disconnect(client);
730 1 lib.ssh2_session_free(session);
731
732 1 return GATE_RESULT_OK;
733 }
734
735
736 1 gate_result_t gate_sshclient_close_sftp(gate_sshclient_sftp_t* sftp)
737 {
738
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
739
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_sftp)
740 {
741 1 lib.ssh2_sftp_shutdown(ptr_sftp);
742 1 *sftp = NULL;
743 }
744 1 return GATE_RESULT_OK;
745 }
746
747 1 gate_result_t gate_sshclient_sftp_open(gate_sshclient_sftp_t* sftp, gate_string_t const* path, gate_enumint_t stream_open_flags,
748 gate_sshclient_sftp_handle_t* sftp_handle)
749 {
750 char file_path[GATE_MAX_FILEPATH_LENGTH];
751 gate_size_t file_path_length;
752
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
753 1 unsigned long flags = 0;
754 1 long mode = LIBSSH2_SFTP_S_IFREG;
755 1 int open_type = LIBSSH2_SFTP_OPENFILE;
756 LIBSSH2_SFTP_HANDLE* ptr_handle;
757
758
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_sftp)
759 {
760 GATE_DEBUG_TRACE("Missing sftp session");
761 return GATE_RESULT_NULLPOINTER;
762 }
763
764 1 file_path_length = gate_string_to_buffer(path, file_path, sizeof(file_path));
765
766
1/6
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
1 switch (stream_open_flags)
767 {
768 1 case GATE_STREAM_OPEN_READ:
769 1 flags = LIBSSH2_FXF_READ;
770 1 break;
771 case GATE_STREAM_OPEN_WRITE:
772 flags = LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC;
773 mode |= LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IRGRP;
774 break;
775 case GATE_STREAM_OPEN_READWRITE:
776 flags = LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE;
777 case GATE_STREAM_OPEN_APPEND:
778 case GATE_STREAM_OPEN_APPENDWRITE:
779 flags = LIBSSH2_FXF_APPEND | LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT;
780 case GATE_STREAM_OPEN_APPENDREADWRITE:
781 flags = LIBSSH2_FXF_APPEND | LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT;
782 default:
783 GATE_DEBUG_TRACE("gate_sshclient_sftp_open(): unsupported open-flags");
784 return GATE_RESULT_INVALIDARG;
785 }
786
787 1 ptr_handle = lib.ssh2_sftp_open_ex(ptr_sftp, file_path, (unsigned int)file_path_length, flags, mode, open_type);
788
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
789 {
790 GATE_DEBUG_TRACE("ssh2_sftp_open_ex() failed");
791 return GATE_RESULT_FAILED;
792 }
793
794
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sftp_handle)
795 {
796 1 *sftp_handle = (gate_sshclient_sftp_handle_t)ptr_handle;
797 }
798 else
799 {
800 lib.ssh2_sftp_close_handle(ptr_handle);
801 }
802 1 return GATE_RESULT_OK;
803 }
804
805 1 gate_result_t gate_sshclient_sftp_read(gate_sshclient_sftp_handle_t* sftp_handle, char* buffer, gate_size_t capacity, gate_size_t* returned)
806 {
807
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP_HANDLE* ptr_handle = sftp_handle ? *((LIBSSH2_SFTP_HANDLE**)sftp_handle) : NULL;
808 ssize_t result;
809
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
810 {
811 GATE_DEBUG_TRACE("Missing sftp handle");
812 return GATE_RESULT_NULLPOINTER;
813 }
814 1 result = lib.ssh2_sftp_read(ptr_handle, buffer, capacity);
815
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result < 0)
816 {
817 GATE_DEBUG_TRACE("ssh2_sftp_read() failed");
818 return GATE_RESULT_FAILED;
819 }
820
821
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (returned)
822 {
823 1 *returned = (gate_size_t)result;
824 }
825 1 return GATE_RESULT_OK;
826 }
827 gate_result_t gate_sshclient_sftp_write(gate_sshclient_sftp_handle_t* sftp_handle, char const* buffer, gate_size_t length, gate_size_t* written)
828 {
829 LIBSSH2_SFTP_HANDLE* ptr_handle = sftp_handle ? *((LIBSSH2_SFTP_HANDLE**)sftp_handle) : NULL;
830 ssize_t result;
831 if (!ptr_handle)
832 {
833 GATE_DEBUG_TRACE("Missing sftp handle");
834 return GATE_RESULT_NULLPOINTER;
835 }
836 result = lib.ssh2_sftp_write(ptr_handle, buffer, length);
837 if (result < 0)
838 {
839 GATE_DEBUG_TRACE("ssh2_sftp_write() failed");
840 return GATE_RESULT_FAILED;
841 }
842
843 if (written)
844 {
845 *written = (gate_size_t)result;
846 }
847 return GATE_RESULT_OK;
848 }
849 1 gate_result_t gate_sshclient_sftp_seek(gate_sshclient_sftp_handle_t* sftp_handle, gate_uint64_t position)
850 {
851
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP_HANDLE* ptr_handle = sftp_handle ? *((LIBSSH2_SFTP_HANDLE**)sftp_handle) : NULL;
852
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
853 {
854 GATE_DEBUG_TRACE("Missing sftp handle");
855 return GATE_RESULT_NULLPOINTER;
856 }
857 1 lib.ssh2_sftp_seek64(ptr_handle, position);
858 1 return GATE_RESULT_OK;
859 }
860 1 gate_result_t gate_sshclient_sftp_tell(gate_sshclient_sftp_handle_t* sftp_handle, gate_uint64_t* position)
861 {
862
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP_HANDLE* ptr_handle = sftp_handle ? *((LIBSSH2_SFTP_HANDLE**)sftp_handle) : NULL;
863
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
864 {
865 GATE_DEBUG_TRACE("Missing sftp handle");
866 return GATE_RESULT_NULLPOINTER;
867 }
868
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (position)
869 {
870 1 *position = lib.ssh2_sftp_tell64(ptr_handle);
871 }
872 1 return GATE_RESULT_OK;
873 }
874 2 gate_result_t gate_sshclient_sftp_close(gate_sshclient_sftp_handle_t* sftp_handle)
875 {
876
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 LIBSSH2_SFTP_HANDLE* ptr_handle = sftp_handle ? *((LIBSSH2_SFTP_HANDLE**)sftp_handle) : NULL;
877
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!ptr_handle)
878 {
879 GATE_DEBUG_TRACE("Missing sftp handle");
880 return GATE_RESULT_NULLPOINTER;
881 }
882 2 lib.ssh2_sftp_close_handle(ptr_handle);
883 2 *sftp_handle = NULL;
884 2 return GATE_RESULT_OK;
885 }
886 1 gate_result_t gate_sshclient_sftp_opendir(gate_sshclient_sftp_t* sftp, gate_string_t const* path, gate_sshclient_sftp_handle_t* sftp_handle)
887 {
888 char file_path[GATE_MAX_FILEPATH_LENGTH];
889 gate_size_t file_path_length;
890
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
891 LIBSSH2_SFTP_HANDLE* ptr_handle;
892
893
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_sftp)
894 {
895 GATE_DEBUG_TRACE("Missing sftp session");
896 return GATE_RESULT_NULLPOINTER;
897 }
898
899 1 file_path_length = gate_string_to_buffer(path, file_path, sizeof(file_path));
900
901 1 ptr_handle = lib.ssh2_sftp_open_ex(ptr_sftp, file_path, (unsigned int)file_path_length, 0, 0, LIBSSH2_SFTP_OPENDIR);
902
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
903 {
904 GATE_DEBUG_TRACE("ssh2_sftp_open_ex() failed");
905 return GATE_RESULT_FAILED;
906 }
907
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sftp_handle)
908 {
909 1 *sftp_handle = (gate_sshclient_sftp_handle_t)ptr_handle;
910 }
911 else
912 {
913 lib.ssh2_sftp_close_handle(ptr_handle);
914 }
915 1 return GATE_RESULT_OK;
916 }
917
918 19 static void convert_attributes(LIBSSH2_SFTP_ATTRIBUTES* ptr_attr, gate_file_properties_t* file_props)
919 {
920
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (ptr_attr->flags & LIBSSH2_SFTP_ATTR_SIZE)
921 {
922 19 file_props->size = ptr_attr->filesize;
923 }
924
925
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (ptr_attr->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS)
926 {
927
2/2
✓ Branch 0 taken 17 times.
✓ Branch 1 taken 2 times.
19 if (LIBSSH2_SFTP_S_ISREG(ptr_attr->permissions)) file_props->attribs |= GATE_FILEENTRY_ATTRIB_FILE;
928
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (LIBSSH2_SFTP_S_ISDIR(ptr_attr->permissions)) file_props->attribs |= GATE_FILEENTRY_ATTRIB_DIRECTORY;
929
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (LIBSSH2_SFTP_S_ISCHR(ptr_attr->permissions)) file_props->attribs |= GATE_FILEENTRY_ATTRIB_DEVICE;
930
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (LIBSSH2_SFTP_S_ISBLK(ptr_attr->permissions)) file_props->attribs |= GATE_FILEENTRY_ATTRIB_DEVICE;
931
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (LIBSSH2_SFTP_S_ISFIFO(ptr_attr->permissions)) file_props->attribs |= GATE_FILEENTRY_ATTRIB_SPECIAL;
932
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (LIBSSH2_SFTP_S_ISSOCK(ptr_attr->permissions)) file_props->attribs |= GATE_FILEENTRY_ATTRIB_SPECIAL;
933
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (LIBSSH2_SFTP_S_ISLNK(ptr_attr->permissions)) file_props->attribs |= GATE_FILEENTRY_ATTRIB_FILE;
934
935
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IRUSR) file_props->access |= GATE_FILEENTRY_ACCESS_OWNERREAD;
936
2/2
✓ Branch 0 taken 13 times.
✓ Branch 1 taken 6 times.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IWUSR) file_props->access |= GATE_FILEENTRY_ACCESS_OWNERWRITE;
937
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 17 times.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IXUSR) file_props->access |= GATE_FILEENTRY_ACCESS_OWNEREXECUTE;
938
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IRGRP) file_props->access |= GATE_FILEENTRY_ACCESS_GROUPREAD;
939
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IWGRP) file_props->access |= GATE_FILEENTRY_ACCESS_GROUPWRITE;
940
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IXGRP) file_props->access |= GATE_FILEENTRY_ACCESS_GROUPEXECUTE;
941
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IROTH) file_props->access |= GATE_FILEENTRY_ACCESS_ALLREAD;
942
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IWOTH) file_props->access |= GATE_FILEENTRY_ACCESS_ALLWRITE;
943
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (ptr_attr->permissions & LIBSSH2_SFTP_S_IXOTH) file_props->access |= GATE_FILEENTRY_ACCESS_ALLEXECUTE;
944 }
945
946
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (ptr_attr->flags & LIBSSH2_SFTP_ATTR_ACMODTIME)
947 {
948 19 gate_time_from_unix(ptr_attr->atime, &file_props->time_accessed);
949 19 gate_time_from_unix(ptr_attr->mtime, &file_props->time_modified);
950 19 gate_time_from_unix(ptr_attr->atime, &file_props->time_created);
951 }
952
953 19 }
954
955 19 gate_result_t gate_sshclient_sftp_readdir(gate_sshclient_sftp_handle_t* sftp_handle, gate_file_entry_t* file_entry)
956 {
957
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 LIBSSH2_SFTP_HANDLE* ptr_handle = sftp_handle ? *((LIBSSH2_SFTP_HANDLE**)sftp_handle) : NULL;
958 char buffer[GATE_MAX_FILENAME_LENGTH];
959 char longentry[GATE_MAX_COPYBUFFER_LENGTH];
960 19 LIBSSH2_SFTP_ATTRIBUTES attribs = GATE_INIT_EMPTY;
961 int result;
962
963
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sftp_handle)
964 {
965 GATE_DEBUG_TRACE("Missing sftp session");
966 return GATE_RESULT_NULLPOINTER;
967 }
968
969 19 attribs.flags = LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID | LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
970 19 result = lib.ssh2_sftp_readdir_ex(ptr_handle, buffer, sizeof(buffer), longentry, sizeof(longentry), &attribs);
971
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (result < 0)
972 {
973 return GATE_RESULT_FAILED;
974 }
975
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 else if (result == 0)
976 {
977 1 return GATE_RESULT_NODATA;
978 }
979
980
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (file_entry)
981 {
982 18 buffer[sizeof(buffer) - 1] = 0;
983 18 gate_mem_clear(file_entry, sizeof(gate_file_entry_t));
984 18 gate_str_print_text(file_entry->name, sizeof(file_entry->name), buffer, gate_str_length(buffer));
985 18 convert_attributes(&attribs, &file_entry->props);
986 }
987 18 return GATE_RESULT_OK;
988 }
989
990 gate_result_t gate_sshclient_sftp_listdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path, gate_file_list_callback_t callback, void* userdata)
991 {
992 gate_result_t result;
993 gate_sshclient_sftp_handle_t handle = NULL;
994 gate_file_entry_t entry;
995 gate_bool_t continue_readdir = true;
996 gate_size_t len;
997 gate_size_t namelen;
998 gate_bool_t need_slash = !gate_string_ends_with_char(path, '/');
999
1000 result = gate_sshclient_sftp_opendir(sftp, path, &handle);
1001 if (GATE_FAILED(result))
1002 {
1003 return result;
1004 }
1005
1006 while (continue_readdir)
1007 {
1008 result = gate_sshclient_sftp_readdir(&handle, &entry);
1009 GATE_BREAK_IF_FAILED(result);
1010
1011 namelen = gate_str_length(entry.name);
1012
1013 if ((gate_str_compare(entry.name, namelen, ".", 1) == 0)
1014 || (gate_str_compare(entry.name, namelen, "..", 2) == 0))
1015 {
1016 /* skip pseudo-dir-entries */
1017 }
1018 else
1019 {
1020 len = gate_str_print_text(entry.path, sizeof(entry.path) - 1, path->str, path->length);
1021 if (need_slash)
1022 {
1023 entry.path[len] = '/';
1024 ++len;
1025 }
1026 gate_str_print_text(&entry.path[len], sizeof(entry.path) - len, entry.name, namelen);
1027
1028 continue_readdir = callback(&entry, userdata);
1029 }
1030 }
1031
1032 gate_sshclient_sftp_close(&handle);
1033 if (result == GATE_RESULT_NODATA)
1034 {
1035 result = GATE_RESULT_OK;
1036 }
1037 return result;
1038 }
1039
1040
1041 gate_result_t gate_sshclient_sftp_mkdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1042 {
1043 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1044 char buffer[GATE_MAX_FILEPATH_LENGTH];
1045 gate_size_t buffer_len;
1046 int result;
1047
1048 if (!ptr_sftp)
1049 {
1050 GATE_DEBUG_TRACE("Missing sftp session");
1051 return GATE_RESULT_NULLPOINTER;
1052 }
1053
1054 buffer_len = gate_string_to_buffer(path, buffer, sizeof(buffer));
1055
1056 result = lib.ssh2_sftp_mkdir_ex(ptr_sftp, buffer, (unsigned int)buffer_len, 0775);
1057 if (result != 0)
1058 {
1059 GATE_DEBUG_TRACE("ssh2_sftp_mkdir_ex() failed");
1060 return GATE_RESULT_FAILED;
1061 }
1062 return GATE_RESULT_OK;
1063 }
1064
1065 gate_result_t gate_sshclient_sftp_rmdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1066 {
1067 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1068 char buffer[GATE_MAX_FILEPATH_LENGTH];
1069 gate_size_t buffer_len;
1070 int result;
1071
1072 if (!ptr_sftp)
1073 {
1074 GATE_DEBUG_TRACE("Missing sftp session");
1075 return GATE_RESULT_NULLPOINTER;
1076 }
1077
1078 buffer_len = gate_string_to_buffer(path, buffer, sizeof(buffer));
1079
1080 result = lib.ssh2_sftp_rmdir_ex(ptr_sftp, buffer, (unsigned int)buffer_len);
1081 if (result != 0)
1082 {
1083 GATE_DEBUG_TRACE("ssh2_sftp_rmdir_ex() failed");
1084 return GATE_RESULT_FAILED;
1085 }
1086 return GATE_RESULT_OK;
1087 }
1088 gate_result_t gate_sshclient_sftp_unlink(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1089 {
1090 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1091 char buffer[GATE_MAX_FILEPATH_LENGTH];
1092 gate_size_t buffer_len;
1093 int result;
1094
1095 if (!ptr_sftp)
1096 {
1097 GATE_DEBUG_TRACE("Missing sftp session");
1098 return GATE_RESULT_NULLPOINTER;
1099 }
1100
1101 buffer_len = gate_string_to_buffer(path, buffer, sizeof(buffer));
1102
1103 result = lib.ssh2_sftp_unlink_ex(ptr_sftp, buffer, (unsigned int)buffer_len);
1104 if (result != 0)
1105 {
1106 GATE_DEBUG_TRACE("ssh2_sftp_unlink_ex() failed");
1107 return GATE_RESULT_FAILED;
1108 }
1109 return GATE_RESULT_OK;
1110 }
1111 gate_result_t gate_sshclient_sftp_rename(gate_sshclient_sftp_t* sftp, gate_string_t const* src_path, gate_string_t const* dst_path)
1112 {
1113 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1114 char src_buffer[GATE_MAX_FILEPATH_LENGTH];
1115 char dst_buffer[GATE_MAX_FILEPATH_LENGTH];
1116 gate_size_t src_buffer_len;
1117 gate_size_t dst_buffer_len;
1118 int result;
1119
1120 if (!ptr_sftp)
1121 {
1122 GATE_DEBUG_TRACE("Missing sftp session");
1123 return GATE_RESULT_NULLPOINTER;
1124 }
1125
1126 src_buffer_len = gate_string_to_buffer(src_path, src_buffer, sizeof(src_buffer));
1127 dst_buffer_len = gate_string_to_buffer(dst_path, dst_buffer, sizeof(dst_buffer));
1128
1129 result = lib.ssh2_sftp_rename_ex(ptr_sftp, src_buffer, (unsigned int)src_buffer_len,
1130 dst_buffer, (unsigned int)dst_buffer_len, LIBSSH2_SFTP_RENAME_ATOMIC);
1131 if (result != 0)
1132 {
1133 GATE_DEBUG_TRACE("ssh2_sftp_rename_ex() failed");
1134 return GATE_RESULT_FAILED;
1135 }
1136 return GATE_RESULT_OK;
1137 }
1138 1 gate_result_t gate_sshclient_sftp_stat(gate_sshclient_sftp_t* sftp, gate_string_t const* path, gate_file_properties_t* file_props)
1139 {
1140
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1141 char buffer[GATE_MAX_FILEPATH_LENGTH];
1142 gate_size_t buffer_len;
1143 int result;
1144 1 LIBSSH2_SFTP_ATTRIBUTES attribs = GATE_INIT_EMPTY;
1145
1146
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_sftp)
1147 {
1148 GATE_DEBUG_TRACE("Missing sftp session");
1149 return GATE_RESULT_NULLPOINTER;
1150 }
1151
1152 1 buffer_len = gate_string_to_buffer(path, buffer, sizeof(buffer));
1153
1154 1 attribs.flags = LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID | LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
1155 1 result = lib.ssh2_sftp_stat_ex(ptr_sftp, buffer, (unsigned int)buffer_len, LIBSSH2_SFTP_LSTAT, &attribs);
1156
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result != 0)
1157 {
1158 GATE_DEBUG_TRACE("ssh2_sftp_stat_ex() failed");
1159 return GATE_RESULT_FAILED;
1160 }
1161
1162 1 convert_attributes(&attribs, file_props);
1163
1164 1 return GATE_RESULT_OK;
1165 }
1166
1167
1168 typedef struct ssh_channel_impl_class
1169 {
1170 LIBSSH2_CHANNEL* channel;
1171 gate_size_t read_buffer_used;
1172 gate_size_t read_buffer_offset;
1173 char read_buffer[8192];
1174
1175 gate_size_t err_buffer_used;
1176 gate_size_t err_buffer_offset;
1177 char err_buffer[8192];
1178 } ssh_channel_impl_t;
1179
1180 gate_result_t gate_sshclient_channel_open(gate_sshclient_t* client, gate_sshclient_channel_t* ptr_channel)
1181 {
1182 ssh_channel_impl_t* impl = NULL;
1183 LIBSSH2_SESSION* session = client ? (LIBSSH2_SESSION*)client->handles[0] : NULL;
1184 LIBSSH2_CHANNEL* channel = NULL;
1185
1186 if (!session)
1187 {
1188 GATE_DEBUG_TRACE("missing client session");
1189 return GATE_RESULT_NULLPOINTER;
1190 }
1191
1192 channel = lib.ssh2_channel_open_ex(session, "session", 7, LIBSSH2_CHANNEL_WINDOW_DEFAULT, LIBSSH2_CHANNEL_PACKET_DEFAULT, NULL, 0);
1193 if (!channel)
1194 {
1195 GATE_DEBUG_TRACE_SSH2_ERROR(session, "ssh2_channel_open_ex() failed");
1196 return GATE_RESULT_FAILED;
1197 }
1198
1199 lib.ssh2_channel_set_blocking(channel, 1);
1200
1201 if (ptr_channel)
1202 {
1203 impl = (ssh_channel_impl_t*)gate_mem_alloc(sizeof(ssh_channel_impl_t));
1204 if (NULL == impl)
1205 {
1206 lib.ssh2_channel_close(channel);
1207 return GATE_RESULT_OUTOFMEMORY;
1208 }
1209 impl->channel = channel;
1210 impl->read_buffer_offset = 0;
1211 impl->read_buffer_used = 0;
1212 *ptr_channel = (gate_sshclient_channel_t)impl;
1213 }
1214 else
1215 {
1216 lib.ssh2_channel_close(channel);
1217 }
1218 return GATE_RESULT_OK;
1219 }
1220
1221 gate_result_t gate_sshclient_channel_close(gate_sshclient_channel_t* channel)
1222 {
1223 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1224 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1225 int result;
1226
1227 if (!ssh_channel)
1228 {
1229 return GATE_RESULT_NULLPOINTER;
1230 }
1231 result = lib.ssh2_channel_close(ssh_channel);
1232 if (0 != result)
1233 {
1234 return GATE_RESULT_LOCKED;
1235 }
1236 return GATE_RESULT_OK;
1237 }
1238
1239 gate_result_t gate_sshclient_channel_free(gate_sshclient_channel_t* channel)
1240 {
1241 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1242 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1243 int result;
1244
1245 if (!ssh_channel)
1246 {
1247 return GATE_RESULT_NULLPOINTER;
1248 }
1249 result = lib.ssh2_channel_free(ssh_channel);
1250 if (0 != result)
1251 {
1252 return GATE_RESULT_LOCKED;
1253 }
1254
1255 gate_mem_dealloc(impl);
1256 *channel = NULL;
1257 return GATE_RESULT_OK;
1258 }
1259
1260 gate_result_t gate_sshclient_channel_exec(gate_sshclient_channel_t* channel, gate_string_t const* command)
1261 {
1262 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1263 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1264 gate_cstrbuffer_t sb;
1265 int result;
1266 char const* req_name;
1267 unsigned int req_name_len;
1268 char const* ptr_command;
1269 unsigned int command_length;
1270
1271 if (!ssh_channel)
1272 {
1273 return GATE_RESULT_NULLPOINTER;
1274 }
1275 if (NULL == gate_cstrbuffer_create_string(&sb, command, false))
1276 {
1277 return GATE_RESULT_OUTOFMEMORY;
1278 }
1279
1280 command_length = (unsigned int)gate_cstrbuffer_length(&sb);
1281 if (command_length == 0)
1282 {
1283 ptr_command = NULL;
1284 req_name = "shell";
1285 req_name_len = 5;
1286 }
1287 else
1288 {
1289 ptr_command = gate_cstrbuffer_get(&sb);
1290 req_name = "exec";
1291 req_name_len = 4;
1292 }
1293
1294 result = lib.ssh2_channel_process_startup(ssh_channel, req_name, req_name_len, ptr_command, command_length);
1295 gate_cstrbuffer_destroy(&sb);
1296 if (0 != result)
1297 {
1298 return GATE_RESULT_FAILED;
1299 }
1300 return GATE_RESULT_OK;
1301 }
1302
1303 gate_result_t gate_sshclient_channel_canread(gate_sshclient_channel_t* channel, gate_enumint_t stream_type, gate_bool_t* ptr_canread)
1304 {
1305 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1306 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1307 ssize_t bytes_returned;
1308 int stream_id;
1309
1310 if (!ssh_channel || !ptr_canread)
1311 {
1312 return GATE_RESULT_NULLPOINTER;
1313 }
1314
1315 switch (stream_type)
1316 {
1317 case GATE_SSHCLIENT_STREAMTYPE_DEFAULT: stream_id = 0; break;
1318 case GATE_SSHCLIENT_STREAMTYPE_ERROR: stream_id = SSH_EXTENDED_DATA_STDERR; break;
1319 default: stream_id = stream_type; break;
1320 }
1321
1322 switch (stream_type)
1323 {
1324 case GATE_SSHCLIENT_STREAMTYPE_DEFAULT:
1325 {
1326 if (impl->read_buffer_offset < impl->read_buffer_used)
1327 {
1328 /* something is in the buffer */
1329 *ptr_canread = true;
1330 return GATE_RESULT_OK;
1331 }
1332
1333 lib.ssh2_channel_set_blocking(ssh_channel, 0);
1334 bytes_returned = lib.ssh2_channel_read_ex(ssh_channel, stream_id, &impl->read_buffer[0], sizeof(impl->read_buffer));
1335 lib.ssh2_channel_set_blocking(ssh_channel, 1);
1336 if (bytes_returned == LIBSSH2_ERROR_EAGAIN)
1337 {
1338 /* cannot read, would block */
1339 *ptr_canread = false;
1340 return GATE_RESULT_OK;
1341 }
1342 if (bytes_returned < 0)
1343 {
1344 /* another error, will be returned with next read attempt */
1345 }
1346 else
1347 {
1348 /* buffer is filled with data to be returned on next read attempt */
1349 impl->read_buffer_offset = 0;
1350 impl->read_buffer_used = (gate_size_t)bytes_returned;
1351 }
1352 *ptr_canread = true;
1353 return GATE_RESULT_OK;
1354 }
1355 case GATE_SSHCLIENT_STREAMTYPE_ERROR:
1356 {
1357 if (impl->err_buffer_offset < impl->err_buffer_used)
1358 {
1359 /* something is in the buffer */
1360 *ptr_canread = true;
1361 return GATE_RESULT_OK;
1362 }
1363
1364 lib.ssh2_channel_set_blocking(ssh_channel, 0);
1365 bytes_returned = lib.ssh2_channel_read_ex(ssh_channel, stream_id, &impl->err_buffer[0], sizeof(impl->err_buffer));
1366 lib.ssh2_channel_set_blocking(ssh_channel, 1);
1367 if (bytes_returned == LIBSSH2_ERROR_EAGAIN)
1368 {
1369 /* cannot read, would block */
1370 *ptr_canread = false;
1371 return GATE_RESULT_OK;
1372 }
1373 if (bytes_returned < 0)
1374 {
1375 /* another error, will be returned with next read attempt */
1376 }
1377 else
1378 {
1379 /* buffer is filled with data to be returned on next read attempt */
1380 impl->err_buffer_offset = 0;
1381 impl->err_buffer_used = (gate_size_t)bytes_returned;
1382 }
1383 *ptr_canread = true;
1384 return GATE_RESULT_OK;
1385 }
1386 default:
1387 {
1388 break;
1389 }
1390 }
1391 return GATE_RESULT_NOTSUPPORTED;
1392 }
1393
1394 gate_result_t gate_sshclient_channel_read(gate_sshclient_channel_t* channel, gate_enumint_t stream_type, char* buffer, gate_size_t bufferlen, gate_size_t* bufferused)
1395 {
1396 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1397 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1398 ssize_t bytes_returned;
1399 int stream_id = 0;
1400
1401 if (!ssh_channel || !buffer)
1402 {
1403 return GATE_RESULT_NULLPOINTER;
1404 }
1405 switch (stream_type)
1406 {
1407 case GATE_SSHCLIENT_STREAMTYPE_DEFAULT:
1408 {
1409 if (impl->read_buffer_offset < impl->read_buffer_used)
1410 {
1411 /* we have data in the read buffer */
1412 if (bufferlen > (impl->read_buffer_used - impl->read_buffer_offset))
1413 {
1414 bufferlen = (impl->read_buffer_used - impl->read_buffer_offset);
1415 }
1416 gate_mem_copy(buffer, &impl->read_buffer[impl->read_buffer_offset], bufferlen);
1417 impl->read_buffer_offset += bufferlen;
1418 if (bufferused)
1419 {
1420 *bufferused = bufferlen;
1421 }
1422 return GATE_RESULT_OK;
1423 }
1424 stream_id = 0;
1425 break;
1426 }
1427 case GATE_SSHCLIENT_STREAMTYPE_ERROR:
1428 {
1429 if (impl->err_buffer_offset < impl->err_buffer_used)
1430 {
1431 /* we have data in the error buffer */
1432 if (bufferlen > (impl->err_buffer_used - impl->err_buffer_offset))
1433 {
1434 bufferlen = (impl->err_buffer_used - impl->err_buffer_offset);
1435 }
1436 gate_mem_copy(buffer, &impl->err_buffer[impl->err_buffer_offset], bufferlen);
1437 impl->err_buffer_offset += bufferlen;
1438 if (bufferused)
1439 {
1440 *bufferused = bufferlen;
1441 }
1442 return GATE_RESULT_OK;
1443 }
1444 stream_id = SSH_EXTENDED_DATA_STDERR;
1445 break;
1446 }
1447 default:
1448 {
1449 stream_id = stream_type;
1450 break;
1451 }
1452 }
1453
1454 bytes_returned = lib.ssh2_channel_read_ex(ssh_channel, stream_id, buffer, bufferlen);
1455 if (bytes_returned < 0)
1456 {
1457 return GATE_RESULT_FAILED;
1458 }
1459 if (bufferused)
1460 {
1461 *bufferused = (gate_size_t)bytes_returned;
1462 }
1463 return GATE_RESULT_OK;
1464 }
1465
1466 gate_result_t gate_sshclient_channel_write(gate_sshclient_channel_t* channel, gate_enumint_t stream_type, char const* buffer, gate_size_t bufferlen, gate_size_t* bufferprocessed)
1467 {
1468 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1469 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1470 ssize_t bytes_written;
1471 int stream_id = 0;
1472
1473 if (!ssh_channel || !buffer)
1474 {
1475 return GATE_RESULT_NULLPOINTER;
1476 }
1477 switch (stream_type)
1478 {
1479 case GATE_SSHCLIENT_STREAMTYPE_DEFAULT: stream_id = 0; break;
1480 case GATE_SSHCLIENT_STREAMTYPE_ERROR: stream_id = SSH_EXTENDED_DATA_STDERR; break;
1481 default: stream_id = stream_type; break;
1482 }
1483
1484 bytes_written = lib.ssh2_channel_write_ex(ssh_channel, stream_id, buffer, bufferlen);
1485 if (bytes_written < 0)
1486 {
1487 return GATE_RESULT_FAILED;
1488 }
1489 if (bufferprocessed)
1490 {
1491 *bufferprocessed = (gate_size_t)bytes_written;
1492 }
1493 return GATE_RESULT_OK;
1494 }
1495
1496 gate_bool_t gate_sshclient_channel_eof(gate_sshclient_channel_t* channel)
1497 {
1498 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1499 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1500
1501 if (!ssh_channel)
1502 {
1503 return false;
1504 }
1505 return lib.ssh2_channel_eof(ssh_channel) == 1 ? true : false;
1506 }
1507
1508 gate_result_t gate_sshclient_channel_send_eof(gate_sshclient_channel_t* channel)
1509 {
1510 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1511 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1512 int result;
1513
1514 if (!ssh_channel)
1515 {
1516 return GATE_RESULT_NULLPOINTER;
1517 }
1518 result = lib.ssh2_channel_send_eof(ssh_channel);
1519 if (result != 0)
1520 {
1521 return GATE_RESULT_FAILED;
1522 }
1523 return GATE_RESULT_OK;
1524 }
1525
1526 gate_result_t gate_sshclient_channel_wait_eof(gate_sshclient_channel_t* channel)
1527 {
1528 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1529 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1530 int result;
1531
1532 if (!ssh_channel)
1533 {
1534 return GATE_RESULT_NULLPOINTER;
1535 }
1536 result = lib.ssh2_channel_wait_eof(ssh_channel);
1537 if (result != 0)
1538 {
1539 return GATE_RESULT_FAILED;
1540 }
1541 return GATE_RESULT_OK;
1542 }
1543
1544 gate_result_t gate_sshclient_channel_setenv(gate_sshclient_channel_t* channel, gate_string_t const* name, gate_string_t const* value)
1545 {
1546 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1547 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1548 int result;
1549
1550 if (!ssh_channel)
1551 {
1552 return GATE_RESULT_NULLPOINTER;
1553 }
1554 result = lib.ssh2_channel_setenv_ex(ssh_channel,
1555 gate_string_ptr(name, 0), (unsigned int)gate_string_length(name),
1556 gate_string_ptr(value, 0), (unsigned int)gate_string_length(value));
1557 if (result != 0)
1558 {
1559 return GATE_RESULT_FAILED;
1560 }
1561 return GATE_RESULT_OK;
1562 }
1563
1564 gate_result_t gate_sshclient_channel_get_exit_signal(gate_sshclient_channel_t* channel, gate_string_t* ptr_signal, gate_string_t* ptr_errmsg, gate_string_t* ptr_langtag)
1565 {
1566 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1567 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1568 gate_result_t ret = GATE_RESULT_FAILED;
1569 int result;
1570 char* exitsignal = NULL;
1571 size_t exitsignal_len = 0;
1572 char* errmsg = NULL;
1573 size_t errmsg_len = 0;
1574 char* langtag = NULL;
1575 size_t langtag_len = 0;
1576
1577 do
1578 {
1579 if (!ssh_channel)
1580 {
1581 ret = GATE_RESULT_NULLPOINTER;
1582 break;
1583 }
1584 result = lib.ssh2_channel_get_exit_signal(ssh_channel, &exitsignal, &exitsignal_len, &errmsg, &errmsg_len, &langtag, &langtag_len);
1585 if (result != 0)
1586 {
1587 ret = GATE_RESULT_FAILED;
1588 break;
1589 }
1590
1591 if (ptr_signal)
1592 {
1593 if (NULL == gate_string_create(ptr_signal, exitsignal, exitsignal_len))
1594 {
1595 ret = GATE_RESULT_OUTOFMEMORY;
1596 }
1597 }
1598 if (ptr_errmsg)
1599 {
1600 if (NULL == gate_string_create(ptr_errmsg, errmsg, errmsg_len))
1601 {
1602 if (ptr_signal) gate_string_release(ptr_signal);
1603 ret = GATE_RESULT_OUTOFMEMORY;
1604 }
1605 }
1606 if (ptr_langtag)
1607 {
1608 if (NULL == gate_string_create(ptr_langtag, langtag, langtag_len))
1609 {
1610 if (ptr_signal) gate_string_release(ptr_errmsg);
1611 if (ptr_signal) gate_string_release(ptr_signal);
1612 ret = GATE_RESULT_OUTOFMEMORY;
1613 }
1614 }
1615
1616 ret = GATE_RESULT_OK;
1617
1618 } while (0);
1619
1620 return ret;
1621 }
1622
1623 gate_result_t gate_sshclient_channel_get_exit_status(gate_sshclient_channel_t* channel, int* ptr_status)
1624 {
1625 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1626 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1627 int result;
1628
1629 if (!ssh_channel)
1630 {
1631 return GATE_RESULT_NULLPOINTER;
1632 }
1633 result = lib.ssh2_channel_get_exit_status(ssh_channel);
1634 if (ptr_status)
1635 {
1636 *ptr_status = result;
1637 }
1638 return GATE_RESULT_OK;
1639 }
1640
1641 #endif
1642
1643
1644
1645 #if defined(GATE_NET_SSHCLIENTS_NO_IMPL)
1646
1647 gate_result_t gate_sshclient_create(gate_sshclient_t* client, gate_string_t const* server, gate_uint16_t port)
1648 {
1649 GATE_UNUSED_ARG(client);
1650 GATE_UNUSED_ARG(server);
1651 GATE_UNUSED_ARG(port);
1652 return GATE_RESULT_NOTIMPLEMENTED;
1653 }
1654 gate_result_t gate_sshclient_connect(gate_sshclient_t* client,
1655 gate_string_t const* user, gate_string_t const* password, gate_enumint_t flags)
1656 {
1657 GATE_UNUSED_ARG(client);
1658 GATE_UNUSED_ARG(user);
1659 GATE_UNUSED_ARG(password);
1660 GATE_UNUSED_ARG(flags);
1661 return GATE_RESULT_NOTIMPLEMENTED;
1662 }
1663 gate_result_t gate_sshclient_connect_keys(gate_sshclient_t* client,
1664 gate_string_t const* user, gate_string_t const* pubkey, gate_string_t const* privkey,
1665 gate_string_t const* passphrase, gate_enumint_t flags)
1666 {
1667 GATE_UNUSED_ARG(client);
1668 GATE_UNUSED_ARG(user);
1669 GATE_UNUSED_ARG(pubkey);
1670 GATE_UNUSED_ARG(privkey);
1671 GATE_UNUSED_ARG(passphrase);
1672 GATE_UNUSED_ARG(flags);
1673 return GATE_RESULT_NOTIMPLEMENTED;
1674 }
1675
1676 gate_result_t gate_sshclient_disconnect(gate_sshclient_t* client)
1677 {
1678 GATE_UNUSED_ARG(client);
1679 return GATE_RESULT_NOTIMPLEMENTED;
1680 }
1681 gate_result_t gate_sshclient_release(gate_sshclient_t* client)
1682 {
1683 GATE_UNUSED_ARG(client);
1684 return GATE_RESULT_NOTIMPLEMENTED;
1685 }
1686
1687 gate_result_t gate_sshclient_open_sftp(gate_sshclient_t* client, gate_sshclient_sftp_t* sftp)
1688 {
1689 GATE_UNUSED_ARG(client);
1690 GATE_UNUSED_ARG(sftp);
1691 return GATE_RESULT_NOTIMPLEMENTED;
1692 }
1693 gate_result_t gate_sshclient_close_sftp(gate_sshclient_sftp_t* sftp)
1694 {
1695 GATE_UNUSED_ARG(sftp);
1696 return GATE_RESULT_NOTIMPLEMENTED;
1697 }
1698
1699 gate_result_t gate_sshclient_sftp_open(gate_sshclient_sftp_t* sftp, gate_string_t const* path,
1700 gate_enumint_t stream_open_flags, gate_sshclient_sftp_handle_t* sftp_handle)
1701 {
1702 GATE_UNUSED_ARG(sftp);
1703 GATE_UNUSED_ARG(path);
1704 GATE_UNUSED_ARG(stream_open_flags);
1705 GATE_UNUSED_ARG(sftp_handle);
1706 return GATE_RESULT_NOTIMPLEMENTED;
1707 }
1708 gate_result_t gate_sshclient_sftp_read(gate_sshclient_sftp_handle_t* sftp_handle,
1709 char* buffer, gate_size_t capacity, gate_size_t* returned)
1710 {
1711 GATE_UNUSED_ARG(sftp_handle);
1712 GATE_UNUSED_ARG(buffer);
1713 GATE_UNUSED_ARG(capacity);
1714 GATE_UNUSED_ARG(returned);
1715 return GATE_RESULT_NOTIMPLEMENTED;
1716 }
1717 gate_result_t gate_sshclient_sftp_write(gate_sshclient_sftp_handle_t* sftp_handle,
1718 char const* buffer, gate_size_t length, gate_size_t* written)
1719 {
1720 GATE_UNUSED_ARG(sftp_handle);
1721 GATE_UNUSED_ARG(buffer);
1722 GATE_UNUSED_ARG(length);
1723 GATE_UNUSED_ARG(written);
1724 return GATE_RESULT_NOTIMPLEMENTED;
1725 }
1726 gate_result_t gate_sshclient_sftp_seek(gate_sshclient_sftp_handle_t* sftp_handle, gate_uint64_t position)
1727 {
1728 GATE_UNUSED_ARG(sftp_handle);
1729 GATE_UNUSED_ARG(position);
1730 return GATE_RESULT_NOTIMPLEMENTED;
1731 }
1732 gate_result_t gate_sshclient_sftp_tell(gate_sshclient_sftp_handle_t* sftp_handle, gate_uint64_t* position)
1733 {
1734 GATE_UNUSED_ARG(sftp_handle);
1735 GATE_UNUSED_ARG(position);
1736 return GATE_RESULT_NOTIMPLEMENTED;
1737 }
1738 gate_result_t gate_sshclient_sftp_close(gate_sshclient_sftp_handle_t* sftp_handle)
1739 {
1740 GATE_UNUSED_ARG(sftp_handle);
1741 return GATE_RESULT_NOTIMPLEMENTED;
1742 }
1743 gate_result_t gate_sshclient_sftp_opendir(gate_sshclient_sftp_t* sftp, gate_string_t const* path,
1744 gate_sshclient_sftp_handle_t* sftp_handle)
1745 {
1746 GATE_UNUSED_ARG(sftp);
1747 GATE_UNUSED_ARG(path);
1748 GATE_UNUSED_ARG(sftp_handle);
1749 return GATE_RESULT_NOTIMPLEMENTED;
1750 }
1751 gate_result_t gate_sshclient_sftp_readdir(gate_sshclient_sftp_handle_t* sftp_handle, gate_file_entry_t* file_entry)
1752 {
1753 GATE_UNUSED_ARG(sftp_handle);
1754 GATE_UNUSED_ARG(file_entry);
1755 return GATE_RESULT_NOTIMPLEMENTED;
1756 }
1757 gate_result_t gate_sshclient_sftp_listdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path,
1758 gate_file_list_callback_t callback, void* userdata)
1759 {
1760 GATE_UNUSED_ARG(sftp);
1761 GATE_UNUSED_ARG(path);
1762 GATE_UNUSED_ARG(callback);
1763 GATE_UNUSED_ARG(userdata);
1764 return GATE_RESULT_NOTIMPLEMENTED;
1765 }
1766 gate_result_t gate_sshclient_sftp_mkdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1767 {
1768 GATE_UNUSED_ARG(sftp);
1769 GATE_UNUSED_ARG(path);
1770 return GATE_RESULT_NOTIMPLEMENTED;
1771 }
1772 gate_result_t gate_sshclient_sftp_rmdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1773 {
1774 GATE_UNUSED_ARG(sftp);
1775 GATE_UNUSED_ARG(path);
1776 return GATE_RESULT_NOTIMPLEMENTED;
1777 }
1778 gate_result_t gate_sshclient_sftp_unlink(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1779 {
1780 GATE_UNUSED_ARG(sftp);
1781 GATE_UNUSED_ARG(path);
1782 return GATE_RESULT_NOTIMPLEMENTED;
1783 }
1784 gate_result_t gate_sshclient_sftp_rename(gate_sshclient_sftp_t* sftp, gate_string_t const* src_path, gate_string_t const* dst_path)
1785 {
1786 GATE_UNUSED_ARG(sftp);
1787 GATE_UNUSED_ARG(src_path);
1788 GATE_UNUSED_ARG(dst_path);
1789 return GATE_RESULT_NOTIMPLEMENTED;
1790 }
1791 gate_result_t gate_sshclient_sftp_stat(gate_sshclient_sftp_t* sftp, gate_string_t const* path, gate_file_properties_t* file_props)
1792 {
1793 GATE_UNUSED_ARG(sftp);
1794 GATE_UNUSED_ARG(path);
1795 GATE_UNUSED_ARG(file_props);
1796 return GATE_RESULT_NOTIMPLEMENTED;
1797 }
1798
1799 gate_result_t gate_sshclient_channel_open(gate_sshclient_t* client, gate_sshclient_channel_t* ptr_channel)
1800 {
1801 GATE_UNUSED_ARG(client);
1802 GATE_UNUSED_ARG(ptr_channel);
1803 return GATE_RESULT_NOTIMPLEMENTED;
1804 }
1805 gate_result_t gate_sshclient_channel_close(gate_sshclient_channel_t* channel)
1806 {
1807 GATE_UNUSED_ARG(channel);
1808 return GATE_RESULT_NOTIMPLEMENTED;
1809 }
1810 gate_result_t gate_sshclient_channel_free(gate_sshclient_channel_t* channel)
1811 {
1812 GATE_UNUSED_ARG(channel);
1813 return GATE_RESULT_NOTIMPLEMENTED;
1814 }
1815 gate_result_t gate_sshclient_channel_exec(gate_sshclient_channel_t* channel, gate_string_t const* command)
1816 {
1817 GATE_UNUSED_ARG(channel);
1818 GATE_UNUSED_ARG(command);
1819 return GATE_RESULT_NOTIMPLEMENTED;
1820 }
1821 gate_result_t gate_sshclient_channel_canread(gate_sshclient_channel_t* channel, gate_enumint_t stream_type, gate_bool_t* ptr_canread)
1822 {
1823 GATE_UNUSED_ARG(channel);
1824 GATE_UNUSED_ARG(stream_type);
1825 GATE_UNUSED_ARG(ptr_canread);
1826 return GATE_RESULT_NOTIMPLEMENTED;
1827 }
1828 gate_result_t gate_sshclient_channel_read(gate_sshclient_channel_t* channel, gate_enumint_t stream_type, char* buffer, gate_size_t bufferlen, gate_size_t* bufferused)
1829 {
1830 GATE_UNUSED_ARG(channel);
1831 GATE_UNUSED_ARG(stream_type);
1832 GATE_UNUSED_ARG(buffer);
1833 GATE_UNUSED_ARG(bufferlen);
1834 GATE_UNUSED_ARG(bufferused);
1835 return GATE_RESULT_NOTIMPLEMENTED;
1836 }
1837 gate_result_t gate_sshclient_channel_write(gate_sshclient_channel_t* channel, gate_enumint_t stream_type, char const* buffer, gate_size_t bufferlen, gate_size_t* bufferprocessed)
1838 {
1839 GATE_UNUSED_ARG(channel);
1840 GATE_UNUSED_ARG(stream_type);
1841 GATE_UNUSED_ARG(buffer);
1842 GATE_UNUSED_ARG(bufferlen);
1843 GATE_UNUSED_ARG(bufferprocessed);
1844 return GATE_RESULT_NOTIMPLEMENTED;
1845 }
1846
1847 gate_bool_t gate_sshclient_channel_eof(gate_sshclient_channel_t* channel)
1848 {
1849 GATE_UNUSED_ARG(channel);
1850 return false;
1851 }
1852 gate_result_t gate_sshclient_channel_send_eof(gate_sshclient_channel_t* channel)
1853 {
1854 GATE_UNUSED_ARG(channel);
1855 return GATE_RESULT_NOTIMPLEMENTED;
1856 }
1857 gate_result_t gate_sshclient_channel_wait_eof(gate_sshclient_channel_t* channel)
1858 {
1859 GATE_UNUSED_ARG(channel);
1860 return GATE_RESULT_NOTIMPLEMENTED;
1861 }
1862 gate_result_t gate_sshclient_channel_setenv(gate_sshclient_channel_t* channel, gate_string_t const* name, gate_string_t const* value)
1863 {
1864 GATE_UNUSED_ARG(channel);
1865 GATE_UNUSED_ARG(name);
1866 GATE_UNUSED_ARG(value);
1867 return GATE_RESULT_NOTIMPLEMENTED;
1868 }
1869 gate_result_t gate_sshclient_channel_get_exit_signal(gate_sshclient_channel_t* channel, gate_string_t* ptr_signal, gate_string_t* ptr_errmsg, gate_string_t* ptr_langtag)
1870 {
1871 GATE_UNUSED_ARG(channel);
1872 GATE_UNUSED_ARG(ptr_signal);
1873 GATE_UNUSED_ARG(ptr_errmsg);
1874 GATE_UNUSED_ARG(ptr_langtag);
1875 return GATE_RESULT_NOTIMPLEMENTED;
1876 }
1877 gate_result_t gate_sshclient_channel_get_exit_status(gate_sshclient_channel_t* channel, int* ptr_status)
1878 {
1879 GATE_UNUSED_ARG(channel);
1880 GATE_UNUSED_ARG(ptr_status);
1881 return GATE_RESULT_NOTIMPLEMENTED;
1882 }
1883
1884 #endif
1885