summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2021-11-19 21:23:28 +0100
committerAndreas Baumann <mail@andreasbaumann.cc>2021-11-19 21:23:28 +0100
commitc258810b81a9ef4d93530f5c26a5512954a86220 (patch)
treebac20b5c4d921a9dbbe7f65d72abff46c9cac17b
parenta1bd091b4f5ed19e11816bbd87ef4c96f3342ac3 (diff)
downloadcssh-c258810b81a9ef4d93530f5c26a5512954a86220.tar.gz
cssh-c258810b81a9ef4d93530f5c26a5512954a86220.tar.bz2
added option --ignore-authentication-errors to ignore authentication errors
added option --allow-password-authentication to explicitely allow authentication with password added some similar projects to README
-rw-r--r--README16
-rw-r--r--TODOS2
-rw-r--r--src/cssh.c85
-rw-r--r--src/options.ggo.in8
4 files changed, 77 insertions, 34 deletions
diff --git a/README b/README
index fe66791..7c28af9 100644
--- a/README
+++ b/README
@@ -33,6 +33,22 @@ GNU parallel
Way complex, good for batches. I think cssh should not try to compete
with it. GNU parallel is written in Perl.
+Dsh
+---
+
+http://www.netfort.gr.jp/~dancer/software/dsh.html
+
+Distributed or Dancer's shell, written in C. dssh with -M -c -r ssh is
+basically the same what we are doing. dssh has no interactive mode.
+
+Clusterit
+---------
+
+http://www.sourceforge.net/projects/clusterit
+
+Also written in C. Set of tools for simple cluster-excution, focus
+on compilation and shell.
+
Why libssh and not libssh2
--------------------------
diff --git a/TODOS b/TODOS
index 5bec231..05c40c7 100644
--- a/TODOS
+++ b/TODOS
@@ -12,6 +12,8 @@
- clusters: named set of hosts
- tags: for things line cssh -t centos -c yum update or so
- meta commands like enable/disable some hosts/tags
+- make password authentication optional
+- make ignore-errors and auth-methods enums in gengetopt
diff --git a/src/cssh.c b/src/cssh.c
index 6b68362..3fe7218 100644
--- a/src/cssh.c
+++ b/src/cssh.c
@@ -352,7 +352,7 @@ static int authenticate_pubkey( ssh_session session )
}
static int authenticate_password( ssh_session session, const char *host, const unsigned short port, const char *user )
-{
+{
char prompt[128];
char pass[128];
@@ -369,13 +369,16 @@ static int authenticate_password( ssh_session session, const char *host, const u
}
}
- snprintf( prompt, sizeof( prompt ), "%s@%s:%d's password:",
- prompt_user, host, port );
+ if( strchr( host, '@' ) == NULL ) {
+ snprintf( prompt, sizeof( prompt ), "%s@%s:%d's password:",
+ prompt_user, host, port );
+ } else {
+ snprintf( prompt, sizeof( prompt ), "%s:%d's password:",
+ host, port );
+ }
memset( pass, 0, sizeof( pass ) );
if( ssh_getpass( prompt, pass, sizeof( pass ), 0, 0 ) < 0 ) {
- fprintf( stderr, "ERROR: ssh_getpass failed\n" );
- ssh_disconnect( session );
- ssh_free( session );
+ fprintf( stderr, "\nERROR: ssh_getpass failed\n" );
return -1;
}
@@ -398,8 +401,6 @@ static int authenticate_password( ssh_session session, const char *host, const u
case SSH_AUTH_ERROR:
fprintf( stderr, "ERROR: Failed to authenticate with password: %s\n",
ssh_get_error( session ) );
- ssh_disconnect( session );
- ssh_free( session );
return SSH_AUTH_ERROR;
}
@@ -793,7 +794,7 @@ int main( int argc, char *argv[] )
}
for( unsigned int i = 0; i < nof_sessions; i++ ) {
session[i] = ssh_new( );
- if( session == NULL ) {
+ if( session[i] == NULL ) {
exit( EXIT_FAILURE );
}
}
@@ -821,13 +822,12 @@ int main( int argc, char *argv[] )
// asynchonous connection phase
- connection_state_e *connection_state = (connection_state_e *)malloc( nof_sessions * sizeof( connection_state_e ) );
+ connection_state_e *connection_state = (connection_state_e *)calloc( 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( 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;
@@ -867,13 +867,12 @@ int main( int argc, char *argv[] )
// authentication phase
- auth_state_e *auth_state = (auth_state_e *)malloc( ( nof_sessions + 1 ) * sizeof( auth_state_e ) );
+ auth_state_e *auth_state = (auth_state_e *)calloc( nof_sessions, sizeof( auth_state_e ) );
if( auth_state == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for 'auth_state'\n" );
cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
- memset( auth_state, CSSH_AUTH_INIT, ( nof_sessions + 1 ) * sizeof( auth_state_e ) );
unsigned int nof_authenticated = 0;
while( nof_authenticated < nof_connected ) {
for( unsigned int i = 0; i < nof_sessions; i++ ) {
@@ -941,18 +940,22 @@ int main( int argc, char *argv[] )
break;
case CSSH_AUTH_PUBKEY_DONE_FAILED:
- rc = authenticate_password( session[i], host[i], port[i], args_info.login_given ? args_info.login_arg : NULL );
-
- if( rc == SSH_AUTH_SUCCESS ) {
- auth_state[i] = CSSH_AUTH_PASSWORD_DONE_SUCCESS;
- } else if( rc == SSH_AUTH_AGAIN ) {
- // ok, wait next iteration
- } else if( rc == SSH_AUTH_DENIED ) {
- auth_state[i] = CSSH_AUTH_PASSWORD_DONE_FAILED;
+ if( args_info.allow_password_authentication_given ) {
+ rc = authenticate_password( session[i], host[i], port[i], args_info.login_given ? args_info.login_arg : NULL );
+ if( rc == SSH_AUTH_SUCCESS ) {
+ auth_state[i] = CSSH_AUTH_PASSWORD_DONE_SUCCESS;
+ } else if( rc == SSH_AUTH_AGAIN ) {
+ // ok, wait next iteration
+ } else if( rc == SSH_AUTH_DENIED ) {
+ auth_state[i] = CSSH_AUTH_PASSWORD_DONE_FAILED;
+ } else {
+ cleanup_sessions( &session, NULL, NULL, host, &port, nof_sessions, args_info.verbose_given > 0 );
+ ssh_finalize( );
+ exit( EXIT_FAILURE );
+ }
} else {
- cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
+ auth_state[i] = CSSH_AUTH_DONE_FAILED;
+ }
break;
case CSSH_AUTH_PASSWORD_DONE_SUCCESS:
@@ -971,8 +974,13 @@ int main( int argc, char *argv[] )
case CSSH_AUTH_DONE_FAILED:
// one authentication failed, bail out for now
fprintf( stderr, "ERROR: authentication failed for one host ('%s'), aborting now\n", host[i] );
- cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
+ if( args_info.ignore_authentication_errors_given ) {
+ connection_state[i] = CSSH_CONNECTION_STATE_ERROR;
+ } else {
+ cleanup_sessions( &session, NULL, NULL, host, &port, nof_sessions, args_info.verbose_given > 0 );
+ ssh_finalize( );
+ exit( EXIT_FAILURE );
+ }
}
}
@@ -986,12 +994,22 @@ int main( int argc, char *argv[] )
if( i != j ) {
connection_state[j] = connection_state[i];
auth_state[j] = auth_state[i];
+ session[j] = session[i];
+ host[j] = host[i];
+ port[j] = port[i];
}
j++;
+ } else {
+ fprintf( stderr, "ERROR: host '%s' has errors, ignoring it\n", host[i] );
}
}
- nof_sessions = j;
-
+ if( j != nof_sessions ) {
+ nof_sessions = j;
+ connection_state = (connection_state_e *)realloc( connection_state, nof_sessions * sizeof( connection_state_e ) );
+ auth_state = (auth_state_e *)realloc( auth_state, nof_sessions * sizeof( auth_state_e ) );
+ session = (ssh_session *)realloc( session, nof_sessions * sizeof( ssh_session ) );
+ }
+
// in CLI mode get next command from linenoise
CLI_NEXT_CMD:
@@ -1026,19 +1044,18 @@ CLI_NEXT_CMD:
// explicit low-level handling of channels in SSH mode
- ssh_data_t *ssh_data = (ssh_data_t *)malloc( ( nof_sessions + 1 ) * sizeof( ssh_data_t ) );
+ ssh_data_t *ssh_data = (ssh_data_t *)calloc( nof_sessions, sizeof( ssh_data_t ) );
if( ssh_data == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for ssh_data array\n" );
cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
- memset( ssh_data, 0, ( nof_sessions + 1 ) * sizeof( ssh_data_t ) );
for( unsigned int i = 0; i < nof_sessions; i++ ) {
ssh_data[i].channel = ssh_channel_new( session[i] );
if( ssh_data[i].channel == NULL ) {
- fprintf( stderr, "ERROR: Unable to open SSH channel: %s\n",
- ssh_get_error( session[i] ) );
+ fprintf( stderr, "ERROR: Unable to open SSH channel for host '%s': %s\n",
+ host[i], ssh_get_error( session[i] ) );
cleanup_sessions( &session, &ssh_data, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
@@ -1192,13 +1209,12 @@ SHELL_EOF:
case CSSH_EXECUTE_AS_SCP: {
- scp_data_t *scp_data = (scp_data_t *)malloc( ( nof_sessions + 1 ) * sizeof( scp_data_t ) );
+ scp_data_t *scp_data = (scp_data_t *)calloc( nof_sessions, sizeof( scp_data_t ) );
if( scp_data == NULL ) {
fprintf( stderr, "ERROR: Memory allocation failed for scp_data array\n" );
cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
- memset( scp_data, 0, ( nof_sessions + 1 ) * sizeof( scp_data_t ) );
for( unsigned int i = 0; i < nof_sessions; i++ ) {
scp_data[i].read_state = CSSH_SCP_READ_STATE_IDLE;
}
@@ -1533,6 +1549,7 @@ SHELL_EOF:
// the end
free( connection_state );
+ free( auth_state );
cmdline_parser_free( &args_info );
diff --git a/src/options.ggo.in b/src/options.ggo.in
index 46eb635..71e4364 100644
--- a/src/options.ggo.in
+++ b/src/options.ggo.in
@@ -52,3 +52,11 @@ section "Additional options"
"Ignore host if we cannot connect to it at startup"
optional
+ option "ignore-authentication-errors" -
+ "Ignore host if we cannot authenticate to it at startup"
+ optional
+
+ option "allow-password-authentication" -
+ "Allow password identification if identification with keys fails"
+ optional
+