summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Baumann <mail@andreasbaumann.cc>2015-08-27 16:15:54 +0200
committerAndreas Baumann <mail@andreasbaumann.cc>2015-08-27 16:15:54 +0200
commit648886a5914fab9444ec4ce02abde8eb1a3bb4f8 (patch)
tree07d714e5e0f94a6ee87ef68db0958b5161b98ce4
parentb7e207c9186fa4d4c44bdfa6f0b08012947a31b5 (diff)
downloadcssh-648886a5914fab9444ec4ce02abde8eb1a3bb4f8.tar.gz
cssh-648886a5914fab9444ec4ce02abde8eb1a3bb4f8.tar.bz2
preparations for scp mode
l---------src/cscp1
-rw-r--r--src/cssh.c356
2 files changed, 209 insertions, 148 deletions
diff --git a/src/cscp b/src/cscp
new file mode 120000
index 0000000..e58b80a
--- /dev/null
+++ b/src/cscp
@@ -0,0 +1 @@
+cssh \ No newline at end of file
diff --git a/src/cssh.c b/src/cssh.c
index c493105..236e832 100644
--- a/src/cssh.c
+++ b/src/cssh.c
@@ -275,7 +275,7 @@ static int read_hosts_file( const char *hosts_file, unsigned short default_port,
return 0;
}
-static void cleanup_sessions( ssh_session **session, ssh_channel **channel, char **host, unsigned short *port, const int nof_sessions, bool verbose )
+static void cleanup_sessions( ssh_session **session, ssh_channel **channel, ssh_scp **scp, char **host, unsigned short *port, const int nof_sessions, bool verbose )
{
for( unsigned int i = 0; i < nof_sessions; i++ ) {
if( ssh_is_connected( (*session)[i] ) ) {
@@ -289,6 +289,10 @@ static void cleanup_sessions( ssh_session **session, ssh_channel **channel, char
ssh_channel_free( (*channel)[i] );
}
}
+ if( scp != NULL ) {
+ ssh_scp_close( (*scp)[i] );
+ ssh_scp_free( (*scp)[i] );
+ }
ssh_disconnect( (*session)[i] );
if( verbose ) {
fprintf( stderr, "Disconnected from '%s', port %d..\n", host[i], port[i] );
@@ -299,6 +303,9 @@ static void cleanup_sessions( ssh_session **session, ssh_channel **channel, char
if( channel != NULL ) {
free( *channel );
}
+ if( scp != NULL ) {
+ free( *scp );
+ }
free( *session );
free( *host );
free( port );
@@ -310,6 +317,11 @@ typedef enum execution_mode_e {
CSSH_EXECUTE_AS_SCP
} execution_mode_e;
+typedef enum copy_direction_e {
+ CSSH_COPY_DIRECTION_UPLOAD,
+ CSSH_COPY_DIRECTION_DOWNLOAD
+} copy_direction_e;
+
static execution_mode_e determine_execution_mode( const char *argv0 )
{
char *b = ssh_basename( argv0 );
@@ -445,7 +457,7 @@ int main( int argc, char *argv[] )
} 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, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -487,7 +499,7 @@ int main( int argc, char *argv[] )
if( verify_knownhost( session[i] ) < 0 ) {
fprintf( stderr, "ERROR: closing connection to '%s', port '%d' due to security reasons\n",
host[i], port[i] );
- cleanup_sessions( &session, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
auth_state[i] = CSSH_AUTH_VERIFY_HOST_DONE;
@@ -508,7 +520,7 @@ int main( int argc, char *argv[] )
} else {
fprintf( stderr, "ERROR: ssh_userauth_none to '%s', port '%d' failed: %s\n",
host[i], port[i], ssh_get_error( session[i] ) );
- cleanup_sessions( &session, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
break;
@@ -533,7 +545,7 @@ int main( int argc, char *argv[] )
} else if( rc == SSH_AUTH_DENIED ) {
auth_state[i] = CSSH_AUTH_PUBKEY_DONE_FAILED;
} else {
- cleanup_sessions( &session, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
break;
@@ -552,7 +564,7 @@ int main( int argc, char *argv[] )
} else if( rc == SSH_AUTH_DENIED ) {
auth_state[i] = CSSH_AUTH_PASSWORD_DONE_FAILED;
} else {
- cleanup_sessions( &session, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
break;
@@ -572,7 +584,7 @@ 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", host[i] );
- cleanup_sessions( &session, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
}
@@ -587,174 +599,222 @@ int main( int argc, char *argv[] )
cssh_msleep( 10 );
}
- ssh_channel *channel = (ssh_channel *)malloc( ( nof_sessions + 1 ) * sizeof( ssh_channel ) );
- memset( channel, 0, nof_sessions + 1 );
- if( channel == NULL ) {
- fprintf( stderr, "ERROR: Memory allocation failed for ssh_channels" );
- cleanup_sessions( &session, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
- for( unsigned int i = 0; i < nof_sessions; i++ ) {
- channel[i] = ssh_channel_new( session[i] );
- if( channel[i] == NULL ) {
- fprintf( stderr, "ERROR: Unable to open SSH channel: %s\n",
- ssh_get_error( session[i] ) );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
- }
-
- for( unsigned int i = 0; i < nof_sessions; i++ ) {
- rc = ssh_channel_open_session( channel[i] );
- if( rc != SSH_OK ) {
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
- }
-
- char cmd[1024];
- cmd[0] = '\0';
- if( args_info.inputs_num > 0 ) {
- for( int i = command_pos; i < args_info.inputs_num; i++ ) {
- if( i != command_pos ) {
- strncat( cmd, " ", sizeof( cmd ) - strlen( cmd ) - 1 );
+ switch( execution_mode ) {
+ case CSSH_EXECUTE_AS_SSH: {
+
+ // explicit low-level handling of channels in SSH mode
+ ssh_channel *channel = (ssh_channel *)malloc( ( nof_sessions + 1 ) * sizeof( ssh_channel ) );
+ memset( channel, 0, nof_sessions + 1 );
+ if( channel == NULL ) {
+ fprintf( stderr, "ERROR: Memory allocation failed for ssh_channels" );
+ cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ channel[i] = ssh_channel_new( session[i] );
+ if( channel[i] == NULL ) {
+ fprintf( stderr, "ERROR: Unable to open SSH channel: %s\n",
+ ssh_get_error( session[i] ) );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
}
- strncat( cmd, args_info.inputs[i], sizeof( cmd ) - strlen( cmd ) - 1 );
- }
- }
- if( cmd[0] == '\0' ) {
- fprintf( stderr, "ERROR: Empty command, no interactive CLI supported currently\n" );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
-
- for( unsigned int i = 0; i < nof_sessions; i++ ) {
- rc = ssh_channel_request_exec( channel[i], cmd );
- if( rc != SSH_OK ) {
- fprintf( stderr, "ERROR: Executing SSH command '%s' failed: %s\n",
- cmd, ssh_get_error( session[i] ) );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
- }
-
- bool all_eof = false;
- bool *eof_sent = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) );
- if( eof_sent == NULL ) {
- fprintf( stderr, "ERROR: Memory allocation failed for 'eof_sent'" );
- return -1;
- }
- memset( eof_sent, false, ( nof_sessions + 1 ) * sizeof( bool ) );
- bool *is_eof = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) );
- if( is_eof == NULL ) {
- fprintf( stderr, "ERROR: Memory allocation failed for 'is_eof'" );
- return -1;
- }
- memset( is_eof, false, ( nof_sessions + 1 ) * sizeof( bool ) );
-
- while( !all_eof ) {
- all_eof = true;
- for( unsigned int i = 0; i < nof_sessions; i++ ) {
- if( !ssh_channel_is_closed( channel[i] ) && !ssh_channel_is_eof( channel[i] ) ) {
- all_eof = false;
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ rc = ssh_channel_open_session( channel[i] );
+ if( rc != SSH_OK ) {
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
}
- }
-
- // no stdin sent to commands on remote machines for now
- for( unsigned int i = 0; i < nof_sessions; i++ ) {
- if( is_eof[i] && !eof_sent[i] ) {
- ssh_channel_send_eof( channel[i] );
- eof_sent[i] = true;
- continue;
+
+ // compose command to be executed in SSH mode
+ char cmd[1024];
+ cmd[0] = '\0';
+ if( args_info.inputs_num > 0 ) {
+ for( int i = command_pos; i < args_info.inputs_num; i++ ) {
+ if( i != command_pos ) {
+ strncat( cmd, " ", sizeof( cmd ) - strlen( cmd ) - 1 );
+ }
+ strncat( cmd, args_info.inputs[i], sizeof( cmd ) - strlen( cmd ) - 1 );
+ }
}
- }
-
- for( unsigned int i = 0; i < nof_sessions; i++ ) {
- char buffer[4096];
- rc = ssh_channel_poll( channel[i], 0 );
- if( rc == SSH_ERROR ) {
- fprintf( stderr, "ERROR: ssh_channel_poll on stdout failed: %s\n",
- ssh_get_error( session[i] ) );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
+ if( cmd[0] == '\0' ) {
+ fprintf( stderr, "ERROR: Empty command, no interactive CLI supported currently\n" );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
-
- if( rc > 0 ) {
- unsigned int nread = ssh_channel_read_nonblocking( channel[i], buffer, sizeof( buffer ), 0 );
- if( nread == SSH_ERROR ) {
- fprintf( stderr, "ERROR: ssh_channel_read_nonblocking on stdout failed: %s\n",
- ssh_get_error( session[i] ) );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
+
+ // execute command on all channels
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ rc = ssh_channel_request_exec( channel[i], cmd );
+ if( rc != SSH_OK ) {
+ fprintf( stderr, "ERROR: Executing SSH command '%s' failed: %s\n",
+ cmd, ssh_get_error( session[i] ) );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
+ }
+
+ bool all_eof = false;
+ bool *eof_sent = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) );
+ if( eof_sent == NULL ) {
+ fprintf( stderr, "ERROR: Memory allocation failed for 'eof_sent'" );
+ return -1;
+ }
+ memset( eof_sent, false, ( nof_sessions + 1 ) * sizeof( bool ) );
+ bool *is_eof = (bool *)malloc( ( nof_sessions + 1 ) * sizeof( bool ) );
+ if( is_eof == NULL ) {
+ fprintf( stderr, "ERROR: Memory allocation failed for 'is_eof'" );
+ return -1;
+ }
+ memset( is_eof, false, ( nof_sessions + 1 ) * sizeof( bool ) );
+
+ while( !all_eof ) {
+
+ all_eof = true;
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ if( !ssh_channel_is_closed( channel[i] ) && !ssh_channel_is_eof( channel[i] ) ) {
+ all_eof = false;
+ }
+ }
- if( nread == 0 ) {
- is_eof[i] = true;
+ // no stdin sent to commands on remote machines for now
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ if( is_eof[i] && !eof_sent[i] ) {
+ ssh_channel_send_eof( channel[i] );
+ eof_sent[i] = true;
+ continue;
+ }
}
-
- if( nread > 0 ) {
- size_t wrc = fwrite( buffer, 1, nread, stdout );
- if( wrc < 0 ) {
- fprintf( stderr, "ERROR: while writing to stdout: %s\n",
- strerror( errno ) );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
+
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ char buffer[4096];
+ rc = ssh_channel_poll( channel[i], 0 );
+ if( rc == SSH_ERROR ) {
+ fprintf( stderr, "ERROR: ssh_channel_poll on stdout failed: %s\n",
+ ssh_get_error( session[i] ) );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
+
+ if( rc > 0 ) {
+ unsigned int nread = ssh_channel_read_nonblocking( channel[i], buffer, sizeof( buffer ), 0 );
+ if( nread == SSH_ERROR ) {
+ fprintf( stderr, "ERROR: ssh_channel_read_nonblocking on stdout failed: %s\n",
+ ssh_get_error( session[i] ) );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+
+ if( nread == 0 ) {
+ is_eof[i] = true;
+ }
+
+ if( nread > 0 ) {
+ size_t wrc = fwrite( buffer, 1, nread, stdout );
+ if( wrc < 0 ) {
+ fprintf( stderr, "ERROR: while writing to stdout: %s\n",
+ strerror( errno ) );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+
+ if( wrc != nread ) {
+ fprintf( stderr, "ERROR: Write mismatch on stdout (%zu != %d)\n",
+ wrc, nread );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ }
+ }
- if( wrc != nread ) {
- fprintf( stderr, "ERROR: Write mismatch on stdout (%zu != %d)\n",
- wrc, nread );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
+ rc = ssh_channel_poll( channel[i], 1 );
+ if( rc == SSH_ERROR ) {
+ fprintf( stderr, "ERROR: ssh_channel_poll on stderr failed: %s\n",
+ ssh_get_error( session[i] ) );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
+
+ if( rc > 0 ) {
+ unsigned int nread = ssh_channel_read_nonblocking( channel[i], buffer, sizeof( buffer ), 1 );
+ if( nread == SSH_ERROR ) {
+ fprintf( stderr, "ERROR: ssh_channel_read_nonblocking on stderr failed: %s\n",
+ ssh_get_error( session[i] ) );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+
+ if( nread > 0 ) {
+ size_t wrc = fwrite( buffer, 1, nread, stderr );
+ if( wrc < 0 ) {
+ fprintf( stderr, "ERROR: while writting to stderr: %s\n",
+ strerror( errno ) );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+
+ if( wrc != nread ) {
+ fprintf( stderr, "ERROR: Write mismatch on stderr (%zu != %d)\n",
+ wrc, nread );
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+ exit( EXIT_FAILURE );
+ }
+ }
+
+ if( nread == 0 ) {
+ is_eof[i] = true;
+ }
+ }
}
+
+ cssh_msleep( 1 );
}
+
+ cleanup_sessions( &session, &channel, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
+
+ } break;
+
+ case CSSH_EXECUTE_AS_SCP: {
+
+ // TODO: parse 2 arguments and see where we have a local
+ // path and where a host destination with path
+ // TODO: host destination can be explicit (one without -H hosts
+ // parameter) or it is a placeholder host @HOST@:/dira/dirb
+ copy_direction_e copy_direction = CSSH_COPY_DIRECTION_DOWNLOAD;
+ const char *local_directory = ".";
+
+ fprintf( stderr, "Copy mode\n" );
- rc = ssh_channel_poll( channel[i], 1 );
- if( rc == SSH_ERROR ) {
- fprintf( stderr, "ERROR: ssh_channel_poll on stderr failed: %s\n",
- ssh_get_error( session[i] ) );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
+ ssh_scp *scp = (ssh_scp *)malloc( ( nof_sessions + 1 ) * sizeof( ssh_scp ) );
+ memset( scp, 0, nof_sessions + 1 );
+ if( scp == NULL ) {
+ fprintf( stderr, "ERROR: Memory allocation failed for ssh_scp" );
+ cleanup_sessions( &session, NULL, NULL, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
-
- if( rc > 0 ) {
- unsigned int nread = ssh_channel_read_nonblocking( channel[i], buffer, sizeof( buffer ), 1 );
- if( nread == SSH_ERROR ) {
- fprintf( stderr, "ERROR: ssh_channel_read_nonblocking on stderr failed: %s\n",
+ for( unsigned int i = 0; i < nof_sessions; i++ ) {
+ scp[i] = ssh_scp_new( session[i],
+ ( ( copy_direction == CSSH_COPY_DIRECTION_UPLOAD ) ? SSH_SCP_WRITE : SSH_SCP_READ ) |
+ ( ( args_info.recursive_given > 0 ) ? SSH_SCP_RECURSIVE : 0 ),
+ local_directory );
+ if( scp[i] == NULL ) {
+ fprintf( stderr, "ERROR: Unable to open SCP channel: %s\n",
ssh_get_error( session[i] ) );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
+ cleanup_sessions( &session, NULL, &scp, host, port, nof_sessions, args_info.verbose_given > 0 );
exit( EXIT_FAILURE );
}
+ }
- if( nread > 0 ) {
- size_t wrc = fwrite( buffer, 1, nread, stderr );
- if( wrc < 0 ) {
- fprintf( stderr, "ERROR: while writting to stderr: %s\n",
- strerror( errno ) );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
+ cleanup_sessions( &session, NULL, &scp, host, port, nof_sessions, args_info.verbose_given > 0 );
- if( wrc != nread ) {
- fprintf( stderr, "ERROR: Write mismatch on stderr (%zu != %d)\n",
- wrc, nread );
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
- exit( EXIT_FAILURE );
- }
- }
+ } break;
- if( nread == 0 ) {
- is_eof[i] = true;
- }
- }
- }
-
- cssh_msleep( 1 );
+ case CSSH_EXECUTE_UNKNOWN:
+ break;
}
-
- cleanup_sessions( &session, &channel, host, port, nof_sessions, args_info.verbose_given > 0 );
+
exit( EXIT_SUCCESS );
}