<div dir="ltr">Hi all,<div><br></div><div style>So I&#39;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&#39;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( &quot;Key must be 22 letters long.&quot; );</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 &amp;terminal,</div>
<div> <span class="" style="white-space:pre">        </span>    ServerConnection &amp;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 &amp;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&lt;string&gt; 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( &quot;MOSH_KEY&quot; );</div><div>+ if ( env_key != NULL ) {</div>
<div>+   desired_key = strdup( env_key );</div><div>+</div><div>+   if ( desired_key == NULL ) {</div><div>+       perror( &quot;strdup&quot; );</div><div>+       exit( 1 );</div><div>+    }</div><div>+</div><div>+  if ( unsetenv( &quot;MOSH_KEY&quot; ) &lt; 0 ) {</div>
<div>+    perror( &quot;unsetenv&quot; );</div><div>+    exit( 1 );</div><div>+    }</div><div>+ }</div><div>+</div><div>+</div><div>   /* strip off command */</div><div>   for ( int i = 0; i &lt; argc; i++ ) {</div><div>
     if ( 0 == strcmp( argv[ i ], &quot;--&quot; ) ) { /* -- 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&amp; e ) {</div><div>     fprintf( stderr, &quot;Network exception: %s: %s\n&quot;,</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 &amp;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-&gt;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&lt; int &gt; 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 &lt;class MyState, class RemoteState&gt;</div><div> Transport&lt;MyState, RemoteState&gt;::Transport( MyState &amp;initial_state, RemoteState &amp;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( &amp;connection, initial_state ),</div><div>     received_states( 1, TimestampedState&lt;RemoteState&gt;( 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 &amp;initial_state, RemoteState &amp;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 &amp;initial_state, RemoteState &amp;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>