improve error handling, allow user to input stuff

This commit is contained in:
cy384 2020-06-19 18:58:20 -04:00
parent 3893ca8d62
commit 98e3bf2d57
2 changed files with 95 additions and 92 deletions

View File

@ -7,7 +7,7 @@ set_target_properties(ssheven PROPERTIES COMPILE_OPTIONS -ffunction-sections)
IF(CMAKE_SYSTEM_NAME MATCHES Retro68) IF(CMAKE_SYSTEM_NAME MATCHES Retro68)
# for 68k # for 68k
set_target_properties(ssheven PROPERTIES LINK_FLAGS "-Wl,-gc-sections -Wl,--mac-strip-macsbug -Wl,--mac-segments -Wl,${CMAKE_CURRENT_SOURCE_DIR}/ssheven.segmap") set_target_properties(ssheven PROPERTIES LINK_FLAGS "-Wl,-gc-sections -Wl,--mac-strip-macsbug -Wl,--mac-segments -Wl,${CMAKE_CURRENT_SOURCE_DIR}/ssheven.segmap")
target_link_libraries(ssheven RetroConsole ThreadsLib ssh2 mbedtls mbedx509 mbedcrypto OpenTransportApp OpenTransport OpenTptInet) target_link_libraries(ssheven RetroConsole ssh2 mbedtls mbedx509 mbedcrypto OpenTransportApp OpenTransport OpenTptInet)
ELSE() ELSE()
# for PPC # for PPC
set_target_properties(ssheven PROPERTIES LINK_FLAGS "-Wl,-gc-sections") set_target_properties(ssheven PROPERTIES LINK_FLAGS "-Wl,-gc-sections")

185
ssheven.c
View File

