diff options
Diffstat (limited to 'src/cssh.c')
-rw-r--r-- | src/cssh.c | 115 |
1 files changed, 68 insertions, 47 deletions
@@ -1,6 +1,6 @@ /* - cssh - parallel secure shell - Copyright (C) 2015 Andreas Baumann + cssh - cluster secure shell + Copyright (C) 2015-2021 Andreas Baumann This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -51,6 +51,12 @@ #define DEFAULT_PROMPT "cssh> " #define HISTORY_FILE ".cssh_history" +typedef enum connection_state_e { + CSSH_CONNECTION_STATE_UNCONNECTED, + CSSH_CONNECTION_STATE_CONNECTED, + CSSH_CONNECTION_STATE_ERROR +} connection_state_e; + typedef enum auth_state_e { CSSH_AUTH_INIT, CSSH_AUTH_VERIFY_HOST_DONE, @@ -252,8 +258,8 @@ static int accept_server( ssh_session session, unsigned char *hash, size_t hlen static int verify_knownhost( ssh_session session ) { - enum ssh_known_hosts_e state; - + int state; + state = ssh_session_is_known_server( session ); ssh_key srv_pubkey; @@ -295,18 +301,18 @@ static int verify_knownhost( ssh_session session ) fprintf( stderr, "ERROR: Could not find a known host file.\n" ); rc = accept_server( session, hash, hlen ); ssh_clean_pubkey_hash( &hash ); - return rc; + return -1; case SSH_SERVER_NOT_KNOWN: fprintf( stderr, "ERROR: The server is unknown.\n" ); rc = accept_server( session, hash, hlen ); ssh_clean_pubkey_hash( &hash ); - return rc; + return -1; case SSH_SERVER_ERROR: - ssh_clean_pubkey_hash( &hash ); fprintf( stderr, "ERROR: 'ssh_is_server_known' failed with: %s\n", ssh_get_error( session ) ); + ssh_clean_pubkey_hash( &hash ); return -1; default: @@ -606,7 +612,7 @@ int main( int argc, char *argv[] ) ssh_init( ); if( args_info.long_version_given ) { - printf( "cssh version: %s, Copyright (c) 2015-2017, LGPLv2, Andreas Baumann <mail at andreasbaumann dot cc>\n", CSSH_VERSION ); + printf( "cssh version: %s, Copyright (c) 2015-2021, GPLv3, Andreas Baumann <mail at andreasbaumann dot cc>\n", CSSH_VERSION ); printf( "libssh version: %s\n", ssh_copyright( ) ); printf( "linenoise: BSD license, Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com> and " "Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>\n" ); @@ -815,50 +821,52 @@ int main( int argc, char *argv[] ) // asynchonous connection phase - bool all_connected = false; - bool *is_connected = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) ); - if( is_connected == NULL ) { - fprintf( stderr, "ERROR: Memory allocation failed for 'is_connected'\n" ); + connection_state_e *connection_state = (connection_state_e *)malloc( nof_sessions * sizeof( connection_state_e ) ); + if( connection_state == NULL ) { + fprintf( stderr, "ERROR: Memory allocation failed for 'connection_state'\n" ); cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 ); exit( EXIT_SUCCESS ); } - memset( is_connected, false, ( nof_sessions + 1 ) * sizeof( bool ) ); - while( !all_connected ) { + memset( connection_state, CSSH_CONNECTION_STATE_UNCONNECTED, nof_sessions * sizeof( connection_state_e ) ); + unsigned int nof_connected = 0; + while( nof_connected < nof_sessions ) { + nof_connected = 0; for( unsigned int i = 0; i < nof_sessions; i++ ) { - if( !is_connected[i] ) { - rc = ssh_connect( session[i] ); - if( rc == SSH_OK ) { - is_connected[i] = true; - //~ ssh_set_blocking( session[i], 1 ); - if( args_info.verbose_given ) { - fprintf( stderr, "Connected to '%s', port %d..\n", host[i], port[i] ); + switch( connection_state[i] ) { + case CSSH_CONNECTION_STATE_UNCONNECTED: + rc = ssh_connect( session[i] ); + if( rc == SSH_OK ) { + connection_state[i] = CSSH_CONNECTION_STATE_CONNECTED; + //~ ssh_set_blocking( session[i], 1 ); + if( args_info.verbose_given ) { + fprintf( stderr, "Connected to '%s', port %d..\n", host[i], port[i] ); + } + } else if( rc == SSH_AGAIN ) { + // not connected yet + } else { + fprintf( stderr, "ERROR: error connecting to '%s', port '%d': %s\n", + host[i], port[i], ssh_get_error( session[i] ) ); + if( args_info.ignore_connect_errors_given ) { + connection_state[i] = CSSH_CONNECTION_STATE_ERROR; + } else { + cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 ); + exit( EXIT_FAILURE ); + } } - } else if( rc == SSH_AGAIN ) { - // not connected yet - } else { - fprintf( stderr, "ERROR: error connecting to '%s', port '%d': %s\n", - host[i], port[i], ssh_get_error( session[i] ) ); - cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 ); - exit( EXIT_FAILURE ); - } - } - } - - all_connected = true; - for( unsigned int i = 0; i < nof_sessions; i++ ) { - if( !is_connected[i] ) { - all_connected = false; + break; + case CSSH_CONNECTION_STATE_CONNECTED: + case CSSH_CONNECTION_STATE_ERROR: + // good, already connected or we ignore errors + nof_connected++; + break; } } cssh_msleep( 10 ); } - free( is_connected ); - // authentication phase - bool all_authenticated = false; auth_state_e *auth_state = (auth_state_e *)malloc( ( nof_sessions + 1 ) * sizeof( auth_state_e ) ); if( auth_state == NULL ) { fprintf( stderr, "ERROR: Memory allocation failed for 'auth_state'\n" ); @@ -866,8 +874,12 @@ int main( int argc, char *argv[] ) exit( EXIT_FAILURE ); } memset( auth_state, CSSH_AUTH_INIT, ( nof_sessions + 1 ) * sizeof( auth_state_e ) ); - while( !all_authenticated ) { + unsigned int nof_authenticated = 0; + while( nof_authenticated < nof_connected ) { for( unsigned int i = 0; i < nof_sessions; i++ ) { + if( connection_state[i] != CSSH_CONNECTION_STATE_CONNECTED ) { + continue; + } switch( auth_state[i] ) { case CSSH_AUTH_INIT: if( verify_knownhost( session[i] ) < 0 ) { @@ -953,6 +965,7 @@ int main( int argc, char *argv[] ) case CSSH_AUTH_DONE_SUCCESS: // ok + nof_authenticated++; break; case CSSH_AUTH_DONE_FAILED: @@ -962,17 +975,23 @@ int main( int argc, char *argv[] ) exit( EXIT_FAILURE ); } } - - all_authenticated = true; - for( unsigned int i = 0; i < nof_sessions; i++ ) { - if( auth_state[i] != CSSH_AUTH_DONE_SUCCESS ) { - all_authenticated = false; - } - } cssh_msleep( 10 ); } + // rearange session data in case we ignore errornous hosts + unsigned int j = 0; + for( unsigned int i = 0; i < nof_sessions; i++ ) { + if( connection_state[i] != CSSH_CONNECTION_STATE_CONNECTED ) { + if( i != j ) { + connection_state[j] = connection_state[i]; + auth_state[j] = auth_state[i]; + } + j++; + } + } + nof_sessions = j; + // in CLI mode get next command from linenoise CLI_NEXT_CMD: @@ -1513,6 +1532,8 @@ SHELL_EOF: // the end + free( connection_state ); + cmdline_parser_free( &args_info ); exit( EXIT_SUCCESS ); |