From 7cfede3e206592ad0e4cb7a3a63a1e18ee7a5bad Mon Sep 17 00:00:00 2001 From: Tom Smeding Date: Sun, 12 Jul 2020 12:12:54 +0200 Subject: ssh: Some executable renamings --- ssh/ssh_client.c | 153 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 ssh/ssh_client.c (limited to 'ssh/ssh_client.c') diff --git a/ssh/ssh_client.c b/ssh/ssh_client.c new file mode 100644 index 0000000..5c7f084 --- /dev/null +++ b/ssh/ssh_client.c @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include +#include +#include "util.h" +#include "sshnc.h" + + +static bool prompt_yn(const char *text) { + printf("%s", text); + fflush(stdout); + + bool response; + + char *line = NULL; + size_t linelen = 0; + while (true) { + ssize_t nr = getline(&line, &linelen, stdin); + if (nr == -1) { + perror("getline"); + exit(1); + } + + while (nr > 0 && isspace(line[nr - 1])) nr--; + + for (ssize_t i = 0; i < nr; i++) line[i] = tolower(line[i]); + + if ((nr == 1 && line[0] == 'y') || (nr == 3 && memcmp(line, "yes", 3) == 0)) { + response = true; + break; + } + if ((nr == 1 && line[0] == 'n') || (nr == 2 && memcmp(line, "no", 2) == 0)) { + response = false; + break; + } + + printf("Please answer with 'y', 'n', 'yes' or 'no'. [y/n]"); + fflush(stdout); + } + + free(line); + return response; +} + +static bool hostkey_checker(const unsigned char *hash, size_t length, void *userdata) { + (void)userdata; + printf("Server host key hash: %s\n", sshnc_print_hash(hash, length)); + + bool response = prompt_yn( + "Does this hash match the one given to you by the server administrator, or by a\n" + "member that you trust and is already connected to the server? [y/n] "); + if (!response) { + printf("Disconnecting.\n"); + } + + return response; +} + +int main(int argc, char **argv) { + const char *server_host = NULL; + int port = 2222; + + if (argc != 2) { + fprintf(stderr, "Usage: %s \n", argv[0]); + fprintf(stderr, "If port is not specified, %d is assumed.\n", port); + return 1; + } + + if (!parse_host_port(argv[1], &server_host, &port)) { + fprintf(stderr, "Cannot parse host:port from argument '%s'\n", argv[1]); + return 1; + } + + struct sshnc_client *client; + enum sshnc_retval ret = sshnc_connect( + server_host, port, "tomsg", "tomsg", hostkey_checker, NULL, &client); + + if (ret != SSHNC_OK) { + fprintf(stderr, "Could not connect: %s\n", sshnc_strerror(ret)); + return 1; + } + + struct pollfd polls[2]; + polls[0] = (struct pollfd){ + .fd = sshnc_poll_fd(client), + .events = POLLIN, + }; + polls[1] = (struct pollfd){ + .fd = STDIN_FILENO, + .events = POLLIN, + }; + + while (true) { + int pollret = poll(polls, sizeof polls / sizeof polls[0], -1); + if (pollret < 0) { + perror("poll"); + goto cleanup; + } + + if (polls[0].revents & (POLLERR | POLLNVAL)) { + fprintf(stderr, "Error reading from SSH socket\n"); + goto cleanup; + } + if (polls[1].revents & (POLLERR | POLLNVAL)) { + fprintf(stderr, "Error reading from stdin\n"); + goto cleanup; + } + + if (polls[0].revents & (POLLIN | POLLHUP)) { + char buffer[4096]; + size_t length = 0; + ret = sshnc_maybe_recv(client, sizeof buffer, buffer, &length); + if (ret == SSHNC_OK) { + fwrite(buffer, 1, length, stdout); + } else if (ret == SSHNC_EOF) { + break; + } else if (ret != SSHNC_AGAIN) { + fprintf(stderr, "Error on SSH recv: %s\n", sshnc_strerror(ret)); + goto cleanup; + } + } + + if (polls[1].revents & (POLLIN | POLLHUP)) { + char buffer[4096]; + ssize_t nr = read(STDIN_FILENO, buffer, sizeof buffer); + if (nr < 0) { + perror("Error reading from stdin"); + goto cleanup; + } + if (nr == 0) { + break; + } + + ret = sshnc_send(client, buffer, nr); + if (ret == SSHNC_EOF) { + break; + } else if (ret != SSHNC_OK) { + fprintf(stderr, "Error on SSH send: %s\n", sshnc_strerror(ret)); + goto cleanup; + } + } + } + + sshnc_close(client); + return 0; + +cleanup: + sshnc_close(client); + return 1; +} -- cgit v1.2.3-54-g00ecf