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}