aboutsummaryrefslogtreecommitdiff
path: root/ssh/sshnc.h
diff options
context:
space:
mode:
Diffstat (limited to 'ssh/sshnc.h')
-rw-r--r--ssh/sshnc.h102
1 files changed, 102 insertions, 0 deletions
diff --git a/ssh/sshnc.h b/ssh/sshnc.h
new file mode 100644
index 0000000..3e4bcfe
--- /dev/null
+++ b/ssh/sshnc.h
@@ -0,0 +1,102 @@
+#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.
+typedef bool (*sshnc_hostkey_checker_t)(const unsigned char *hash, size_t length);
+
+// 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. All error codes are negative.
+// 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.
+enum sshnc_retval sshnc_connect(
+ const char *hostname,
+ int port,
+ const char *username,
+ const char *subsystem,
+ sshnc_hostkey_checker_t 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.
+enum sshnc_retval sshnc_maybe_recv(
+ struct sshnc_client *client,
+ size_t capacity,
+ char *data, // output
+ size_t *length // output
+);