summaryrefslogtreecommitdiff
path: root/src/cssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cssh.c')
-rw-r--r--src/cssh.c115
1 files changed, 68 insertions, 47 deletions
diff --git a/src/cssh.c b/src/cssh.c
index b5592a6..cc4ed9d 100644
--- a/src/cssh.c
+++ b/src/cssh.c
@@ -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 );