GCC Code Coverage Report


Directory: src/gate/
File: src/gate/net/sshclients.c
Date: 2025-12-12 23:40:09
Exec Total Coverage
Lines: 284 742 38.3%
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 96 static void* gate_libssh2_alloc(size_t count, void** ptr_abstract)
281 {
282 (void)ptr_abstract;
283 96 return gate_mem_alloc(count);
284 }
285
286 96 static void gate_libssh2_free(void* ptr, void** ptr_abstract)
287 {
288 (void)ptr_abstract;
289
1/2
✓ Branch 0 taken 96 times.
✗ Branch 1 not taken.
96 if (ptr)
290 {
291 96 gate_mem_dealloc(ptr);
292 }
293 96 }
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 1 gate_string_t host = GATE_STRING_INIT_EMPTY;
435
436 do
437 {
438 1 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
439 gate_socket_endpoint_t ep;
440 int ssh2_result;
441
442
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!session)
443 {
444 GATE_DEBUG_TRACE("Invalid state: no client session created");
445 ret = GATE_RESULT_INVALIDSTATE;
446 break;
447 }
448
449
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (client->handles[1] != (void*)GATE_SOCKET_INVALID)
450 {
451 GATE_DEBUG_TRACE("Invalid state: socket already opened, cannot connect");
452 ret = GATE_RESULT_INVALIDSTATE;
453 break;
454 }
455
456 1 ret = gate_socket_create_ex(client->socket_family, GATE_SOCKET_MSGTYPE_STREAM, GATE_SOCKET_PROTOCOL_TCP, &socket_handle);
457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
458
459 1 gate_mem_clear(&ep, sizeof(ep));
460
461
1/3
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
1 switch (client->socket_family)
462 {
463 1 case GATE_SOCKET_FAMILY_INET4:
464 {
465 1 ep.ip4.family = GATE_SOCKET_FAMILY_INET4;
466 1 ep.ip4.port = client->port;
467
468 1 gate_string_create_static(&host, client->server);
469 1 ret = gate_socket_parse_ip4(&host, &ep.ip4.address);
470 1 break;
471 }
472 case GATE_SOCKET_FAMILY_INET6:
473 {
474 ep.ip6.family = GATE_SOCKET_FAMILY_INET6;
475 ep.ip6.port = client->port;
476 ep.ip6.scope = 0;
477
478 gate_string_create_static(&host, client->server);
479 ret = gate_socket_parse_ip6(&host, &ep.ip6.address);
480 break;
481 }
482 default:
483 {
484 ret = GATE_RESULT_NOTSUPPORTED;
485 break;
486 }
487 }
488
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
489
490 1 gate_socket_set(socket_handle, GATE_SOCKET_OPTION_BLOCKING, 1);
491 1 gate_socket_set(socket_handle, GATE_SOCKET_OPTION_RECEIVETIMEOUT, GATE_SSH2_SESSION_TIMEOUT_DEFAULT);
492 1 gate_socket_set(socket_handle, GATE_SOCKET_OPTION_SENDTIMEOUT, GATE_SSH2_SESSION_TIMEOUT_DEFAULT);
493
494 1 ret = gate_socket_connect(socket_handle, &ep);
495
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
496 1 GATE_DEBUG_TRACE_VALUE((int)socket_handle);
497
498 1 lib.ssh2_session_set_blocking(session, 1);
499 1 lib.ssh2_session_set_timeout(session, GATE_SSH2_SESSION_TIMEOUT_DEFAULT);
500
501 /* ssh2_result = lib.ssh2_session_startup(session, (int)socket_handle); */
502 1 ssh2_result = lib.ssh2_session_handshake(session, (libssh2_socket_t)socket_handle);
503
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (ssh2_result != 0)
504 {
505 GATE_DEBUG_TRACE_SSH2_ERROR(session, "ssh2_session_handshake() failed");
506 ret = GATE_RESULT_FAILED;
507 break;
508 }
509
510 /* success state */
511 1 client->handles[1] = (void*)socket_handle;
512 1 socket_handle = GATE_SOCKET_INVALID;
513 1 ret = GATE_RESULT_OK;
514 } while (0);
515
516
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (socket_handle != GATE_SOCKET_INVALID)
517 {
518 gate_socket_close(socket_handle);
519 }
520
521 1 gate_string_release(&host);
522
523
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(ret, "gate_sshclient_init_connection() failed");
524 1 return ret;
525 }
526
527
528 1 static gate_result_t gate_sshclient_authenticate(gate_sshclient_t* client, gate_string_t const* user, gate_string_t const* pass)
529 {
530 1 gate_result_t ret = GATE_RESULT_FAILED;
531 1 gate_string_t lst = GATE_STRING_INIT_EMPTY;
532
533 do
534 {
535 1 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
536 int ssh2_result;
537 1 char* 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
590 do
591 {
592 1 ret = gate_sshclient_init_connection(client);
593
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_BREAK_IF_FAILED(ret);
594
595 1 ret = gate_sshclient_authenticate(client, user, password);
596
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (GATE_FAILED(ret))
597 {
598 /* authentication failed -> release socket */
599 gate_socket_t socket_handle = (gate_socket_t)client->handles[1];
600 client->handles[1] = (void*)GATE_SOCKET_INVALID;
601 gate_socket_close(socket_handle);
602 break;
603 }
604
605 /* success state */
606 1 ret = GATE_RESULT_OK;
607 } while (0);
608
609
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 GATE_DEBUG_TRACE_FAILED(ret, "gate_sshclient_connect() failed");
610 1 return ret;
611 }
612
613
614 gate_result_t gate_sshclient_connect_keys(
615 gate_sshclient_t* client, gate_string_t const* user,
616 gate_string_t const* pubkey, gate_string_t const* privkey, gate_string_t const* passphrase,
617 gate_enumint_t flags)
618 {
619 gate_result_t ret = GATE_RESULT_FAILED;
620
621 ret = gate_sshclient_init_connection(client);
622 GATE_RETURN_IF_FAILED(ret);
623
624 do
625 {
626 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
627 char const* str_user = gate_string_ptr(user, 0);
628 gate_size_t len_user = gate_string_length(user);
629 char const* str_pubkey = gate_string_ptr(pubkey, 0);
630 gate_size_t len_pubkey = gate_string_length(pubkey);
631 char const* str_privkey = gate_string_ptr(privkey, 0);
632 gate_size_t len_privkey = gate_string_length(privkey);
633 char pass[1024];
634 char const* ptr_passphrase = NULL;
635 int ssh_error;
636
637 if (gate_string_to_buffer(passphrase, pass, sizeof(pass)) > 0)
638 {
639 ptr_passphrase = &pass[0];
640 }
641
642 ssh_error = lib.ssh2_userauth_publickey_frommemory(session,
643 str_user, len_user,
644 str_pubkey, len_pubkey,
645 str_privkey, len_privkey,
646 ptr_passphrase);
647
648 if (ssh_error != 0)
649 {
650 /* authentication failed -> release socket */
651 gate_socket_t socket_handle = (gate_socket_t)client->handles[1];
652 client->handles[1] = (void*)GATE_SOCKET_INVALID;
653 gate_socket_close(socket_handle);
654 switch (ssh_error)
655 {
656 case LIBSSH2_ERROR_ALLOC: ret = GATE_RESULT_OUTOFMEMORY; break;
657 case LIBSSH2_ERROR_SOCKET_SEND: ret = GATE_RESULT_INVALIDOUTPUT; break;
658 case LIBSSH2_ERROR_SOCKET_TIMEOUT: ret = GATE_RESULT_TIMEOUT; break;
659 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED: ret = GATE_RESULT_INVALIDINPUT; break;
660 case LIBSSH2_ERROR_AUTHENTICATION_FAILED: ret = GATE_RESULT_ACCESSDENIED; break;
661 default: ret = GATE_RESULT_FAILED; break;
662 }
663 break;
664 }
665
666 /* success state */
667 ret = GATE_RESULT_OK;
668 } while (0);
669
670 GATE_DEBUG_TRACE_FAILED(ret, "gate_sshclient_connect_keys() failed");
671 return ret;
672 }
673
674
675 2 gate_result_t gate_sshclient_disconnect(gate_sshclient_t* client)
676 {
677 2 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
678 2 gate_socket_t socket_handle = (gate_socket_t)client->handles[1];
679
680
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
2 if (session)
681 {
682 2 lib.ssh2_session_disconnect_ex(session, SSH_DISCONNECT_BY_APPLICATION, "", "");
683 }
684
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
2 if (socket_handle != GATE_SOCKET_INVALID)
685 {
686 1 gate_socket_close(socket_handle);
687 1 client->handles[1] = (void*)GATE_SOCKET_INVALID;
688 }
689 2 return GATE_RESULT_OK;
690 }
691
692 1 gate_result_t gate_sshclient_open_sftp(gate_sshclient_t* client, gate_sshclient_sftp_t* sftp)
693 {
694
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SESSION* session = client ? (LIBSSH2_SESSION*)client->handles[0] : NULL;
695 LIBSSH2_SFTP* ptr_sftp;
696
697
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!session)
698 {
699 GATE_DEBUG_TRACE("missing client session");
700 return GATE_RESULT_NULLPOINTER;
701
702 }
703
704 1 ptr_sftp = lib.ssh2_sftp_init(session);
705
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_sftp)
706 {
707 GATE_DEBUG_TRACE("ssh2_sftp_init() failed");
708 return GATE_RESULT_FAILED;
709 }
710
711
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sftp)
712 {
713 1 *sftp = (gate_sshclient_sftp_t)ptr_sftp;
714 }
715 else
716 {
717 lib.ssh2_sftp_shutdown(ptr_sftp);
718 }
719
720 1 return GATE_RESULT_OK;
721 }
722
723 1 gate_result_t gate_sshclient_release(gate_sshclient_t* client)
724 {
725 1 LIBSSH2_SESSION* session = (LIBSSH2_SESSION*)client->handles[0];
726
727 1 gate_sshclient_disconnect(client);
728 1 lib.ssh2_session_free(session);
729
730 1 return GATE_RESULT_OK;
731 }
732
733
734 1 gate_result_t gate_sshclient_close_sftp(gate_sshclient_sftp_t* sftp)
735 {
736
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
737
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (ptr_sftp)
738 {
739 1 lib.ssh2_sftp_shutdown(ptr_sftp);
740 1 *sftp = NULL;
741 }
742 1 return GATE_RESULT_OK;
743 }
744
745 1 gate_result_t gate_sshclient_sftp_open(gate_sshclient_sftp_t* sftp, gate_string_t const* path, gate_enumint_t stream_open_flags,
746 gate_sshclient_sftp_handle_t* sftp_handle)
747 {
748 char file_path[GATE_MAX_FILEPATH_LENGTH];
749 gate_size_t file_path_length;
750
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
751 1 unsigned long flags = 0;
752 1 long mode = LIBSSH2_SFTP_S_IFREG;
753 1 int open_type = LIBSSH2_SFTP_OPENFILE;
754 LIBSSH2_SFTP_HANDLE* ptr_handle;
755
756
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_sftp)
757 {
758 GATE_DEBUG_TRACE("Missing sftp session");
759 return GATE_RESULT_NULLPOINTER;
760 }
761
762 1 file_path_length = gate_string_to_buffer(path, file_path, sizeof(file_path));
763
764
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)
765 {
766 1 case GATE_STREAM_OPEN_READ:
767 1 flags = LIBSSH2_FXF_READ;
768 1 break;
769 case GATE_STREAM_OPEN_WRITE:
770 flags = LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC;
771 mode |= LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP /*| LIBSSH2_SFTP_S_IROTH*/;
772 break;
773 case GATE_STREAM_OPEN_READWRITE:
774 flags = LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE;
775 break;
776 case GATE_STREAM_OPEN_APPEND:
777 case GATE_STREAM_OPEN_APPENDWRITE:
778 flags = LIBSSH2_FXF_APPEND | LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT;
779 break;
780 case GATE_STREAM_OPEN_APPENDREADWRITE:
781 flags = LIBSSH2_FXF_APPEND | LIBSSH2_FXF_READ | LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT;
782 break;
783 default:
784 GATE_DEBUG_TRACE("gate_sshclient_sftp_open(): unsupported open-flags");
785 return GATE_RESULT_INVALIDARG;
786 }
787
788 1 ptr_handle = lib.ssh2_sftp_open_ex(ptr_sftp, file_path, (unsigned int)file_path_length, flags, mode, open_type);
789
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
790 {
791 GATE_DEBUG_TRACE("ssh2_sftp_open_ex() failed");
792 return GATE_RESULT_FAILED;
793 }
794
795
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sftp_handle)
796 {
797 1 *sftp_handle = (gate_sshclient_sftp_handle_t)ptr_handle;
798 }
799 else
800 {
801 lib.ssh2_sftp_close_handle(ptr_handle);
802 }
803 1 return GATE_RESULT_OK;
804 }
805
806 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)
807 {
808
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;
809 ssize_t result;
810
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
811 {
812 GATE_DEBUG_TRACE("Missing sftp handle");
813 return GATE_RESULT_NULLPOINTER;
814 }
815 1 result = lib.ssh2_sftp_read(ptr_handle, buffer, capacity);
816
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result < 0)
817 {
818 GATE_DEBUG_TRACE("ssh2_sftp_read() failed");
819 return GATE_RESULT_FAILED;
820 }
821
822
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (returned)
823 {
824 1 *returned = (gate_size_t)result;
825 }
826 1 return GATE_RESULT_OK;
827 }
828 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)
829 {
830 LIBSSH2_SFTP_HANDLE* ptr_handle = sftp_handle ? *((LIBSSH2_SFTP_HANDLE**)sftp_handle) : NULL;
831 ssize_t result;
832 if (!ptr_handle)
833 {
834 GATE_DEBUG_TRACE("Missing sftp handle");
835 return GATE_RESULT_NULLPOINTER;
836 }
837 result = lib.ssh2_sftp_write(ptr_handle, buffer, length);
838 if (result < 0)
839 {
840 GATE_DEBUG_TRACE("ssh2_sftp_write() failed");
841 return GATE_RESULT_FAILED;
842 }
843
844 if (written)
845 {
846 *written = (gate_size_t)result;
847 }
848 return GATE_RESULT_OK;
849 }
850 1 gate_result_t gate_sshclient_sftp_seek(gate_sshclient_sftp_handle_t* sftp_handle, gate_uint64_t position)
851 {
852
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;
853
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
854 {
855 GATE_DEBUG_TRACE("Missing sftp handle");
856 return GATE_RESULT_NULLPOINTER;
857 }
858 1 lib.ssh2_sftp_seek64(ptr_handle, position);
859 1 return GATE_RESULT_OK;
860 }
861 1 gate_result_t gate_sshclient_sftp_tell(gate_sshclient_sftp_handle_t* sftp_handle, gate_uint64_t* position)
862 {
863
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;
864
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
865 {
866 GATE_DEBUG_TRACE("Missing sftp handle");
867 return GATE_RESULT_NULLPOINTER;
868 }
869
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (position)
870 {
871 1 *position = lib.ssh2_sftp_tell64(ptr_handle);
872 }
873 1 return GATE_RESULT_OK;
874 }
875 2 gate_result_t gate_sshclient_sftp_close(gate_sshclient_sftp_handle_t* sftp_handle)
876 {
877
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;
878
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (!ptr_handle)
879 {
880 GATE_DEBUG_TRACE("Missing sftp handle");
881 return GATE_RESULT_NULLPOINTER;
882 }
883 2 lib.ssh2_sftp_close_handle(ptr_handle);
884 2 *sftp_handle = NULL;
885 2 return GATE_RESULT_OK;
886 }
887 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)
888 {
889 char file_path[GATE_MAX_FILEPATH_LENGTH];
890 gate_size_t file_path_length;
891
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
892 LIBSSH2_SFTP_HANDLE* ptr_handle;
893
894
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_sftp)
895 {
896 GATE_DEBUG_TRACE("Missing sftp session");
897 return GATE_RESULT_NULLPOINTER;
898 }
899
900 1 file_path_length = gate_string_to_buffer(path, file_path, sizeof(file_path));
901
902 1 ptr_handle = lib.ssh2_sftp_open_ex(ptr_sftp, file_path, (unsigned int)file_path_length, 0, 0, LIBSSH2_SFTP_OPENDIR);
903
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_handle)
904 {
905 GATE_DEBUG_TRACE("ssh2_sftp_open_ex() failed");
906 return GATE_RESULT_FAILED;
907 }
908
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 if (sftp_handle)
909 {
910 1 *sftp_handle = (gate_sshclient_sftp_handle_t)ptr_handle;
911 }
912 else
913 {
914 lib.ssh2_sftp_close_handle(ptr_handle);
915 }
916 1 return GATE_RESULT_OK;
917 }
918
919 19 static void convert_attributes(LIBSSH2_SFTP_ATTRIBUTES* ptr_attr, gate_file_properties_t* file_props)
920 {
921
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (ptr_attr->flags & LIBSSH2_SFTP_ATTR_SIZE)
922 {
923 19 file_props->size = ptr_attr->filesize;
924 }
925
926
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (ptr_attr->flags & LIBSSH2_SFTP_ATTR_PERMISSIONS)
927 {
928
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;
929
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;
930
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;
931
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;
932
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;
933
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;
934
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;
935
936
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;
937
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;
938
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;
939
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;
940
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;
941
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;
942
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;
943
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;
944
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;
945 }
946
947
1/2
✓ Branch 0 taken 19 times.
✗ Branch 1 not taken.
19 if (ptr_attr->flags & LIBSSH2_SFTP_ATTR_ACMODTIME)
948 {
949 19 gate_time_from_unix(ptr_attr->atime, &file_props->time_accessed);
950 19 gate_time_from_unix(ptr_attr->mtime, &file_props->time_modified);
951 19 gate_time_from_unix(ptr_attr->atime, &file_props->time_created);
952 }
953
954 19 }
955
956 19 gate_result_t gate_sshclient_sftp_readdir(gate_sshclient_sftp_handle_t* sftp_handle, gate_file_entry_t* file_entry)
957 {
958
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;
959 char buffer[GATE_MAX_FILENAME_LENGTH];
960 char longentry[GATE_MAX_COPYBUFFER_LENGTH];
961 19 LIBSSH2_SFTP_ATTRIBUTES attribs = GATE_INIT_EMPTY;
962 int result;
963
964
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (!sftp_handle)
965 {
966 GATE_DEBUG_TRACE("Missing sftp session");
967 return GATE_RESULT_NULLPOINTER;
968 }
969
970 19 attribs.flags = LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID | LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
971 19 result = lib.ssh2_sftp_readdir_ex(ptr_handle, buffer, sizeof(buffer), longentry, sizeof(longentry), &attribs);
972
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if (result < 0)
973 {
974 return GATE_RESULT_FAILED;
975 }
976
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 18 times.
19 else if (result == 0)
977 {
978 1 return GATE_RESULT_NODATA;
979 }
980
981
1/2
✓ Branch 0 taken 18 times.
✗ Branch 1 not taken.
18 if (file_entry)
982 {
983 18 buffer[sizeof(buffer) - 1] = 0;
984 18 gate_mem_clear(file_entry, sizeof(gate_file_entry_t));
985 18 gate_str_print_text(file_entry->name, sizeof(file_entry->name), buffer, gate_str_length(buffer));
986 18 convert_attributes(&attribs, &file_entry->props);
987 }
988 18 return GATE_RESULT_OK;
989 }
990
991 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)
992 {
993 gate_result_t result;
994 gate_sshclient_sftp_handle_t handle = NULL;
995 gate_bool_t continue_readdir = true;
996 gate_bool_t const need_slash = !gate_string_ends_with_char(path, '/');
997
998 result = gate_sshclient_sftp_opendir(sftp, path, &handle);
999 if (GATE_FAILED(result))
1000 {
1001 return result;
1002 }
1003
1004 while (continue_readdir)
1005 {
1006 gate_file_entry_t entry;
1007 gate_size_t namelen;
1008
1009 result = gate_sshclient_sftp_readdir(&handle, &entry);
1010 GATE_BREAK_IF_FAILED(result);
1011
1012 namelen = gate_str_length(entry.name);
1013
1014 if ((gate_str_compare(entry.name, namelen, ".", 1) == 0)
1015 || (gate_str_compare(entry.name, namelen, "..", 2) == 0))
1016 {
1017 /* skip pseudo-dir-entries */
1018 }
1019 else
1020 {
1021 gate_size_t len = gate_str_print_text(entry.path, sizeof(entry.path) - 1, path->str, path->length);
1022 if (need_slash)
1023 {
1024 entry.path[len] = '/';
1025 ++len;
1026 }
1027 gate_str_print_text(&entry.path[len], sizeof(entry.path) - len, entry.name, namelen);
1028
1029 continue_readdir = callback(&entry, userdata);
1030 }
1031 }
1032
1033 gate_sshclient_sftp_close(&handle);
1034 if (result == GATE_RESULT_NODATA)
1035 {
1036 result = GATE_RESULT_OK;
1037 }
1038 return result;
1039 }
1040
1041
1042 gate_result_t gate_sshclient_sftp_mkdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1043 {
1044 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1045 char buffer[GATE_MAX_FILEPATH_LENGTH];
1046 gate_size_t buffer_len;
1047 int result;
1048
1049 if (!ptr_sftp)
1050 {
1051 GATE_DEBUG_TRACE("Missing sftp session");
1052 return GATE_RESULT_NULLPOINTER;
1053 }
1054
1055 buffer_len = gate_string_to_buffer(path, buffer, sizeof(buffer));
1056
1057 result = lib.ssh2_sftp_mkdir_ex(ptr_sftp, buffer, (unsigned int)buffer_len, 0775);
1058 if (result != 0)
1059 {
1060 GATE_DEBUG_TRACE("ssh2_sftp_mkdir_ex() failed");
1061 return GATE_RESULT_FAILED;
1062 }
1063 return GATE_RESULT_OK;
1064 }
1065
1066 gate_result_t gate_sshclient_sftp_rmdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1067 {
1068 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1069 char buffer[GATE_MAX_FILEPATH_LENGTH];
1070 gate_size_t buffer_len;
1071 int result;
1072
1073 if (!ptr_sftp)
1074 {
1075 GATE_DEBUG_TRACE("Missing sftp session");
1076 return GATE_RESULT_NULLPOINTER;
1077 }
1078
1079 buffer_len = gate_string_to_buffer(path, buffer, sizeof(buffer));
1080
1081 result = lib.ssh2_sftp_rmdir_ex(ptr_sftp, buffer, (unsigned int)buffer_len);
1082 if (result != 0)
1083 {
1084 GATE_DEBUG_TRACE("ssh2_sftp_rmdir_ex() failed");
1085 return GATE_RESULT_FAILED;
1086 }
1087 return GATE_RESULT_OK;
1088 }
1089 gate_result_t gate_sshclient_sftp_unlink(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1090 {
1091 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1092 char buffer[GATE_MAX_FILEPATH_LENGTH];
1093 gate_size_t buffer_len;
1094 int result;
1095
1096 if (!ptr_sftp)
1097 {
1098 GATE_DEBUG_TRACE("Missing sftp session");
1099 return GATE_RESULT_NULLPOINTER;
1100 }
1101
1102 buffer_len = gate_string_to_buffer(path, buffer, sizeof(buffer));
1103
1104 result = lib.ssh2_sftp_unlink_ex(ptr_sftp, buffer, (unsigned int)buffer_len);
1105 if (result != 0)
1106 {
1107 GATE_DEBUG_TRACE("ssh2_sftp_unlink_ex() failed");
1108 return GATE_RESULT_FAILED;
1109 }
1110 return GATE_RESULT_OK;
1111 }
1112 gate_result_t gate_sshclient_sftp_rename(gate_sshclient_sftp_t* sftp, gate_string_t const* src_path, gate_string_t const* dst_path)
1113 {
1114 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1115 char src_buffer[GATE_MAX_FILEPATH_LENGTH];
1116 char dst_buffer[GATE_MAX_FILEPATH_LENGTH];
1117 gate_size_t src_buffer_len;
1118 gate_size_t dst_buffer_len;
1119 int result;
1120
1121 if (!ptr_sftp)
1122 {
1123 GATE_DEBUG_TRACE("Missing sftp session");
1124 return GATE_RESULT_NULLPOINTER;
1125 }
1126
1127 src_buffer_len = gate_string_to_buffer(src_path, src_buffer, sizeof(src_buffer));
1128 dst_buffer_len = gate_string_to_buffer(dst_path, dst_buffer, sizeof(dst_buffer));
1129
1130 result = lib.ssh2_sftp_rename_ex(ptr_sftp, src_buffer, (unsigned int)src_buffer_len,
1131 dst_buffer, (unsigned int)dst_buffer_len, LIBSSH2_SFTP_RENAME_ATOMIC);
1132 if (result != 0)
1133 {
1134 GATE_DEBUG_TRACE("ssh2_sftp_rename_ex() failed");
1135 return GATE_RESULT_FAILED;
1136 }
1137 return GATE_RESULT_OK;
1138 }
1139 1 gate_result_t gate_sshclient_sftp_stat(gate_sshclient_sftp_t* sftp, gate_string_t const* path, gate_file_properties_t* file_props)
1140 {
1141
1/2
✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
1 LIBSSH2_SFTP* ptr_sftp = sftp ? *((LIBSSH2_SFTP**)sftp) : NULL;
1142 char buffer[GATE_MAX_FILEPATH_LENGTH];
1143 gate_size_t buffer_len;
1144 int result;
1145 1 LIBSSH2_SFTP_ATTRIBUTES attribs = GATE_INIT_EMPTY;
1146
1147
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (!ptr_sftp)
1148 {
1149 GATE_DEBUG_TRACE("Missing sftp session");
1150 return GATE_RESULT_NULLPOINTER;
1151 }
1152
1153 1 buffer_len = gate_string_to_buffer(path, buffer, sizeof(buffer));
1154
1155 1 attribs.flags = LIBSSH2_SFTP_ATTR_SIZE | LIBSSH2_SFTP_ATTR_UIDGID | LIBSSH2_SFTP_ATTR_PERMISSIONS | LIBSSH2_SFTP_ATTR_ACMODTIME;
1156 1 result = lib.ssh2_sftp_stat_ex(ptr_sftp, buffer, (unsigned int)buffer_len, LIBSSH2_SFTP_LSTAT, &attribs);
1157
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
1 if (result != 0)
1158 {
1159 GATE_DEBUG_TRACE("ssh2_sftp_stat_ex() failed");
1160 return GATE_RESULT_FAILED;
1161 }
1162
1163 1 convert_attributes(&attribs, file_props);
1164
1165 1 return GATE_RESULT_OK;
1166 }
1167
1168
1169 typedef struct ssh_channel_impl_class
1170 {
1171 LIBSSH2_CHANNEL* channel;
1172 gate_size_t read_buffer_used;
1173 gate_size_t read_buffer_offset;
1174 char read_buffer[8192];
1175
1176 gate_size_t err_buffer_used;
1177 gate_size_t err_buffer_offset;
1178 char err_buffer[8192];
1179 } ssh_channel_impl_t;
1180
1181 gate_result_t gate_sshclient_channel_open(gate_sshclient_t* client, gate_sshclient_channel_t* ptr_channel)
1182 {
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 ssh_channel_impl_t* impl = NULL;
1204 impl = (ssh_channel_impl_t*)gate_mem_alloc(sizeof(ssh_channel_impl_t));
1205 if (NULL == impl)
1206 {
1207 lib.ssh2_channel_close(channel);
1208 return GATE_RESULT_OUTOFMEMORY;
1209 }
1210 impl->channel = channel;
1211 impl->read_buffer_offset = 0;
1212 impl->read_buffer_used = 0;
1213 *ptr_channel = (gate_sshclient_channel_t)impl;
1214 }
1215 else
1216 {
1217 lib.ssh2_channel_close(channel);
1218 }
1219 return GATE_RESULT_OK;
1220 }
1221
1222 gate_result_t gate_sshclient_channel_close(gate_sshclient_channel_t* channel)
1223 {
1224 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1225 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1226 int result;
1227
1228 if (!ssh_channel)
1229 {
1230 return GATE_RESULT_NULLPOINTER;
1231 }
1232 result = lib.ssh2_channel_close(ssh_channel);
1233 if (0 != result)
1234 {
1235 return GATE_RESULT_LOCKED;
1236 }
1237 return GATE_RESULT_OK;
1238 }
1239
1240 gate_result_t gate_sshclient_channel_free(gate_sshclient_channel_t* channel)
1241 {
1242 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1243 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1244 int result;
1245
1246 if (!ssh_channel)
1247 {
1248 return GATE_RESULT_NULLPOINTER;
1249 }
1250 result = lib.ssh2_channel_free(ssh_channel);
1251 if (0 != result)
1252 {
1253 return GATE_RESULT_LOCKED;
1254 }
1255
1256 gate_mem_dealloc(impl);
1257 *channel = NULL;
1258 return GATE_RESULT_OK;
1259 }
1260
1261 gate_result_t gate_sshclient_channel_exec(gate_sshclient_channel_t* channel, gate_string_t const* command)
1262 {
1263 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1264 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1265 gate_cstrbuffer_t sb;
1266 int result;
1267 char const* req_name;
1268 unsigned int req_name_len;
1269 char const* ptr_command;
1270 unsigned int command_length;
1271
1272 if (!ssh_channel)
1273 {
1274 return GATE_RESULT_NULLPOINTER;
1275 }
1276 if (NULL == gate_cstrbuffer_create_string(&sb, command, false))
1277 {
1278 return GATE_RESULT_OUTOFMEMORY;
1279 }
1280
1281 command_length = (unsigned int)gate_cstrbuffer_length(&sb);
1282 if (command_length == 0)
1283 {
1284 ptr_command = NULL;
1285 req_name = "shell";
1286 req_name_len = 5;
1287 }
1288 else
1289 {
1290 ptr_command = gate_cstrbuffer_get(&sb);
1291 req_name = "exec";
1292 req_name_len = 4;
1293 }
1294
1295 result = lib.ssh2_channel_process_startup(ssh_channel, req_name, req_name_len, ptr_command, command_length);
1296 gate_cstrbuffer_destroy(&sb);
1297 if (0 != result)
1298 {
1299 return GATE_RESULT_FAILED;
1300 }
1301 return GATE_RESULT_OK;
1302 }
1303
1304 gate_result_t gate_sshclient_channel_canread(gate_sshclient_channel_t* channel, gate_enumint_t stream_type, gate_bool_t* ptr_canread)
1305 {
1306 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1307 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1308 ssize_t bytes_returned;
1309 int stream_id;
1310
1311 if (!ssh_channel || !ptr_canread)
1312 {
1313 return GATE_RESULT_NULLPOINTER;
1314 }
1315
1316 switch (stream_type)
1317 {
1318 case GATE_SSHCLIENT_STREAMTYPE_DEFAULT: stream_id = 0; break;
1319 case GATE_SSHCLIENT_STREAMTYPE_ERROR: stream_id = SSH_EXTENDED_DATA_STDERR; break;
1320 default: stream_id = stream_type; break;
1321 }
1322
1323 switch (stream_type)
1324 {
1325 case GATE_SSHCLIENT_STREAMTYPE_DEFAULT:
1326 {
1327 if (impl->read_buffer_offset < impl->read_buffer_used)
1328 {
1329 /* something is in the buffer */
1330 *ptr_canread = true;
1331 return GATE_RESULT_OK;
1332 }
1333
1334 lib.ssh2_channel_set_blocking(ssh_channel, 0);
1335 bytes_returned = lib.ssh2_channel_read_ex(ssh_channel, stream_id, &impl->read_buffer[0], sizeof(impl->read_buffer));
1336 lib.ssh2_channel_set_blocking(ssh_channel, 1);
1337 if (bytes_returned == LIBSSH2_ERROR_EAGAIN)
1338 {
1339 /* cannot read, would block */
1340 *ptr_canread = false;
1341 return GATE_RESULT_OK;
1342 }
1343 if (bytes_returned < 0)
1344 {
1345 /* another error, will be returned with next read attempt */
1346 }
1347 else
1348 {
1349 /* buffer is filled with data to be returned on next read attempt */
1350 impl->read_buffer_offset = 0;
1351 impl->read_buffer_used = (gate_size_t)bytes_returned;
1352 }
1353 *ptr_canread = true;
1354 return GATE_RESULT_OK;
1355 }
1356 case GATE_SSHCLIENT_STREAMTYPE_ERROR:
1357 {
1358 if (impl->err_buffer_offset < impl->err_buffer_used)
1359 {
1360 /* something is in the buffer */
1361 *ptr_canread = true;
1362 return GATE_RESULT_OK;
1363 }
1364
1365 lib.ssh2_channel_set_blocking(ssh_channel, 0);
1366 bytes_returned = lib.ssh2_channel_read_ex(ssh_channel, stream_id, &impl->err_buffer[0], sizeof(impl->err_buffer));
1367 lib.ssh2_channel_set_blocking(ssh_channel, 1);
1368 if (bytes_returned == LIBSSH2_ERROR_EAGAIN)
1369 {
1370 /* cannot read, would block */
1371 *ptr_canread = false;
1372 return GATE_RESULT_OK;
1373 }
1374 if (bytes_returned < 0)
1375 {
1376 /* another error, will be returned with next read attempt */
1377 }
1378 else
1379 {
1380 /* buffer is filled with data to be returned on next read attempt */
1381 impl->err_buffer_offset = 0;
1382 impl->err_buffer_used = (gate_size_t)bytes_returned;
1383 }
1384 *ptr_canread = true;
1385 return GATE_RESULT_OK;
1386 }
1387 default:
1388 {
1389 break;
1390 }
1391 }
1392 return GATE_RESULT_NOTSUPPORTED;
1393 }
1394
1395 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)
1396 {
1397 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1398 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1399 ssize_t bytes_returned;
1400 int stream_id = 0;
1401
1402 if (!ssh_channel || !buffer)
1403 {
1404 return GATE_RESULT_NULLPOINTER;
1405 }
1406 switch (stream_type)
1407 {
1408 case GATE_SSHCLIENT_STREAMTYPE_DEFAULT:
1409 {
1410 if (impl->read_buffer_offset < impl->read_buffer_used)
1411 {
1412 /* we have data in the read buffer */
1413 if (bufferlen > (impl->read_buffer_used - impl->read_buffer_offset))
1414 {
1415 bufferlen = (impl->read_buffer_used - impl->read_buffer_offset);
1416 }
1417 gate_mem_copy(buffer, &impl->read_buffer[impl->read_buffer_offset], bufferlen);
1418 impl->read_buffer_offset += bufferlen;
1419 if (bufferused)
1420 {
1421 *bufferused = bufferlen;
1422 }
1423 return GATE_RESULT_OK;
1424 }
1425 stream_id = 0;
1426 break;
1427 }
1428 case GATE_SSHCLIENT_STREAMTYPE_ERROR:
1429 {
1430 if (impl->err_buffer_offset < impl->err_buffer_used)
1431 {
1432 /* we have data in the error buffer */
1433 if (bufferlen > (impl->err_buffer_used - impl->err_buffer_offset))
1434 {
1435 bufferlen = (impl->err_buffer_used - impl->err_buffer_offset);
1436 }
1437 gate_mem_copy(buffer, &impl->err_buffer[impl->err_buffer_offset], bufferlen);
1438 impl->err_buffer_offset += bufferlen;
1439 if (bufferused)
1440 {
1441 *bufferused = bufferlen;
1442 }
1443 return GATE_RESULT_OK;
1444 }
1445 stream_id = SSH_EXTENDED_DATA_STDERR;
1446 break;
1447 }
1448 default:
1449 {
1450 stream_id = stream_type;
1451 break;
1452 }
1453 }
1454
1455 bytes_returned = lib.ssh2_channel_read_ex(ssh_channel, stream_id, buffer, bufferlen);
1456 if (bytes_returned < 0)
1457 {
1458 return GATE_RESULT_FAILED;
1459 }
1460 if (bufferused)
1461 {
1462 *bufferused = (gate_size_t)bytes_returned;
1463 }
1464 return GATE_RESULT_OK;
1465 }
1466
1467 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)
1468 {
1469 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1470 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1471 ssize_t bytes_written;
1472 int stream_id = 0;
1473
1474 if (!ssh_channel || !buffer)
1475 {
1476 return GATE_RESULT_NULLPOINTER;
1477 }
1478 switch (stream_type)
1479 {
1480 case GATE_SSHCLIENT_STREAMTYPE_DEFAULT: stream_id = 0; break;
1481 case GATE_SSHCLIENT_STREAMTYPE_ERROR: stream_id = SSH_EXTENDED_DATA_STDERR; break;
1482 default: stream_id = stream_type; break;
1483 }
1484
1485 bytes_written = lib.ssh2_channel_write_ex(ssh_channel, stream_id, buffer, bufferlen);
1486 if (bytes_written < 0)
1487 {
1488 return GATE_RESULT_FAILED;
1489 }
1490 if (bufferprocessed)
1491 {
1492 *bufferprocessed = (gate_size_t)bytes_written;
1493 }
1494 return GATE_RESULT_OK;
1495 }
1496
1497 gate_bool_t gate_sshclient_channel_eof(gate_sshclient_channel_t* channel)
1498 {
1499 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1500 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1501
1502 if (!ssh_channel)
1503 {
1504 return false;
1505 }
1506 return lib.ssh2_channel_eof(ssh_channel) == 1 ? true : false;
1507 }
1508
1509 gate_result_t gate_sshclient_channel_send_eof(gate_sshclient_channel_t* channel)
1510 {
1511 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1512 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1513 int result;
1514
1515 if (!ssh_channel)
1516 {
1517 return GATE_RESULT_NULLPOINTER;
1518 }
1519 result = lib.ssh2_channel_send_eof(ssh_channel);
1520 if (result != 0)
1521 {
1522 return GATE_RESULT_FAILED;
1523 }
1524 return GATE_RESULT_OK;
1525 }
1526
1527 gate_result_t gate_sshclient_channel_wait_eof(gate_sshclient_channel_t* channel)
1528 {
1529 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1530 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1531 int result;
1532
1533 if (!ssh_channel)
1534 {
1535 return GATE_RESULT_NULLPOINTER;
1536 }
1537 result = lib.ssh2_channel_wait_eof(ssh_channel);
1538 if (result != 0)
1539 {
1540 return GATE_RESULT_FAILED;
1541 }
1542 return GATE_RESULT_OK;
1543 }
1544
1545 gate_result_t gate_sshclient_channel_setenv(gate_sshclient_channel_t* channel, gate_string_t const* name, gate_string_t const* value)
1546 {
1547 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1548 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1549 int result;
1550
1551 if (!ssh_channel)
1552 {
1553 return GATE_RESULT_NULLPOINTER;
1554 }
1555 result = lib.ssh2_channel_setenv_ex(ssh_channel,
1556 gate_string_ptr(name, 0), (unsigned int)gate_string_length(name),
1557 gate_string_ptr(value, 0), (unsigned int)gate_string_length(value));
1558 if (result != 0)
1559 {
1560 return GATE_RESULT_FAILED;
1561 }
1562 return GATE_RESULT_OK;
1563 }
1564
1565 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)
1566 {
1567 gate_result_t ret;
1568 do
1569 {
1570 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1571 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1572 int result;
1573 char* exitsignal = NULL;
1574 size_t exitsignal_len = 0;
1575 char* errmsg = NULL;
1576 size_t errmsg_len = 0;
1577 char* langtag = NULL;
1578 size_t langtag_len = 0;
1579
1580 if (!ssh_channel)
1581 {
1582 ret = GATE_RESULT_NULLPOINTER;
1583 break;
1584 }
1585 result = lib.ssh2_channel_get_exit_signal(ssh_channel, &exitsignal, &exitsignal_len, &errmsg, &errmsg_len, &langtag, &langtag_len);
1586 if (result != 0)
1587 {
1588 ret = GATE_RESULT_FAILED;
1589 break;
1590 }
1591
1592 if (ptr_signal)
1593 {
1594 if (NULL == gate_string_create(ptr_signal, exitsignal, exitsignal_len))
1595 {
1596 ret = GATE_RESULT_OUTOFMEMORY;
1597 break;
1598 }
1599 }
1600 if (ptr_errmsg)
1601 {
1602 if (NULL == gate_string_create(ptr_errmsg, errmsg, errmsg_len))
1603 {
1604 if (ptr_signal) gate_string_release(ptr_signal);
1605 ret = GATE_RESULT_OUTOFMEMORY;
1606 break;
1607 }
1608 }
1609 if (ptr_langtag)
1610 {
1611 if (NULL == gate_string_create(ptr_langtag, langtag, langtag_len))
1612 {
1613 if (ptr_signal) gate_string_release(ptr_errmsg);
1614 if (ptr_signal) gate_string_release(ptr_signal);
1615 ret = GATE_RESULT_OUTOFMEMORY;
1616 break;
1617 }
1618 }
1619 /* success case */
1620 ret = GATE_RESULT_OK;
1621 } while (0);
1622
1623 return ret;
1624 }
1625
1626 gate_result_t gate_sshclient_channel_get_exit_status(gate_sshclient_channel_t* channel, int* ptr_status)
1627 {
1628 ssh_channel_impl_t* impl = channel ? (ssh_channel_impl_t*)*channel : NULL;
1629 LIBSSH2_CHANNEL* ssh_channel = impl ? impl->channel : NULL;
1630 int result;
1631
1632 if (!ssh_channel)
1633 {
1634 return GATE_RESULT_NULLPOINTER;
1635 }
1636 result = lib.ssh2_channel_get_exit_status(ssh_channel);
1637 if (ptr_status)
1638 {
1639 *ptr_status = result;
1640 }
1641 return GATE_RESULT_OK;
1642 }
1643
1644 #endif
1645
1646
1647
1648 #if defined(GATE_NET_SSHCLIENTS_NO_IMPL)
1649
1650 gate_result_t gate_sshclient_create(gate_sshclient_t* client, gate_string_t const* server, gate_uint16_t port)
1651 {
1652 GATE_UNUSED_ARG(client);
1653 GATE_UNUSED_ARG(server);
1654 GATE_UNUSED_ARG(port);
1655 return GATE_RESULT_NOTIMPLEMENTED;
1656 }
1657 gate_result_t gate_sshclient_connect(gate_sshclient_t* client,
1658 gate_string_t const* user, gate_string_t const* password, gate_enumint_t flags)
1659 {
1660 GATE_UNUSED_ARG(client);
1661 GATE_UNUSED_ARG(user);
1662 GATE_UNUSED_ARG(password);
1663 GATE_UNUSED_ARG(flags);
1664 return GATE_RESULT_NOTIMPLEMENTED;
1665 }
1666 gate_result_t gate_sshclient_connect_keys(gate_sshclient_t* client,
1667 gate_string_t const* user, gate_string_t const* pubkey, gate_string_t const* privkey,
1668 gate_string_t const* passphrase, gate_enumint_t flags)
1669 {
1670 GATE_UNUSED_ARG(client);
1671 GATE_UNUSED_ARG(user);
1672 GATE_UNUSED_ARG(pubkey);
1673 GATE_UNUSED_ARG(privkey);
1674 GATE_UNUSED_ARG(passphrase);
1675 GATE_UNUSED_ARG(flags);
1676 return GATE_RESULT_NOTIMPLEMENTED;
1677 }
1678
1679 gate_result_t gate_sshclient_disconnect(gate_sshclient_t* client)
1680 {
1681 GATE_UNUSED_ARG(client);
1682 return GATE_RESULT_NOTIMPLEMENTED;
1683 }
1684 gate_result_t gate_sshclient_release(gate_sshclient_t* client)
1685 {
1686 GATE_UNUSED_ARG(client);
1687 return GATE_RESULT_NOTIMPLEMENTED;
1688 }
1689
1690 gate_result_t gate_sshclient_open_sftp(gate_sshclient_t* client, gate_sshclient_sftp_t* sftp)
1691 {
1692 GATE_UNUSED_ARG(client);
1693 GATE_UNUSED_ARG(sftp);
1694 return GATE_RESULT_NOTIMPLEMENTED;
1695 }
1696 gate_result_t gate_sshclient_close_sftp(gate_sshclient_sftp_t* sftp)
1697 {
1698 GATE_UNUSED_ARG(sftp);
1699 return GATE_RESULT_NOTIMPLEMENTED;
1700 }
1701
1702 gate_result_t gate_sshclient_sftp_open(gate_sshclient_sftp_t* sftp, gate_string_t const* path,
1703 gate_enumint_t stream_open_flags, gate_sshclient_sftp_handle_t* sftp_handle)
1704 {
1705 GATE_UNUSED_ARG(sftp);
1706 GATE_UNUSED_ARG(path);
1707 GATE_UNUSED_ARG(stream_open_flags);
1708 GATE_UNUSED_ARG(sftp_handle);
1709 return GATE_RESULT_NOTIMPLEMENTED;
1710 }
1711 gate_result_t gate_sshclient_sftp_read(gate_sshclient_sftp_handle_t* sftp_handle,
1712 char* buffer, gate_size_t capacity, gate_size_t* returned)
1713 {
1714 GATE_UNUSED_ARG(sftp_handle);
1715 GATE_UNUSED_ARG(buffer);
1716 GATE_UNUSED_ARG(capacity);
1717 GATE_UNUSED_ARG(returned);
1718 return GATE_RESULT_NOTIMPLEMENTED;
1719 }
1720 gate_result_t gate_sshclient_sftp_write(gate_sshclient_sftp_handle_t* sftp_handle,
1721 char const* buffer, gate_size_t length, gate_size_t* written)
1722 {
1723 GATE_UNUSED_ARG(sftp_handle);
1724 GATE_UNUSED_ARG(buffer);
1725 GATE_UNUSED_ARG(length);
1726 GATE_UNUSED_ARG(written);
1727 return GATE_RESULT_NOTIMPLEMENTED;
1728 }
1729 gate_result_t gate_sshclient_sftp_seek(gate_sshclient_sftp_handle_t* sftp_handle, gate_uint64_t position)
1730 {
1731 GATE_UNUSED_ARG(sftp_handle);
1732 GATE_UNUSED_ARG(position);
1733 return GATE_RESULT_NOTIMPLEMENTED;
1734 }
1735 gate_result_t gate_sshclient_sftp_tell(gate_sshclient_sftp_handle_t* sftp_handle, gate_uint64_t* position)
1736 {
1737 GATE_UNUSED_ARG(sftp_handle);
1738 GATE_UNUSED_ARG(position);
1739 return GATE_RESULT_NOTIMPLEMENTED;
1740 }
1741 gate_result_t gate_sshclient_sftp_close(gate_sshclient_sftp_handle_t* sftp_handle)
1742 {
1743 GATE_UNUSED_ARG(sftp_handle);
1744 return GATE_RESULT_NOTIMPLEMENTED;
1745 }
1746 gate_result_t gate_sshclient_sftp_opendir(gate_sshclient_sftp_t* sftp, gate_string_t const* path,
1747 gate_sshclient_sftp_handle_t* sftp_handle)
1748 {
1749 GATE_UNUSED_ARG(sftp);
1750 GATE_UNUSED_ARG(path);
1751 GATE_UNUSED_ARG(sftp_handle);
1752 return GATE_RESULT_NOTIMPLEMENTED;
1753 }
1754 gate_result_t gate_sshclient_sftp_readdir(gate_sshclient_sftp_handle_t* sftp_handle, gate_file_entry_t* file_entry)
1755 {
1756 GATE_UNUSED_ARG(sftp_handle);
1757 GATE_UNUSED_ARG(file_entry);
1758 return GATE_RESULT_NOTIMPLEMENTED;
1759 }
1760 gate_result_t gate_sshclient_sftp_listdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path,
1761 gate_file_list_callback_t callback, void* userdata)
1762 {
1763 GATE_UNUSED_ARG(sftp);
1764 GATE_UNUSED_ARG(path);
1765 GATE_UNUSED_ARG(callback);
1766 GATE_UNUSED_ARG(userdata);
1767 return GATE_RESULT_NOTIMPLEMENTED;
1768 }
1769 gate_result_t gate_sshclient_sftp_mkdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1770 {
1771 GATE_UNUSED_ARG(sftp);
1772 GATE_UNUSED_ARG(path);
1773 return GATE_RESULT_NOTIMPLEMENTED;
1774 }
1775 gate_result_t gate_sshclient_sftp_rmdir(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1776 {
1777 GATE_UNUSED_ARG(sftp);
1778 GATE_UNUSED_ARG(path);
1779 return GATE_RESULT_NOTIMPLEMENTED;
1780 }
1781 gate_result_t gate_sshclient_sftp_unlink(gate_sshclient_sftp_t* sftp, gate_string_t const* path)
1782 {
1783 GATE_UNUSED_ARG(sftp);
1784 GATE_UNUSED_ARG(path);
1785 return GATE_RESULT_NOTIMPLEMENTED;
1786 }
1787 gate_result_t gate_sshclient_sftp_rename(gate_sshclient_sftp_t* sftp, gate_string_t const* src_path, gate_string_t const* dst_path)
1788 {
1789 GATE_UNUSED_ARG(sftp);
1790 GATE_UNUSED_ARG(src_path);
1791 GATE_UNUSED_ARG(dst_path);
1792 return GATE_RESULT_NOTIMPLEMENTED;
1793 }
1794 gate_result_t gate_sshclient_sftp_stat(gate_sshclient_sftp_t* sftp, gate_string_t const* path, gate_file_properties_t* file_props)
1795 {
1796 GATE_UNUSED_ARG(sftp);
1797 GATE_UNUSED_ARG(path);
1798 GATE_UNUSED_ARG(file_props);
1799 return GATE_RESULT_NOTIMPLEMENTED;
1800 }
1801
1802 gate_result_t gate_sshclient_channel_open(gate_sshclient_t* client, gate_sshclient_channel_t* ptr_channel)
1803 {
1804 GATE_UNUSED_ARG(client);
1805 GATE_UNUSED_ARG(ptr_channel);
1806 return GATE_RESULT_NOTIMPLEMENTED;
1807 }
1808 gate_result_t gate_sshclient_channel_close(gate_sshclient_channel_t* channel)
1809 {
1810 GATE_UNUSED_ARG(channel);
1811 return GATE_RESULT_NOTIMPLEMENTED;
1812 }
1813 gate_result_t gate_sshclient_channel_free(gate_sshclient_channel_t* channel)
1814 {
1815 GATE_UNUSED_ARG(channel);
1816 return GATE_RESULT_NOTIMPLEMENTED;
1817 }
1818 gate_result_t gate_sshclient_channel_exec(gate_sshclient_channel_t* channel, gate_string_t const* command)
1819 {
1820 GATE_UNUSED_ARG(channel);
1821 GATE_UNUSED_ARG(command);
1822 return GATE_RESULT_NOTIMPLEMENTED;
1823 }
1824 gate_result_t gate_sshclient_channel_canread(gate_sshclient_channel_t* channel, gate_enumint_t stream_type, gate_bool_t* ptr_canread)
1825 {
1826 GATE_UNUSED_ARG(channel);
1827 GATE_UNUSED_ARG(stream_type);
1828 GATE_UNUSED_ARG(ptr_canread);
1829 return GATE_RESULT_NOTIMPLEMENTED;
1830 }
1831 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)
1832 {
1833 GATE_UNUSED_ARG(channel);
1834 GATE_UNUSED_ARG(stream_type);
1835 GATE_UNUSED_ARG(buffer);
1836 GATE_UNUSED_ARG(bufferlen);
1837 GATE_UNUSED_ARG(bufferused);
1838 return GATE_RESULT_NOTIMPLEMENTED;
1839 }
1840 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)
1841 {
1842 GATE_UNUSED_ARG(channel);
1843 GATE_UNUSED_ARG(stream_type);
1844 GATE_UNUSED_ARG(buffer);
1845 GATE_UNUSED_ARG(bufferlen);
1846 GATE_UNUSED_ARG(bufferprocessed);
1847 return GATE_RESULT_NOTIMPLEMENTED;
1848 }
1849
1850 gate_bool_t gate_sshclient_channel_eof(gate_sshclient_channel_t* channel)
1851 {
1852 GATE_UNUSED_ARG(channel);
1853 return false;
1854 }
1855 gate_result_t gate_sshclient_channel_send_eof(gate_sshclient_channel_t* channel)
1856 {
1857 GATE_UNUSED_ARG(channel);
1858 return GATE_RESULT_NOTIMPLEMENTED;
1859 }
1860 gate_result_t gate_sshclient_channel_wait_eof(gate_sshclient_channel_t* channel)
1861 {
1862 GATE_UNUSED_ARG(channel);
1863 return GATE_RESULT_NOTIMPLEMENTED;
1864 }
1865 gate_result_t gate_sshclient_channel_setenv(gate_sshclient_channel_t* channel, gate_string_t const* name, gate_string_t const* value)
1866 {
1867 GATE_UNUSED_ARG(channel);
1868 GATE_UNUSED_ARG(name);
1869 GATE_UNUSED_ARG(value);
1870 return GATE_RESULT_NOTIMPLEMENTED;
1871 }
1872 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)
1873 {
1874 GATE_UNUSED_ARG(channel);
1875 GATE_UNUSED_ARG(ptr_signal);
1876 GATE_UNUSED_ARG(ptr_errmsg);
1877 GATE_UNUSED_ARG(ptr_langtag);
1878 return GATE_RESULT_NOTIMPLEMENTED;
1879 }
1880 gate_result_t gate_sshclient_channel_get_exit_status(gate_sshclient_channel_t* channel, int* ptr_status)
1881 {
1882 GATE_UNUSED_ARG(channel);
1883 GATE_UNUSED_ARG(ptr_status);
1884 return GATE_RESULT_NOTIMPLEMENTED;
1885 }
1886
1887 #endif
1888