From e79751284a11e222cee2185a2fca9211e511f4e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Deuc=D0=B5?= <shurd@sasktel.net> Date: Wed, 27 Dec 2023 02:42:49 -0500 Subject: [PATCH] Somewhat working now... still some issues getting the second channel working reliably though. --- src/syncterm/ssh.c | 114 +++++++++++++++++++++++++++++---------------- 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/src/syncterm/ssh.c b/src/syncterm/ssh.c index 07b1dfb6fa..3c5df27f57 100644 --- a/src/syncterm/ssh.c +++ b/src/syncterm/ssh.c @@ -2,11 +2,13 @@ /* $Id: ssh.c,v 1.31 2020/05/28 22:58:26 deuce Exp $ */ +#include <assert.h> #include <stdlib.h> #include "bbslist.h" #include "ciolib.h" #include "conn.h" +#include "eventwrap.h" #include "gen_defs.h" #include "genwrap.h" #include "sftp.h" @@ -51,60 +53,95 @@ cryptlib_error_message(int status, const char *msg) static void close_sftp_channel(void) { + if (sftp_state == NULL) + return; pthread_mutex_lock(&ssh_mutex); if (sftp_channel != -1) { - cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, sftp_channel); - cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE, 0); + if (cryptStatusOK(cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, sftp_channel))) + cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE, 0); sftp_channel = -1; } pthread_mutex_unlock(&ssh_mutex); sftpc_finish(sftp_state); + sftp_state = NULL; +} + +static void +close_ssh_channel(void) +{ + pthread_mutex_lock(&ssh_mutex); + if (ssh_channel != -1) { + if (cryptStatusOK(cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, ssh_channel))) + cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE, 0); + ssh_channel = -1; + } + pthread_mutex_unlock(&ssh_mutex); } void ssh_input_thread(void *args) { - int status; + int popstatus, gchstatus, status; int rd; size_t buffered; size_t buffer; int chan; SetThreadName("SSH Input"); - conn_api.input_thread_running = 1; while (ssh_active && !conn_api.terminate) { if (!socket_readable(ssh_sock, 100)) continue; pthread_mutex_lock(&ssh_mutex); - status = cl.FlushData(ssh_session); - status = cl.PopData(ssh_session, conn_api.rd_buf, conn_api.rd_buf_size, &rd); - if (cryptStatusOK(status)) - status = cl.GetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, &chan); + conn_api.input_thread_running = 1; + cl.FlushData(ssh_session); + popstatus = cl.PopData(ssh_session, conn_api.rd_buf, conn_api.rd_buf_size, &rd); + gchstatus = cl.GetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, &chan); pthread_mutex_unlock(&ssh_mutex); // Handle case where there was socket activity without readable data (ie: rekey) - if (status == CRYPT_ERROR_TIMEOUT) + if (popstatus == CRYPT_ERROR_TIMEOUT) continue; - if (cryptStatusError(status)) { - if ((status == CRYPT_ERROR_COMPLETE) || (status == CRYPT_ERROR_READ) || (status == CRYPT_ERROR_NOTFOUND)) { /* connection closed */ - ssh_active = true; + // A final read on a channel just occured... figure out which is missing... + if (gchstatus == CRYPT_ERROR_NOTFOUND) { + if (ssh_channel != -1) { + status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, ssh_channel); + if (status == CRYPT_ERROR_NOTFOUND) { + chan = ssh_channel; + } + } + if (chan == -1) { + if (sftp_channel != -1) { + status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, ssh_channel); + if (status == CRYPT_ERROR_NOTFOUND) { + chan = sftp_channel; + } + } + } + } + + if (cryptStatusError(popstatus)) { + if ((popstatus == CRYPT_ERROR_COMPLETE) || (popstatus == CRYPT_ERROR_READ)) { /* connection closed */ + if (chan == ssh_channel) + break; + } + else { + cryptlib_error_message(popstatus, "recieving data"); break; } - cryptlib_error_message(status, "recieving data"); - ssh_active = true; - break; } else { if (chan == sftp_channel) { if (!sftpc_recv(sftp_state, conn_api.rd_buf, rd)) { - ssh_active = true; close_sftp_channel(); continue; } + if (gchstatus == CRYPT_ERROR_NOTFOUND) { + sftp_channel = -1; + } } - else { + else if (chan == ssh_channel) { buffered = 0; while (buffered < rd) { pthread_mutex_lock(&(conn_inbuf.mutex)); @@ -112,6 +149,13 @@ ssh_input_thread(void *args) buffered += conn_buf_put(&conn_inbuf, conn_api.rd_buf + buffered, buffer); pthread_mutex_unlock(&(conn_inbuf.mutex)); } + if (gchstatus == CRYPT_ERROR_NOTFOUND) { + ssh_channel = -1; + } + } + else { + assert(true); + cryptlib_error_message(gchstatus, "unknown channel"); } } } @@ -128,7 +172,7 @@ ssh_output_thread(void *args) SetThreadName("SSH Output"); conn_api.output_thread_running = 1; - while (ssh_active && !conn_api.terminate) { + while (ssh_active && !conn_api.terminate && ssh_channel != -1) { pthread_mutex_lock(&(conn_outbuf.mutex)); wr = conn_buf_wait_bytes(&conn_outbuf, 1, 100); if (wr) { @@ -138,17 +182,19 @@ ssh_output_thread(void *args) while (ssh_active && sent < wr) { ret = 0; pthread_mutex_lock(&ssh_mutex); + if (ssh_channel == -1) { + pthread_mutex_unlock(&ssh_mutex); + break; + } status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, ssh_channel); if (cryptStatusOK(status)) status = cl.PushData(ssh_session, conn_api.wr_buf + sent, wr - sent, &ret); pthread_mutex_unlock(&ssh_mutex); if (cryptStatusError(status)) { if ((status == CRYPT_ERROR_COMPLETE) || (status == CRYPT_ERROR_NOTFOUND)) { /* connection closed */ - ssh_active = true; break; } cryptlib_error_message(status, "sending data"); - ssh_active = true; break; } sent += ret; @@ -187,11 +233,9 @@ sftp_send(uint8_t *buf, size_t sz, void *cb_data) cryptlib_error_message(status, "sending sftp data"); if (cryptStatusError(status)) { if (status == CRYPT_ERROR_COMPLETE) { /* connection closed */ - ssh_active = true; // TODO: Why are we doing this? break; } cryptlib_error_message(status, "sending sftp data"); - ssh_active = true; break; } sent += ret; @@ -380,6 +424,7 @@ ssh_connect(struct bbslist *bbs) uifc.pop(NULL); return -1; } + cl.FlushData(ssh_session); ssh_active = true; if (!bbs->hidepopups) { @@ -426,57 +471,47 @@ ssh_connect(struct bbslist *bbs) #if NOTYET // TODO: Without this sleep, all is woe. - SLEEP(10); + //SLEEP(10); + while (!conn_api.input_thread_running) + SLEEP(1); if (cryptStatusOK(status)) { -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); if (!bbs->hidepopups) { /* Clear ownership */ uifc.pop(NULL); uifc.pop("Creating SFTP Channel"); } -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); pthread_mutex_lock(&ssh_mutex); -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, CRYPT_UNUSED); -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); if (cryptStatusError(status)) cryptlib_error_message(status, "setting new channel"); if (cryptStatusOK(status)) { -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); status = cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_TYPE, "subsystem", 9); if (cryptStatusError(status)) cryptlib_error_message(status, "setting channel type"); if (cryptStatusOK(status)) { -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); status = cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_ARG1, "sftp", 4); if (cryptStatusError(status)) cryptlib_error_message(status, "setting subsystem"); if (cryptStatusOK(status)) { -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); status = cl.GetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, &sftp_channel); if (cryptStatusError(status)) cryptlib_error_message(status, "getting new channel"); if (cryptStatusOK(status)) { -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); // TODO: Do something... } } } } - pthread_mutex_unlock(&ssh_mutex); } if (sftp_channel != -1) { -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); pthread_mutex_lock(&ssh_mutex); -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); + cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, sftp_channel); status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE, 1); pthread_mutex_unlock(&ssh_mutex); -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); - if (cryptStatusError(status)) + if (cryptStatusError(status)) { cryptlib_error_message(status, "activating sftp session"); -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); + } if (cryptStatusOK(status)) { -fprintf(stderr, "%s:%d\n", __FILE__, __LINE__); sftp_state = sftpc_begin(sftp_send, NULL); if (sftp_state == NULL) fprintf(stderr, "Failure!\n"); @@ -498,7 +533,8 @@ ssh_close(void) char garbage[1024]; conn_api.terminate = 1; - cl.SetAttribute(ssh_session, CRYPT_SESSINFO_ACTIVE, 0); + close_sftp_channel(); + close_ssh_channel(); ssh_active = false; while (conn_api.input_thread_running == 1 || conn_api.output_thread_running == 1) { conn_recv_upto(garbage, sizeof(garbage), 0); -- GitLab