<div dir="ltr">Hi all,<div><br></div><div style>So I've been running mosh in situations where some admins would be using telnet (inside a vpn tunnel, as an emergency remote admin, etc.). In order do this conveniently it requires me to start up a mosh-server instance with a pre-shared (instead of the dynamically generated) key. That way I can connect with mosh_client even if I don't have the two-way comms required to get the MOSH_KEY value that mosh_server generated back to the client.</div>
<div style><br></div><div style>Anyway - In order to do this I patched mosh_server to check for the existence of MOSH_KEY in the environment at startup; if its present (and valid) it will use that instead of generating one. </div>
<div style><br></div><div style><br></div><div style>Thought there might be other people out there who find this useful. The following patch applies cleanly to the latest git reversion. (Although it probably works against 1.2.4 as well).</div>
<div style><br></div><div style>Cheers</div><div style>-jc</div><div style><br></div><div style><br></div><div style><br></div><div style><br></div><div style>-------SNIP----</div><div style><br></div><div style><br></div>
<div style><div>diff --git a/src/crypto/crypto.cc b/src/crypto/crypto.cc</div><div>index 9458de9..f44b486 100644</div><div>--- a/src/crypto/crypto.cc</div><div>+++ b/src/crypto/crypto.cc</div><div>@@ -97,8 +97,25 @@ AlignedBuffer::AlignedBuffer( size_t len, const char *data )</div>
<div> }</div><div> }</div><div> </div><div>-Base64Key::Base64Key( string printable_key )</div><div>+Base64Key::Base64Key( const char *key) </div><div>+{</div><div>+</div><div>+ if (key == NULL) {</div><div>+ genrandom_key();</div>
<div>+ return;</div><div>+ }</div><div>+ string key_string = key; </div><div>+ init_key(key);</div><div>+}</div><div>+</div><div>+void Base64Key::init_key( string printable_key )</div><div> {</div><div>+</div><div>+ if ( printable_key.length() == 0 ) { /* unused, but analagous to char * NULL case. included for consistency */</div>
<div>+<span class="" style="white-space:pre">        </span>genrandom_key();</div><div>+<span class="" style="white-space:pre">        </span>return;<span class="" style="white-space:pre">        </span></div><div>+ }</div><div>+</div><div> if ( printable_key.length() != 22 ) {</div>
<div> throw CryptoException( "Key must be 22 letters long." );</div><div> }</div><div>@@ -120,7 +137,13 @@ Base64Key::Base64Key( string printable_key )</div><div> }</div><div> }</div><div> </div><div>-Base64Key::Base64Key()</div>
<div>+Base64Key::Base64Key( string printable_key )</div><div>+{</div><div>+<span class="" style="white-space:pre">        </span>init_key(printable_key);</div><div>+}</div><div>+</div><div>+</div><div>+void Base64Key::genrandom_key()</div>
<div> {</div><div> ifstream devrandom( rdev, ifstream::in | ifstream::binary );</div><div> </div><div>@@ -130,6 +153,12 @@ Base64Key::Base64Key()</div><div> }</div><div> }</div><div> </div><div>+</div><div>+Base64Key::Base64Key()</div>
<div>+{</div><div>+<span class="" style="white-space:pre">        </span>genrandom_key();</div><div>+}</div><div>+</div><div> string Base64Key::printable_key( void ) const</div><div> {</div><div> char base64[ 24 ];</div><div>diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h</div>
<div>index c2eb996..1cb5ce8 100644</div><div>--- a/src/crypto/crypto.h</div><div>+++ b/src/crypto/crypto.h</div><div>@@ -78,9 +78,12 @@ namespace Crypto {</div><div> class Base64Key {</div><div> private:</div><div> unsigned char key[ 16 ];</div>
<div>+ void genrandom_key();</div><div>+ void init_key(string printable_key);</div><div> </div><div> public:</div><div> Base64Key(); /* random key */</div><div>+ Base64Key( const char *key); /* User specified, NULL=random */</div>
<div> Base64Key( string printable_key );</div><div> string printable_key( void ) const;</div><div> unsigned char *data( void ) { return key; }</div><div>diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc</div>
<div>index f686e60..a0d7cee 100644</div><div>--- a/src/frontend/mosh-server.cc</div><div>+++ b/src/frontend/mosh-server.cc</div><div>@@ -95,7 +95,7 @@ void serve( int host_fd,</div><div> <span class="" style="white-space:pre">        </span> Terminal::Complete &terminal,</div>
<div> <span class="" style="white-space:pre">        </span> ServerConnection &network );</div><div> </div><div>-int run_server( const char *desired_ip, const char *desired_port,</div><div>+int run_server( const char *desired_ip, const char *desired_port, const char *desired_key,</div>
<div> <span class="" style="white-space:pre">                </span>const string &command_path, char *command_argv[],</div><div> <span class="" style="white-space:pre">                </span>const int colors, bool verbose, bool with_motd );</div>
<div> </div><div>@@ -163,6 +163,7 @@ int main( int argc, char *argv[] )</div><div> const char *desired_ip = NULL;</div><div> string desired_ip_str;</div><div> const char *desired_port = NULL;</div><div>+ const char *desired_key = NULL;</div>
<div> string command_path;</div><div> char **command_argv = NULL;</div><div> int colors = 0;</div><div>@@ -170,6 +171,23 @@ int main( int argc, char *argv[] )</div><div> /* Will cause mosh-server not to correctly detach on old versions of sshd. */</div>
<div> list<string> locale_vars;</div><div> </div><div>+ /* Advanced users may specify a preshared key to the server in MOSH_KEY */</div><div>+ char *env_key = getenv( "MOSH_KEY" );</div><div>+ if ( env_key != NULL ) {</div>
<div>+ desired_key = strdup( env_key );</div><div>+</div><div>+ if ( desired_key == NULL ) {</div><div>+ perror( "strdup" );</div><div>+ exit( 1 );</div><div>+ }</div><div>+</div><div>+ if ( unsetenv( "MOSH_KEY" ) < 0 ) {</div>
<div>+ perror( "unsetenv" );</div><div>+ exit( 1 );</div><div>+ }</div><div>+ }</div><div>+</div><div>+</div><div> /* strip off command */</div><div> for ( int i = 0; i < argc; i++ ) {</div><div>
if ( 0 == strcmp( argv[ i ], "--" ) ) { /* -- is mandatory */</div><div>@@ -316,7 +334,7 @@ int main( int argc, char *argv[] )</div><div> }</div><div> </div><div> try {</div><div>- return run_server( desired_ip, desired_port, command_path, command_argv, colors, verbose, with_motd );</div>
<div>+ return run_server( desired_ip, desired_port, desired_key, command_path, command_argv, colors, verbose, with_motd );</div><div> } catch ( const Network::NetworkException& e ) {</div><div> fprintf( stderr, "Network exception: %s: %s\n",</div>
<div> <span class="" style="white-space:pre">        </span> e.function.c_str(), strerror( e.the_errno ) );</div><div>@@ -328,7 +346,7 @@ int main( int argc, char *argv[] )</div><div> }</div><div> }</div><div> </div><div>-int run_server( const char *desired_ip, const char *desired_port,</div>
<div>+int run_server( const char *desired_ip, const char *desired_port, const char *desired_key,</div><div> <span class="" style="white-space:pre">                </span>const string &command_path, char *command_argv[],</div><div> <span class="" style="white-space:pre">                </span>const int colors, bool verbose, bool with_motd ) {</div>
<div> /* get initial window size */</div><div>@@ -348,7 +366,7 @@ int run_server( const char *desired_ip, const char *desired_port,</div><div> </div><div> /* open network */</div><div> Network::UserStream blank;</div>
<div>- ServerConnection *network = new ServerConnection( terminal, blank, desired_ip, desired_port );</div><div>+ ServerConnection *network = new ServerConnection( terminal, blank, desired_ip, desired_port, desired_key );</div>
<div> </div><div> if ( verbose ) {</div><div> network->set_verbose();</div><div>diff --git a/src/network/network.cc b/src/network/network.cc</div><div>index 2f4e0bf..c3b0e8e 100644</div><div>--- a/src/network/network.cc</div>
<div>+++ b/src/network/network.cc</div><div>@@ -199,13 +199,13 @@ const std::vector< int > Connection::fds( void ) const</div><div> return ret;</div><div> }</div><div> </div><div>-Connection::Connection( const char *desired_ip, const char *desired_port ) /* server */</div>
<div>+Connection::Connection( const char *desired_ip, const char *desired_port, const char *desired_key ) /* server */</div><div> : socks(),</div><div> has_remote_addr( false ),</div><div> remote_addr(),</div><div>
server( true ),</div><div> MTU( DEFAULT_SEND_MTU ),</div><div>- key(),</div><div>+ key(desired_key),</div><div> session( key ),</div><div> direction( TO_CLIENT ),</div><div> next_seq( 0 ),</div>
<div>@@ -221,13 +221,19 @@ Connection::Connection( const char *desired_ip, const char *desired_port ) /* se</div><div> have_send_exception( false ),</div><div> send_exception()</div><div> {</div><div>- setup();</div>
<div>+setup();</div><div>+</div><div>+ /* The mosh wrapper always gives an IP request, in order</div><div>+ to deal with multihomed servers. The port is optional. </div><div> </div><div>- /* The mosh wrapper always gives an IP request, in order</div>
<div>- to deal with multihomed servers. The port is optional. */</div><div>+ If an IP request is given, we try to bind to that IP, but we also</div><div>+ try INADDR_ANY. If a port request is given, we bind only to that port. </div>
<div> </div><div>- /* If an IP request is given, we try to bind to that IP, but we also</div><div>- try INADDR_ANY. If a port request is given, we bind only to that port. */</div><div>+ In some (rare) cases the user may want to start a server with a pre-specified key.</div>
<div>+ in that case, desired_key will point to a base16 encoded string that meets</div><div>+ the key requirements. Otherwise it will be NULL.</div><div>+ */</div><div>+ </div><div> </div><div>-----------------------</div>
<div><br></div><div> /* convert port numbers */</div><div> int desired_port_low = 0;</div><div>diff --git a/src/network/network.h b/src/network/network.h</div><div>index 61efe50..00ae532 100644</div><div>--- a/src/network/network.h</div>
<div>+++ b/src/network/network.h</div><div>@@ -160,7 +160,7 @@ namespace Network {</div><div> string recv_one( int sock_to_recv, bool nonblocking );</div><div> </div><div> public:</div><div>- Connection( const char *desired_ip, const char *desired_port ); /* server */</div>
<div>+ Connection( const char *desired_ip, const char *desired_port, const char *desired_key_str=NULL ); /* server */</div><div> Connection( const char *key_str, const char *ip, int port ); /* client */</div><div>
</div><div> void send( string s );</div><div>diff --git a/src/network/networktransport.cc b/src/network/networktransport.cc</div><div>index 127e80c..ea239fd 100644</div><div>--- a/src/network/networktransport.cc</div>
<div>+++ b/src/network/networktransport.cc</div><div>@@ -41,8 +41,8 @@ using namespace std;</div><div> </div><div> template <class MyState, class RemoteState></div><div> Transport<MyState, RemoteState>::Transport( MyState &initial_state, RemoteState &initial_remote,</div>
<div>-<span class="" style="white-space:pre">                                        </span> const char *desired_ip, const char *desired_port )</div><div>- : connection( desired_ip, desired_port ),</div><div>+<span class="" style="white-space:pre">                                        </span> const char *desired_ip, const char *desired_port, const char *desired_key )</div>
<div>+ : connection( desired_ip, desired_port, desired_key),</div><div> sender( &connection, initial_state ),</div><div> received_states( 1, TimestampedState<RemoteState>( timestamp(), 0, initial_remote ) ),</div>
<div> receiver_quench_timer( 0 ),</div><div>diff --git a/src/network/networktransport.h b/src/network/networktransport.h</div><div>index c23d0bd..3141ad8 100644</div><div>--- a/src/network/networktransport.h</div><div>
+++ b/src/network/networktransport.h</div><div>@@ -67,9 +67,9 @@ namespace Network {</div><div> </div><div> public:</div><div> Transport( MyState &initial_state, RemoteState &initial_remote,</div><div>-<span class="" style="white-space:pre">        </span> const char *desired_ip, const char *desired_port );</div>
<div>+<span class="" style="white-space:pre">        </span> const char *desired_ip, const char *desired_port, const char *desired_key ); /* server */</div><div> Transport( MyState &initial_state, RemoteState &initial_remote,</div>
<div>-<span class="" style="white-space:pre">        </span> const char *key_str, const char *ip, int port );</div><div>+<span class="" style="white-space:pre">        </span> const char *key_str, const char *ip, int port ); /* client */</div>
<div> </div><div> /* Send data or an ack if necessary. */</div><div> void tick( void ) { sender.tick(); }</div><div><br></div><div><br></div><div><br></div></div></div>