From 66583499ed6270373dd9813e7d099fad44b7b644 Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Mon, 13 Jul 2020 18:10:36 +0200 Subject: tomsg_clientlib: Async connect routines This is quite complex, and it probably can be implemented with a simpler API and implementation. Regardless, it _seems_ to work. --- ssh/tomsg_clientlib.h | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) (limited to 'ssh/tomsg_clientlib.h') diff --git a/ssh/tomsg_clientlib.h b/ssh/tomsg_clientlib.h index 03f1fcf..e8cb3a7 100644 --- a/ssh/tomsg_clientlib.h +++ b/ssh/tomsg_clientlib.h @@ -21,6 +21,7 @@ enum tomsg_retval { // Error codes TOMSG_ERR_CONNECT, // Server refused connection + TOMSG_ERR_UNTRUSTED, // Hostkey was rejected TOMSG_ERR_CLOSED, // Server connection unexpectedly closed TOMSG_ERR_VERSION, // Server protocol version incompatible TOMSG_ERR_TRANSPORT, // Error in the underlying SSH transport @@ -45,6 +46,8 @@ const char* tomsg_strerror(enum tomsg_retval code); // If successful, stores a new connection structure in 'client' and returns // TOMSG_OK. On error, stores NULL in 'client' and returns an error code. +// This function blocks until version negotiation is complete. For a +// non-blocking version, see tomsg_async_connect(). enum tomsg_retval tomsg_connect( const char *hostname, int port, tomsg_hostkey_checker_t checker, @@ -52,6 +55,55 @@ enum tomsg_retval tomsg_connect( struct tomsg_client **client // output ); +struct tomsg_async_connect; + +// If this returns an error code, it stores NULL in *client. +enum tomsg_retval tomsg_async_connect( + const char *hostname, int port, + struct tomsg_async_connect **client // output +); + +enum tomsg_async_connect_event_type { + TOMSG_AC_HOSTKEY, // should check hostkey, see 'key' and tomsg_async_{accept,reject}() + TOMSG_AC_SUCCESS, // the tomsg_async_connect struct has been freed; connection is in 'client' +}; + +struct tomsg_async_connect_event { + enum tomsg_async_connect_event_type type; + + union { + struct { + // Same as arguments to tomsg_hostkey_checker_t + unsigned char *hostkey; + size_t length; + } key; // TOMSG_AC_HOSTKEY + struct tomsg_client *client; // TOMSG_AC_SUCCESS + }; +}; + +void tomsg_async_connect_event_nullify(struct tomsg_async_connect_event *event); + +// Will return TOMSG_ERR_AGAIN if no events are available at present. In that +// case, use poll(2) on the file descriptor from tomsg_async_connect_poll_fd(). +// NOTE: If an error message is returned, the struct tomsg_async_connect will +// already be freed. +enum tomsg_retval tomsg_async_connect_next_event( + struct tomsg_async_connect *client, + struct tomsg_async_connect_event *event // output +); + +// Accept or reject the hostkey obtained using a prior invocation of +// tomsg_async_connect_next_event(). Pass true to accept, false to reject. In +// case of rejection, as well as on error, the connection will be closed and +// the client structure freed. A successful rejection is indicated by +// TOMSG_ERR_UNTRUSTED. +enum tomsg_retval tomsg_async_connect_accept(struct tomsg_async_connect *client, bool accept); + +// 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 tomsg_async_connect_next_event(). +int tomsg_async_connect_poll_fd(const struct tomsg_async_connect *client); + // 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. -- cgit v1.2.3-54-g00ecf