[mosh-devel] Pre-shared keys (patch)

johnny cache johnycsh at gmail.com
Tue Nov 12 15:03:28 EST 2013


Hi all,

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.

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.


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).

Cheers
-jc




-------SNIP----


diff --git a/src/crypto/crypto.cc b/src/crypto/crypto.cc
index 9458de9..f44b486 100644
--- a/src/crypto/crypto.cc
+++ b/src/crypto/crypto.cc
@@ -97,8 +97,25 @@ AlignedBuffer::AlignedBuffer( size_t len, const char
*data )
   }
 }

-Base64Key::Base64Key( string printable_key )
+Base64Key::Base64Key( const char *key)
+{
+
+  if (key == NULL) {
+    genrandom_key();
+    return;
+  }
+  string key_string = key;
+  init_key(key);
+}
+
+void Base64Key::init_key( string printable_key )
 {
+
+  if ( printable_key.length() == 0 ) { /* unused, but analagous to char *
NULL case. included for consistency */
+ genrandom_key();
+ return;
+  }
+
   if ( printable_key.length() != 22 ) {
     throw CryptoException( "Key must be 22 letters long." );
   }
@@ -120,7 +137,13 @@ Base64Key::Base64Key( string printable_key )
   }
 }

-Base64Key::Base64Key()
+Base64Key::Base64Key( string printable_key )
+{
+ init_key(printable_key);
+}
+
+
+void Base64Key::genrandom_key()
 {
   ifstream devrandom( rdev, ifstream::in | ifstream::binary );

@@ -130,6 +153,12 @@ Base64Key::Base64Key()
   }
 }

