stund_protocol/lib.rs
1// Copyright 2018 Peter Williams <peter@newton.cx>
2// Licensed under the MIT License.
3
4#![deny(missing_docs)]
5#![doc(html_root_url = "https://docs.rs/stund_protocol/0.1.4")]
6
7//! The stund client-server communication protocol.
8//!
9//! [Stund](https://github.com/pkgw/stund) is a simple daemon for maintaining
10//! SSH tunnels. This crate defines the communication protocol used between
11//! the CLI client and the daemon that acts as the parent to SSH processes.
12//!
13//! The protocol only has a handful of commands at the moment. These are
14//! defined in this main module. The [`client`] submodule implements the
15//! client protocol.
16
17extern crate bytes;
18extern crate dirs;
19#[macro_use] extern crate failure;
20#[macro_use] extern crate futures;
21extern crate libc;
22extern crate serde;
23#[macro_use] extern crate serde_derive;
24#[macro_use] extern crate state_machine_future;
25extern crate tokio_codec;
26extern crate tokio_core;
27extern crate tokio_io;
28extern crate tokio_serde_bincode;
29extern crate tokio_uds;
30
31use failure::Error;
32use std::path::PathBuf;
33
34pub mod codecs;
35pub mod client;
36
37
38/// Get the path to the Unix domain socket used for client/server communication.
39///
40/// At the moment, this is fixed to `$HOME/.ssh/stund.sock`.
41pub fn get_socket_path() -> Result<PathBuf, Error> {
42 let mut p = dirs::home_dir().ok_or(format_err!("unable to determine your home directory"))?;
43 p.push(".ssh");
44 p.push("stund.sock");
45 Ok(p)
46}
47
48
49/// A message that the client may send to the server.
50///
51/// Some messages are only allowed in certain contexts.
52#[derive(Debug, Deserialize, PartialEq, Serialize)]
53pub enum ClientMessage {
54 /// Open an SSH tunnel.
55 Open(OpenParameters),
56
57 /// User input to be sent to SSH.
58 UserData(Vec<u8>),
59
60 /// Close an existing tunnel.
61 Close(CloseParameters),
62
63 /// Ask the daemon about its status.
64 QueryStatus,
65
66 /// Tell the daemon to exit.
67 Exit,
68
69 /// End the session.
70 Goodbye,
71}
72
73
74/// A message that the server may send to the client.
75#[derive(Debug, Deserialize, PartialEq, Serialize)]
76pub enum ServerMessage {
77 /// Generic message indicating success with whatever the client was asking
78 /// for.
79 Ok,
80
81 /// Generic message indicating an error with whatever the client was
82 /// asking for.
83 Error(String),
84
85 /// Output from an SSH process to be reported to the user by the client.
86 SshData(Vec<u8>),
87
88 /// In response to an `Open` message, indicates that this tunnel is
89 /// already open.
90 TunnelAlreadyOpen,
91
92 /// In response to a `Close` message, indicates that no such tunnel was
93 /// open.
94 TunnelNotOpen,
95
96 /// In response to a `QueryStatus` message, information about the server
97 /// status.
98 StatusResponse(StatusInformation),
99}
100
101
102/// Parameters to the "Open" command.
103///
104/// This command takes only a single parameter. The model of `stund` is that
105/// configuration of details like usernames should be done via the
106/// `$HOME/.ssh/config` file, and so are not needed here.
107#[derive(Debug, Deserialize, PartialEq, Serialize)]
108pub struct OpenParameters {
109 /// The hostname to which to connect.
110 pub host: String,
111}
112
113/// Possible outcomes of the "Open" command.
114///
115/// Besides these outcomes, an error may be signal by the return of a textual
116/// error message.
117#[derive(Clone, Copy, Debug, Eq, PartialEq)]
118pub enum OpenResult {
119 /// Indicates that the tunnel was successfully opened.
120 Success,
121
122 /// Indicates that nothing was done because a tunnel to the specified
123 /// host was already open.
124 AlreadyOpen,
125}
126
127
128/// Parameters to the "Close" command.
129#[derive(Debug, Deserialize, PartialEq, Serialize)]
130pub struct CloseParameters {
131 /// The hostname of the connection to be closed.
132 pub host: String,
133}
134
135/// Possible outcomes of the "Close" command.
136///
137/// Besides these outcomes, an error may be signal by the return of a textual
138/// error message.
139#[derive(Clone, Copy, Debug, Eq, PartialEq)]
140pub enum CloseResult {
141 /// Indicates that the tunnel was successfully opened.
142 Success,
143
144 /// Indicates that nothing was done because no tunnel to the specified
145 /// host was open.
146 NotOpen,
147}
148
149
150/// Information about the current status of the server.
151#[derive(Debug, Deserialize, PartialEq, Serialize)]
152pub struct StatusInformation {
153 /// A list of information about the tunnels that have been opened during
154 /// this server’s lifetime.
155 ///
156 /// This list includes tunnels that have been closed, but not any tunnels
157 /// opened from any previous invocations of the server.
158 pub tunnels: Vec<TunnelInformation>,
159}
160
161/// Information about a single tunnel opened by the server.
162#[derive(Debug, Deserialize, PartialEq, Serialize)]
163pub struct TunnelInformation {
164 /// The hostname associated with the connection.
165 pub host: String,
166
167 /// The current state of the SSH tunnel.
168 pub state: TunnelState,
169}
170
171/// The state of a single tunnel opened by the server.
172#[derive(Debug, Deserialize, PartialEq, Serialize)]
173pub enum TunnelState {
174 /// The tunnel is currently opene.
175 Open,
176
177 /// The tunnel was opened but then was manually closed.
178 Closed,
179
180 /// The tunnel was opened but died unexpectedly.
181 ///
182 /// This may be due to something like a connection drop or the user
183 /// killing the associated SSH process outside of the server’s knowledge.
184 Died,
185}