aboutsummaryrefslogtreecommitdiff
path: root/ssh/sshnc.h
blob: 1e820757fbb5bf5c7e275a5415cb433677c5e844 (plain)
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,
	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
);