1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#pragma once
#include <stddef.h>
#include <stdbool.h>
// This "SSH netcat" library is very specifically oriented on the use of SSH in
// the tomsg protocol. That is: it is assumed that what you want is a
// connection with one simple channel with a particular subsystem, and that you
// need no authentication at all (i.e. authentication type 'none'). For
// anything more involved, use libssh directly.
struct sshnc_client;
// Should return 'true' if the key is trusted, 'false' otherwise. The hash is
// sha256 in byte form, not yet encoded in hexadecimal or similar. The
// 'userdata' pointer comes from the 'sshnc_connect' invocation.
typedef bool (*sshnc_hostkey_checker_t)(
const unsigned char *hash, size_t length, void *userdata);
// Convenience function to convert a hash to a human-readable form. Returns a
// reference to an internal static buffer.
const char* sshnc_print_hash(const unsigned char *hash, size_t length);
enum sshnc_retval {
// Successful result
SSHNC_OK = 0,
// Other status codes
SSHNC_EOF, // connection closed (sshnc_send, sshnc_maybe_recv)
SSHNC_AGAIN, // no data now, try again later (sshnc_maybe_recv)
// Error codes
SSHNC_ERR_CONNECT, // could not connect to host
SSHNC_ERR_UNTRUSTED, // hostkey checker rejected key
SSHNC_ERR_AUTH, // error authenticating to server
SSHNC_ERR_DENIED, // server did not accept 'none' authentication
SSHNC_ERR_CLOSED, // server unexpectedly closed connection
SSHNC_ERR_SUBSYSTEM, // server did not accept the subsystem channel
// Internal error codes
SSHNC_ERR_SESSION, // could not open libssh session
SSHNC_ERR_CHANNEL, // could not open libssh channel
SSHNC_ERR_OPTIONS, // could not set libssh options
SSHNC_ERR_GETKEY, // could not get key from libssh
SSHNC_ERR_CALLBACKS, // sshnc would not accept our callbacks structure
SSHNC_ERR_EVENT, // could not create libssh event poller
SSHNC_ERR_WRITE, // could not write to ssh channel
SSHNC_ERR_POLL, // could not poll the socket for activity
};
// Returns reference to internal static buffer.
// Additional error info may be stored in an internal thread_local buffer, and
// returned as part of the description.
const char* sshnc_strerror(enum sshnc_retval code);
// If successful, stores a new connection structure in 'client' and returns
// SSHNC_OK. On error, stores NULL in 'client' and returns an error code.
// The hostkey checker is invoked with the 'userdata' pointer.
enum sshnc_retval sshnc_connect(
const char *hostname,
int port,
const char *username,
const char *subsystem,
sshnc_hostkey_checker_t checker,
void *userdata, // for checker
struct sshnc_client **client // output
);
// Close the connection. This also frees the client structure. Note that even
// in case of an error, you must still call this function to prevent a memory
// leak.
void sshnc_close(struct sshnc_client *client);
// Returns a file descriptor that can be listened for read-ready events (using
// e.g. select(2) or poll(2)). Whenever it becomes ready for reading, you
// should call sshnc_maybe_recv(). If the connection was already closed
// internally due to an error, returns -1.
int sshnc_poll_fd(struct sshnc_client *client);
// Returns SSHNC_OK if successful, SSHNC_EOF if the connection was closed, or
// an error code otherwise.
enum sshnc_retval sshnc_send(
struct sshnc_client *client,
const char *data,
size_t length
);
// Retrieves up to 'capacity' bytes from the connection, and writes them to the
// buffer pointed to by 'data', and the number of bytes received to 'length'.
// Returns SSHNC_OK if successful, SSHNC_EOF if the connection was closed
// before any data was received, SSHNC_AGAIN if no data was available without
// blocking, or an error code otherwise.
// If the return value is not SSHNC_OK, 0 is stored in 'length'.
// Note that because this operation is non-blocking, the caller should only
// call this if it has a reason for suspecting there might be data (e.g.
// because poll(2) reported as such).
// This function also handles general ssh protocol messages, and must thus
// ALWAYS be called if there is readable data on the socket.
// NOTE: when calling this function, you must call it as long as it gives
// SSHNC_OK, because there might be more data than your buffer's size.
enum sshnc_retval sshnc_maybe_recv(
struct sshnc_client *client,
size_t capacity,
char *data, // output
size_t *length // output
);
|