@ -18,6 +18,12 @@
// libssh2 // libssh2
#include <libssh2.h> #include <libssh2.h>
// network buffer size
enum { buffer_size = 4096 };
// text input buffer size
enum { input_buffer_size = 128 };
const char* libssh2_error_string(int i) const char* libssh2_error_string(int i)
{ {
switch (i) switch (i)
@ -123,14 +129,7 @@ const char* libssh2_error_string(int i)
return "unknown error number"; return "unknown error number";
} }
return "what???"; return "should never return from here?";
}
enum { buffer_size = 4096 };
void assertp(char* message, int b)
{
if (!b) printf("assert fail: %s (%d)\n", message, b);
} }
// event handler to yield whenever we're blocked // event handler to yield whenever we're blocked
@ -147,107 +146,94 @@ static pascal void yield_notifier(void* contextPtr, OTEventCode code, OTResult r
} }
} }
void do_ssh_connection(void) void get_line(char* buffer)
{ {
char* hostname = "10.0.2.2:22"; int i = 0;
char* username = "ssheven"; char c;
char* password = "password";
char* command = "uname -a";
while (i < input_buffer_size - 1)
{
c = getc(stdin);
if (c != '\n') buffer[i++] = c; else break;
}
buffer[i] = '\0';
return;
}
void do_ssh_connection(char* hostname, char* username, char* password, char* command)
{
// libssh2 vars
LIBSSH2_CHANNEL* channel; LIBSSH2_CHANNEL* channel;
LIBSSH2_SESSION* session; LIBSSH2_SESSION* session;
int rc; int rc;
// make and set up OT connection // OT vars
OSStatus err = noErr; OSStatus err = noErr;
Ptr buffer = nil; char* buffer = NULL;
EndpointRef endpoint = kOTInvalidEndpointRef; EndpointRef endpoint = kOTInvalidEndpointRef;
TCall sndCall; TCall sndCall;
DNSAddress hostDNSAddress; DNSAddress hostDNSAddress;
OSStatus result;
OTFlags ot_flags;
// allocate buffer // allocate buffer
buffer = OTAllocMem(buffer_size); buffer = OTAllocMem(buffer_size);
if (buffer == nil) if (buffer == NULL)
{ {
printf("could not get memory!!!\n"); printf("failed to allocate OT buffer\n");
return; return;
} }
else
{
printf("got OT buffer\n");
}
// open TCP endpoint // open TCP endpoint
endpoint = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err); endpoint = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, nil, &err);
assertp("endpoint opened", err == noErr); if (err != noErr)
if (err != noErr) return; {
printf("failed to open TCP endpoint\n");
if (buffer != NULL) OTFreeMem(buffer);
return;
}
// configure the endpoint #define OT_CHECK(X) err = (X); if (err != noErr) { printf("" #X " failed: %d\n", err); goto OT_cleanup; };
// synchronous and blocking, and we yield until we get a result
OSStatus result; OT_CHECK(OTSetSynchronous(endpoint));
OT_CHECK(OTSetBlocking(endpoint));
result = OTSetSynchronous(endpoint); OT_CHECK(OTInstallNotifier(endpoint, yield_notifier, nil));
assertp("OTSetSynchronous failed", result == noErr); OT_CHECK(OTUseSyncIdleEvents(endpoint, true));
OT_CHECK(OTBind(endpoint, nil, nil));
result = OTSetBlocking(endpoint);
assertp("OTSetBlocking failed", result == noErr);
result = OTInstallNotifier(endpoint, yield_notifier, nil);
assertp("OTInstallNotifier failed", result == noErr);
result = OTUseSyncIdleEvents(endpoint, true);
assertp("OTUseSyncIdleEvents failed", result == noErr);
err = OTBind(endpoint, nil, nil);
assertp("OTBind failed", err == noErr);
if (err != noErr) return;
// set up address struct and connect
// set up address struct, do the DNS lookup, and connect
OTMemzero(&sndCall, sizeof(TCall)); OTMemzero(&sndCall, sizeof(TCall));
sndCall.addr.buf = (UInt8 *) &hostDNSAddress; sndCall.addr.buf = (UInt8 *) &hostDNSAddress;
sndCall.addr.len = OTInitDNSAddress(&hostDNSAddress, (char *) hostname); sndCall.addr.len = OTInitDNSAddress(&hostDNSAddress, (char *) hostname);
err = OTConnect(endpoint, &sndCall, nil); OT_CHECK(OTConnect(endpoint, &sndCall, nil));
assertp("OTConnect failed", err == noErr);
if (err != noErr) return; printf("OT setup done, endpoint: %d, (should not be %d for libssh2,"
" should not be %d for OT)\n", (int) endpoint,
(int) LIBSSH2_INVALID_SOCKET, (int) kOTInvalidEndpointRef);
printf("OT setup done, endpoint: %d, (should not be %d for libssh2, should not be %d for OT)\n", (int) endpoint, (int) LIBSSH2_INVALID_SOCKET, (int) kOTInvalidEndpointRef); #define SSH_CHECK(X) rc = (X); if (rc != LIBSSH2_ERROR_NONE) { printf("" #X "failed: %s\n", libssh2_error_string(rc)); goto libssh2_cleanup; };
// init libssh2 // init libssh2
rc = libssh2_init(0); SSH_CHECK(libssh2_init(0));
printf("init rc %s\n", libssh2_error_string(rc));
session = libssh2_session_init(); session = libssh2_session_init();
if (session != 0) if (session == 0)
{ {
printf("session ok\n"); printf("failed to open SSH session\n");
} goto libssh2_cleanup;
else
{
printf("session fail\n");
return;
} }
rc = libssh2_session_handshake(session, endpoint); SSH_CHECK(libssh2_session_handshake(session, endpoint));
printf("handshake rc %s\n", libssh2_error_string(rc));
if (rc != LIBSSH2_ERROR_NONE) return;
rc = libssh2_userauth_password(session, username, password); SSH_CHECK(libssh2_userauth_password(session, username, password));
printf("authenticate rc %s\n", libssh2_error_string(rc));
if (rc != LIBSSH2_ERROR_NONE) return;
channel = libssh2_channel_open_session(session); channel = libssh2_channel_open_session(session);
printf("channel open: %d\n", channel); printf("channel open: %d\n", channel);
printf("sending command \"%s\"\n", command); SSH_CHECK(libssh2_channel_exec(channel, command));
rc = libssh2_channel_exec(channel, command);
printf("libssh2_channel_exec rc %s\n", libssh2_error_string(rc));
// read from the channel // read from the channel
rc = libssh2_channel_read(channel, buffer, buffer_size); rc = libssh2_channel_read(channel, buffer, buffer_size);
@ -262,23 +248,18 @@ void do_ssh_connection(void)
printf("channel read error: %s\n", libssh2_error_string(rc)); printf("channel read error: %s\n", libssh2_error_string(rc));
} }
rc = libssh2_channel_close(channel); libssh2_cleanup:
printf("libssh2_channel_close rc %s\n", libssh2_error_string(rc));
libssh2_channel_close(channel);
libssh2_channel_free(channel); libssh2_channel_free(channel);
libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing"); libssh2_session_disconnect(session, "Normal Shutdown, Thank you for playing");
libssh2_session_free(session); libssh2_session_free(session);
libssh2_exit(); libssh2_exit();
// request to close the TCP connection // request to close the TCP connection
rc = OTSndOrderlyDisconnect(endpoint); OT_CHECK(OTSndOrderlyDisconnect(endpoint));
assertp("OTSndOrderlyDisconnect failed", rc == noErr);
// get any remaining data so we can finish closing the connection // get and discard remaining data so we can finish closing the connection
OTFlags ot_flags;
rc = 1; rc = 1;
while (rc != kOTLookErr) while (rc != kOTLookErr)
{ {
@ -286,26 +267,28 @@ void do_ssh_connection(void)
} }
// finish closing the TCP connection // finish closing the TCP connection
OTResult look_result = OTLook(endpoint); result = OTLook(endpoint);
switch (look_result) switch (result)
{ {
case T_DISCONNECT: case T_DISCONNECT:
err = OTRcvDisconnect(endpoint, nil); OTRcvDisconnect(endpoint, nil);
break; break;
default: default:
printf("other connection error: %d\n", look_result); printf("unexpected OTLook result while closing: %d\n", result);
break; break;
} }
OT_cleanup:
// release endpoint // release endpoint
result = OTUnbind(endpoint); err = OTUnbind(endpoint);
assertp("OTUnbind failed", result == noErr); if (err != noErr) printf("OTUnbind failed: %d\n", err);
result = OTCloseProvider(endpoint); err = OTCloseProvider(endpoint);
assertp("OTCloseProvider failed", result == noErr); if (err != noErr) printf("OTCloseProvider failed: %d\n", err);
// if we got a buffer, release it // if we have a buffer, release it
if (buffer != nil) OTFreeMem(buffer); if (buffer != nil) OTFreeMem(buffer);
return; return;
@ -313,20 +296,40 @@ void do_ssh_connection(void)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
printf("starting up\n"); char hostname[input_buffer_size] = {0};
char username[input_buffer_size] = {0};
char password[input_buffer_size] = {0};
char command[input_buffer_size] = {0};
printf("WARNING: this is a prototype with a bad RNG and no host key checks,"
" do not use over untrusted networks or with untrusted SSH servers!\n\n");
printf("ssheven by cy384 version 0.0.0\n\n");
printf("enter a host:port >"); fflush(stdout);
get_line(hostname);
printf("enter a username >"); fflush(stdout);
get_line(username);
printf("enter a password >"); fflush(stdout);
get_line(password);
printf("enter a command >"); fflush(stdout);
get_line(command);
if (InitOpenTransport() != noErr) if (InitOpenTransport() != noErr)
{ {
printf("failed to init OT \n"); printf("failed to initialize OT\n");
return 0; return 0;
} }
do_ssh_connection(); do_ssh_connection(hostname, username, password, command);
CloseOpenTransport(); CloseOpenTransport();
printf("\n(a to exit)\n"); printf("\n(enter to exit)\n");
while (getchar() != 'a'); getchar();
return 0; return 0;
} }