+
+Base64Key::Base64Key()
+{
+ genrandom_key();
+}
+
 string Base64Key::printable_key( void ) const
 {
   char base64[ 24 ];
diff --git a/src/crypto/crypto.h b/src/crypto/crypto.h
index c2eb996..1cb5ce8 100644
--- a/src/crypto/crypto.h
+++ b/src/crypto/crypto.h
@@ -78,9 +78,12 @@ namespace Crypto {
   class Base64Key {
   private:
     unsigned char key[ 16 ];
+    void genrandom_key();
+    void init_key(string printable_key);

   public:
     Base64Key(); /* random key */
+    Base64Key( const char *key); /* User specified, NULL=random */
     Base64Key( string printable_key );
     string printable_key( void ) const;
     unsigned char *data( void ) { return key; }
diff --git a/src/frontend/mosh-server.cc b/src/frontend/mosh-server.cc
index f686e60..a0d7cee 100644
--- a/src/frontend/mosh-server.cc
+++ b/src/frontend/mosh-server.cc
@@ -95,7 +95,7 @@ void serve( int host_fd,
     Terminal::Complete &terminal,
     ServerConnection &network );

-int run_server( const char *desired_ip, const char *desired_port,
+int run_server( const char *desired_ip, const char *desired_port, const
char *desired_key,
  const string &command_path, char *command_argv[],
  const int colors, bool verbose, bool with_motd );

@@ -163,6 +163,7 @@ int main( int argc, char *argv[] )
   const char *desired_ip = NULL;
   string desired_ip_str;
   const char *desired_port = NULL;
+  const char *desired_key = NULL;
   string command_path;
   char **command_argv = NULL;
   int colors = 0;
@@ -170,6 +171,23 @@ int main( int argc, char *argv[] )
   /* Will cause mosh-server not to correctly detach on old versions of
sshd. */
   list<string> locale_vars;

+ /*  Advanced users may specify a preshared key to the server in MOSH_KEY
*/
+ char *env_key = getenv( "MOSH_KEY" );
+ if ( env_key != NULL ) {
+   desired_key = strdup( env_key );
+
+   if ( desired_key == NULL ) {
+       perror( "strdup" );
+       exit( 1 );
+    }
+
+  if ( unsetenv( "MOSH_KEY" ) < 0 ) {
+    perror( "unsetenv" );
+    exit( 1 );
+    }
+ }
+
+
   /* strip off command */
   for ( int i = 0; i < argc; i++ ) {
     if ( 0 == strcmp( argv[ i ], "--" ) ) { /* -- is mandatory */
@@ -316,7 +334,7 @@ int main( int argc, char *argv[] )
   }

   try {
-    return run_server( desired_ip, desired_port, command_path,
command_argv, colors, verbose, with_motd );
+    return run_server( desired_ip, desired_port, desired_key,
command_path, command_argv, colors, verbose, with_motd );
   } catch ( const Network::NetworkException& e ) {
     fprintf( stderr, "Network exception: %s: %s\n",
      e.function.c_str(), strerror( e.the_errno ) );
@@ -328,7 +346,7 @@ int main( int argc, char *argv[] )
   }
 }

-int run_server( const char *desired_ip, const char *desired_port,
+int run_server( const char *desired_ip, const char *desired_port, const
char *desired_key,
  const string &command_path, char *command_argv[],
  const int colors, bool verbose, bool with_motd ) {
   /* get initial window size */
@@ -348,7 +366,7 @@ int run_server( const char *desired_ip, const char
*desired_port,

   /* open network */
   Network::UserStream blank;
-  ServerConnection *network = new ServerConnection( terminal, blank,
desired_ip, desired_port );
+  ServerConnection *network = new ServerConnection( terminal, blank,
desired_ip, desired_port, desired_key );

   if ( verbose ) {
     network->set_verbose();
diff --git a/src/network/network.cc b/src/network/network.cc
index 2f4e0bf..c3b0e8e 100644
--- a/src/network/network.cc
+++ b/src/network/network.cc
@@ -199,13 +199,13 @@ const std::vector< int > Connection::fds( void ) const
   return ret;
 }

-Connection::Connection( const char *desired_ip, const char *desired_port )
/* server */
+Connection::Connection( const char *desired_ip, const char *desired_port,
const char *desired_key ) /* server */
   : socks(),
     has_remote_addr( false ),
     remote_addr(),
     server( true ),
     MTU( DEFAULT_SEND_MTU ),
-    key(),
+    key(desired_key),
     session( key ),
     direction( TO_CLIENT ),
     next_seq( 0 ),
@@ -221,13 +221,19 @@ Connection::Connection( const char *desired_ip, const
char *desired_port ) /* se
     have_send_exception( false ),
     send_exception()
 {
-  setup();
+setup();
+
+   /* The mosh wrapper always gives an IP request, in order
+      to deal with multihomed servers. The port is optional.

-  /* The mosh wrapper always gives an IP request, in order
-     to deal with multihomed servers. The port is optional. */
+     If an IP request is given, we try to bind to that IP, but we also
+     try INADDR_ANY. If a port request is given, we bind only to that
port.

-  /* If an IP request is given, we try to bind to that IP, but we also
-     try INADDR_ANY. If a port request is given, we bind only to that
port. */
+     In some (rare) cases the user may want to start a server with a
pre-specified key.
+     in that case, desired_key will point to a base16 encoded string that
meets
+     the key requirements.  Otherwise it will be NULL.
+   */
+

-----------------------

   /* convert port numbers */
   int desired_port_low = 0;
diff --git a/src/network/network.h b/src/network/network.h
index 61efe50..00ae532 100644
--- a/src/network/network.h
+++ b/src/network/network.h
@@ -160,7 +160,7 @@ namespace Network {
     string recv_one( int sock_to_recv, bool nonblocking );

   public:
-    Connection( const char *desired_ip, const char *desired_port ); /*
server */
+    Connection( const char *desired_ip, const char *desired_port,  const
char *desired_key_str=NULL ); /* server */
     Connection( const char *key_str, const char *ip, int port ); /* client
*/

     void send( string s );
diff --git a/src/network/networktransport.cc
b/src/network/networktransport.cc
index 127e80c..ea239fd 100644
--- a/src/network/networktransport.cc
+++ b/src/network/networktransport.cc
@@ -41,8 +41,8 @@ using namespace std;

 template <class MyState, class RemoteState>
 Transport<MyState, RemoteState>::Transport( MyState &initial_state,
RemoteState &initial_remote,
-    const char *desired_ip, const char *desired_port )
-  : connection( desired_ip, desired_port ),
+    const char *desired_ip, const char *desired_port, const char
*desired_key )
+  : connection( desired_ip, desired_port, desired_key),
     sender( &connection, initial_state ),
     received_states( 1, TimestampedState<RemoteState>( timestamp(), 0,
initial_remote ) ),
     receiver_quench_timer( 0 ),
diff --git a/src/network/networktransport.h b/src/network/networktransport.h
index c23d0bd..3141ad8 100644
--- a/src/network/networktransport.h
+++ b/src/network/networktransport.h
@@ -67,9 +67,9 @@ namespace Network {

   public:
     Transport( MyState &initial_state, RemoteState &initial_remote,
-       const char *desired_ip, const char *desired_port );
+       const char *desired_ip, const char *desired_port, const char
*desired_key ); /* server */
     Transport( MyState &initial_state, RemoteState &initial_remote,
-       const char *key_str, const char *ip, int port );
+       const char *key_str, const char *ip, int port ); /* client */

     /* Send data or an ack if necessary. */
     void tick( void ) { sender.tick(); }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mailman.mit.edu/pipermail/mosh-devel/attachments/20131112/ac22348b/attachment.html


More information about the mosh-devel mailing list