diff --git a/3rdp/build/GNUmakefile b/3rdp/build/GNUmakefile index 52535a26420ff0c8f716c02eb7faf4820196563c..ff3383339ba106d5f5e76b470c9d526c3d2994bf 100644 --- a/3rdp/build/GNUmakefile +++ b/3rdp/build/GNUmakefile @@ -88,7 +88,7 @@ $(CRYPT_SRC): | $(3RDPSRCDIR) $(CRYPT_IDIR): | $(3RDPODIR) $(QUIET)$(IFNOTEXIST) mkdir $(CRYPT_IDIR) -$(CRYPTLIB_BUILD): $(3RDP_ROOT)/dist/cryptlib.zip $(3RDP_ROOT)/build/terminal-params.patch $(3RDP_ROOT)/build/cl-mingw32-static.patch $(3RDP_ROOT)/build/cl-ranlib.patch $(3RDP_ROOT)/build/cl-win32-noasm.patch $(3RDP_ROOT)/build/cl-zz-country.patch $(3RDP_ROOT)/build/cl-algorithms.patch $(3RDP_ROOT)/build/cl-allow-duplicate-ext.patch $(3RDP_ROOT)/build/cl-macosx-minver.patch $(3RDP_ROOT)/build/cl-endian.patch $(3RDP_ROOT)/build/cl-cryptodev.patch $(3RDP_ROOT)/build/cl-posix-me-gently.patch $(3RDP_ROOT)/build/cl-tpm-linux.patch $(3RDP_ROOT)/build/cl-PAM-noprompts.patch $(3RDP_ROOT)/build/cl-zlib.patch $(3RDP_ROOT)/build/Dynamic-linked-static-lib.patch $(3RDP_ROOT)/build/SSL-fix.patch $(3RDP_ROOT)/build/cl-bigger-maxattribute.patch $(3RDP_ROOT)/build/cl-vcxproj.patch $(3RDP_ROOT)/build/cl-mingw-vcver.patch $(3RDP_ROOT)/build/cl-win32-build-fix.patch $(3RDP_ROOT)/build/cl-gcc-non-const-time-val.patch $(3RDP_ROOT)/build/cl-no-odbc.patch $(3RDP_ROOT)/build/cl-noasm-defines.patch $(3RDP_ROOT)/build/cl-bn-noasm64-fix.patch $(3RDP_ROOT)/build/cl-no-RSA-suites.patch $(3RDP_ROOT)/build/cl-fix-ECC-RSA.patch $(3RDP_ROOT)/build/cl-prefer-ECC.patch $(3RDP_ROOT)/build/cl-prefer-ECC-harder.patch $(3RDP_ROOT)/build/cl-more-RSA-ECC-fixes.patch $(3RDP_ROOT)/build/cl-DH-key-init.patch $(3RDP_ROOT)/build/cl-clear-GCM-flag.patch $(3RDP_ROOT)/build/cl-use-ssh-ctr.patch $(3RDP_ROOT)/build/cl-ssh-list-ctr-modes.patch $(3RDP_ROOT)/build/cl-ssh-incCtr.patch $(3RDP_ROOT)/build/cl-ssl-suite-blocksizes.patch $(3RDP_ROOT)/build/cl-no-tpm.patch $(3RDP_ROOT)/build/cl-no-via-aes.patch $(3RDP_ROOT)/build/cl-fix-ssh-ecc-ephemeral.patch $(3RDP_ROOT)/build/cl-just-use-cc.patch $(3RDP_ROOT)/build/cl-learn-numbers.patch $(3RDP_ROOT)/build/cl-no-safe-stack.patch $(3RDP_ROOT)/build/cl-allow-pkcs12.patch $(3RDP_ROOT)/build/cl-uint64_t-redefine.patch $(3RDP_ROOT)/build/cl-random-openbsd.patch $(3RDP_ROOT)/build/cl-openbsd-threads.patch $(3RDP_ROOT)/build/cl-allow-none-auth.patch $(3RDP_ROOT)/build/cl-mingw-add-m32.patch $(3RDP_ROOT)/build/cl-poll-not-select.patch $(3RDP_ROOT)/build/cl-check-before-use.patch $(3RDP_ROOT)/build/cl-linux-yield.patch $(3RDP_ROOT)/build/cl-good-sockets.patch $(3RDP_ROOT)/build/cl-moar-objects.patch $(3RDP_ROOT)/build/cl-pthread_yield.patch $(3RDP_ROOT)/build/cl-check-cert-dont-modify.patch $(3RDP_ROOT)/build/cl-server-term-support.patch | $(CRYPT_SRC) $(CRYPT_IDIR) $(3RDP_ROOT)/build/cl-remove-march.patch +$(CRYPTLIB_BUILD): $(3RDP_ROOT)/dist/cryptlib.zip $(3RDP_ROOT)/build/terminal-params.patch $(3RDP_ROOT)/build/cl-mingw32-static.patch $(3RDP_ROOT)/build/cl-ranlib.patch $(3RDP_ROOT)/build/cl-win32-noasm.patch $(3RDP_ROOT)/build/cl-zz-country.patch $(3RDP_ROOT)/build/cl-algorithms.patch $(3RDP_ROOT)/build/cl-allow-duplicate-ext.patch $(3RDP_ROOT)/build/cl-macosx-minver.patch $(3RDP_ROOT)/build/cl-endian.patch $(3RDP_ROOT)/build/cl-cryptodev.patch $(3RDP_ROOT)/build/cl-posix-me-gently.patch $(3RDP_ROOT)/build/cl-tpm-linux.patch $(3RDP_ROOT)/build/cl-PAM-noprompts.patch $(3RDP_ROOT)/build/cl-zlib.patch $(3RDP_ROOT)/build/Dynamic-linked-static-lib.patch $(3RDP_ROOT)/build/SSL-fix.patch $(3RDP_ROOT)/build/cl-bigger-maxattribute.patch $(3RDP_ROOT)/build/cl-vcxproj.patch $(3RDP_ROOT)/build/cl-mingw-vcver.patch $(3RDP_ROOT)/build/cl-win32-build-fix.patch $(3RDP_ROOT)/build/cl-gcc-non-const-time-val.patch $(3RDP_ROOT)/build/cl-no-odbc.patch $(3RDP_ROOT)/build/cl-noasm-defines.patch $(3RDP_ROOT)/build/cl-bn-noasm64-fix.patch $(3RDP_ROOT)/build/cl-no-RSA-suites.patch $(3RDP_ROOT)/build/cl-fix-ECC-RSA.patch $(3RDP_ROOT)/build/cl-prefer-ECC.patch $(3RDP_ROOT)/build/cl-prefer-ECC-harder.patch $(3RDP_ROOT)/build/cl-more-RSA-ECC-fixes.patch $(3RDP_ROOT)/build/cl-DH-key-init.patch $(3RDP_ROOT)/build/cl-clear-GCM-flag.patch $(3RDP_ROOT)/build/cl-use-ssh-ctr.patch $(3RDP_ROOT)/build/cl-ssh-list-ctr-modes.patch $(3RDP_ROOT)/build/cl-ssh-incCtr.patch $(3RDP_ROOT)/build/cl-ssl-suite-blocksizes.patch $(3RDP_ROOT)/build/cl-no-tpm.patch $(3RDP_ROOT)/build/cl-no-via-aes.patch $(3RDP_ROOT)/build/cl-fix-ssh-ecc-ephemeral.patch $(3RDP_ROOT)/build/cl-just-use-cc.patch $(3RDP_ROOT)/build/cl-learn-numbers.patch $(3RDP_ROOT)/build/cl-no-safe-stack.patch $(3RDP_ROOT)/build/cl-allow-pkcs12.patch $(3RDP_ROOT)/build/cl-uint64_t-redefine.patch $(3RDP_ROOT)/build/cl-random-openbsd.patch $(3RDP_ROOT)/build/cl-openbsd-threads.patch $(3RDP_ROOT)/build/cl-allow-none-auth.patch $(3RDP_ROOT)/build/cl-mingw-add-m32.patch $(3RDP_ROOT)/build/cl-poll-not-select.patch $(3RDP_ROOT)/build/cl-check-before-use.patch $(3RDP_ROOT)/build/cl-linux-yield.patch $(3RDP_ROOT)/build/cl-good-sockets.patch $(3RDP_ROOT)/build/cl-moar-objects.patch $(3RDP_ROOT)/build/cl-pthread_yield.patch $(3RDP_ROOT)/build/cl-check-cert-dont-modify.patch $(3RDP_ROOT)/build/cl-server-term-support.patch $(3RDP_ROOT)/build/cl-add-pubkey-attribute.patch | $(CRYPT_SRC) $(CRYPT_IDIR) $(3RDP_ROOT)/build/cl-remove-march.patch @echo Creating $@ ... $(QUIET)-rm -rf $(CRYPT_SRC)/* $(QUIET)unzip -oa $(3RDPDISTDIR)/cryptlib.zip -d $(CRYPT_SRC) @@ -148,6 +148,7 @@ $(CRYPTLIB_BUILD): $(3RDP_ROOT)/dist/cryptlib.zip $(3RDP_ROOT)/build/terminal-pa $(QUIET)patch -b -p0 -d $(CRYPT_SRC) < cl-remove-march.patch $(QUIET)patch -b -p0 -d $(CRYPT_SRC) < cl-pthread_yield.patch $(QUIET)patch -b -p0 -d $(CRYPT_SRC) < cl-server-term-support.patch + $(QUIET)patch -b -p0 -d $(CRYPT_SRC) < cl-add-pubkey-attribute.patch ifeq ($(os),win32) $(QUIET)cd $(CRYPT_SRC) && env - PATH="$(PATH)" CC="$(CC)" AR="$(AR)" RANLIB="$(RANLIB)" make directories $(QUIET)cd $(CRYPT_SRC) && env - PATH="$(PATH)" CC="$(CC)" AR="$(AR)" RANLIB="$(RANLIB)" make toolscripts diff --git a/3rdp/build/cl-add-pubkey-attribute.patch b/3rdp/build/cl-add-pubkey-attribute.patch new file mode 100644 index 0000000000000000000000000000000000000000..d30bd2ab13af64de2dcd348fdb0291a05f57d89a --- /dev/null +++ b/3rdp/build/cl-add-pubkey-attribute.patch @@ -0,0 +1,48 @@ +diff -ur ../cl-old/context/ctx_attr.c ./context/ctx_attr.c +--- ../cl-old/context/ctx_attr.c 2023-12-28 05:19:27.058456000 -0500 ++++ ./context/ctx_attr.c 2023-12-28 05:41:08.265717000 -0500 +@@ -419,6 +419,7 @@ + case CRYPT_IATTRIBUTE_KEY_SSH: + case CRYPT_IATTRIBUTE_KEY_SSL: + case CRYPT_IATTRIBUTE_KEY_SSL_EXT: ++ case CRYPT_CTXINFO_SSH_PUBLIC_KEY: + { + const PKC_WRITEKEY_FUNCTION writePublicKeyFunction = \ + ( PKC_WRITEKEY_FUNCTION ) \ +diff -ur ../cl-old/context/keyload.c ./context/keyload.c +--- ../cl-old/context/keyload.c 2023-12-28 05:19:27.069792000 -0500 ++++ ./context/keyload.c 2023-12-28 05:41:08.270975000 -0500 +@@ -39,6 +39,7 @@ + { CRYPT_IATTRIBUTE_KEY_PGP_PARTIAL, KEYFORMAT_PGP }, + { CRYPT_IATTRIBUTE_KEY_SPKI, KEYFORMAT_CERT }, + { CRYPT_IATTRIBUTE_KEY_SPKI_PARTIAL, KEYFORMAT_CERT }, ++ { CRYPT_CTXINFO_SSH_PUBLIC_KEY, KEYFORMAT_SSH }, + { CRYPT_ERROR, 0 }, { CRYPT_ERROR, 0 } + }; + int value, status; +diff -ur ../cl-old/cryptlib.h ./cryptlib.h +--- ../cl-old/cryptlib.h 2023-12-28 05:19:25.405198000 -0500 ++++ ./cryptlib.h 2023-12-28 05:41:08.275709000 -0500 +@@ -562,6 +562,7 @@ + /* Misc.information */ + CRYPT_CTXINFO_LABEL, /* Label for private/secret key */ + CRYPT_CTXINFO_PERSISTENT, /* Obj.is backed by device or keyset */ ++ CRYPT_CTXINFO_SSH_PUBLIC_KEY, + + /* Used internally */ + CRYPT_CTXINFO_LAST, CRYPT_CERTINFO_FIRST = 2000, +diff -ur ../cl-old/kernel/attr_acl.c ./kernel/attr_acl.c +--- ../cl-old/kernel/attr_acl.c 2023-12-28 05:19:27.269520000 -0500 ++++ ./kernel/attr_acl.c 2023-12-28 05:48:43.951684000 -0500 +@@ -760,6 +760,11 @@ + MKPERM( Rxx_RWD ), + ROUTE( OBJECT_TYPE_CONTEXT ), + subACL_CtxinfoPersistent ), ++ MKACL_S( /* Hash value */ ++ CRYPT_CTXINFO_SSH_PUBLIC_KEY, ++ ST_CTX_PKC, ST_NONE, ST_NONE, ++ MKPERM( Rxx_Rxx ), ++ ROUTE( OBJECT_TYPE_CONTEXT ), RANGE( 16 + MIN_PKCSIZE, ( CRYPT_MAX_PKCSIZE * 4 ) + 20 ) ), + MKACL_END(), MKACL_END() + }; + diff --git a/src/syncterm/ssh.c b/src/syncterm/ssh.c index f4065954639e29489747d2c0b569045a6b1dd4b9..d389c564ec89a33865b89fde4e712fd45b2f2785 100644 --- a/src/syncterm/ssh.c +++ b/src/syncterm/ssh.c @@ -5,6 +5,7 @@ #include <assert.h> #include <stdlib.h> +#include "base64.h" #include "bbslist.h" #include "ciolib.h" #include "conn.h" @@ -18,6 +19,7 @@ #include "threadwrap.h" #include "uifcinit.h" #include "window.h" +#include "xpendian.h" SOCKET ssh_sock; CRYPT_SESSION ssh_session; @@ -45,7 +47,7 @@ cryptlib_error_message(int status, const char *msg) pthread_mutex_unlock(&ssh_mutex); errmsg[strlen(str) + err_len] = 0; strcat(errmsg, "\r\n\r\n"); - sprintf(str2, "Error %s", msg); + sprintf(str2, "Error %d %s", status, msg); uifcmsg(str2, errmsg); free(errmsg); } @@ -242,15 +244,129 @@ sftp_send(uint8_t *buf, size_t sz, void *cb_data) } return sent == sz; } + +static char * +get_public_key(CRYPT_CONTEXT ctx) +{ + int sz; + int status; + char *raw; + char *ret; + size_t rsz; + + status = cl.GetAttributeString(ctx, CRYPT_CTXINFO_SSH_PUBLIC_KEY, NULL, &sz); + if (cryptStatusOK(status)) { + fprintf(stderr, "Size: %d\n", sz); + raw = malloc(sz); + if (raw != NULL) { + status = cl.GetAttributeString(ctx, CRYPT_CTXINFO_SSH_PUBLIC_KEY, raw, &sz); + if (cryptStatusOK(status)) { + rsz = sz * 4 / 3 + 3; + ret = malloc(rsz); + if (ret != NULL) { + b64_encode(ret, rsz, raw, sz); + free(raw); + return ret; + } + } + free(raw); + } + } + fprintf(stderr, "Error %d\n", status); + return NULL; +} + +static bool +add_public_key(struct bbslist *bbs, char *priv) +{ + int status; + bool added = false; + + // TODO: Without this sleep, all is woe. + //SLEEP(10); + while (!conn_api.input_thread_running) + SLEEP(1); + if (!bbs->hidepopups) { + uifc.pop(NULL); + uifc.pop("Creating SFTP Channel"); + } + pthread_mutex_lock(&ssh_mutex); + status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, CRYPT_UNUSED); + if (cryptStatusError(status)) { + cryptlib_error_message(status, "setting new channel"); + } + if (cryptStatusOK(status)) { + 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)) { + status = cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_ARG1, "sftp", 4); + if (cryptStatusError(status)) + cryptlib_error_message(status, "setting subsystem"); + if (cryptStatusOK(status)) { + status = cl.GetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, &sftp_channel); + if (cryptStatusError(status)) + cryptlib_error_message(status, "getting new channel"); + if (cryptStatusOK(status)) { + // TODO: Do something... + } + } + } + } + if (sftp_channel != -1) { + pthread_mutex_lock(&ssh_mutex); + 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); + if (cryptStatusError(status)) { + cryptlib_error_message(status, "activating sftp session"); + } + if (cryptStatusOK(status)) { + sftp_state = sftpc_begin(sftp_send, NULL); + if (sftp_state != NULL) { + if (sftpc_init(sftp_state)) { + sftp_str_t ret = NULL; + sftp_filehandle_t f = NULL; + + if (sftpc_open(sftp_state, ".ssh/authorized_keys", SSH_FXF_READ, NULL, &f)) { + if (sftpc_read(sftp_state, f, 0, 1024, &ret)) { + fprintf(stderr, "First lines... %s\n", ret->c_str); + free_sftp_str(ret); + added = true; + } + sftpc_close(sftp_state, &f); + } + } + } + } + pthread_mutex_lock(&ssh_mutex); + cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, sftp_channel); + status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_ACTIVE, 0); + if (cryptStatusOK(status)) + sftp_channel = -1; + pthread_mutex_unlock(&ssh_mutex); + } + return added; +} +#else +static char * +get_public_key(CRYPT_CONTEXT ctx) +{ + return NULL; +} + +static bool +add_public_key(struct bbslist *bbs, char *priv) +{ + return true; +} #endif static void error_popup(struct bbslist *bbs, const char *blurb, int status) { - char str[1024]; - sprintf(str, "Error %d %s", status, blurb); if (!bbs->hidepopups) - uifcmsg(str, str); + cryptlib_error_message(status, blurb); conn_api.terminate = 1; if (!bbs->hidepopups) uifc.pop(NULL); @@ -272,6 +388,7 @@ ssh_connect(struct bbslist *bbs) char path[MAX_PATH+1]; CRYPT_KEYSET ssh_keyset; CRYPT_CONTEXT ssh_context; + char *pubkey = NULL; ssh_channel = -1; sftp_channel = -1; @@ -419,9 +536,11 @@ ssh_connect(struct bbslist *bbs) if (ssh_context != -1) { if (!bbs->hidepopups) uifc.pop("Setting Private Key"); + pubkey = get_public_key(ssh_context); status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_PRIVATEKEY, ssh_context); cl.DestroyContext(ssh_context); if (cryptStatusError(status)) { + free(pubkey); error_popup(bbs, "setting private key", status); return -1; } @@ -436,6 +555,7 @@ ssh_connect(struct bbslist *bbs) /* Pass socket to cryptlib */ status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_NETWORKSOCKET, ssh_sock); if (cryptStatusError(status)) { + free(pubkey); error_popup(bbs, "passing socket", status); return -1; } @@ -470,28 +590,21 @@ ssh_connect(struct bbslist *bbs) } status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_ACTIVE, 1); if (cryptStatusError(status)) { - if (!bbs->hidepopups) - cryptlib_error_message(status, "activating session"); - conn_api.terminate = 1; - if (!bbs->hidepopups) - uifc.pop(NULL); + free(pubkey); + error_popup(bbs, "activating session", status); return -1; } cl.FlushData(ssh_session); ssh_active = true; if (!bbs->hidepopups) { - /* Clear ownership */ uifc.pop(NULL); uifc.pop("Clearing Ownership"); } status = cl.SetAttribute(ssh_session, CRYPT_PROPERTY_OWNER, CRYPT_UNUSED); if (cryptStatusError(status)) { - if (!bbs->hidepopups) - cryptlib_error_message(status, "clearing session ownership"); - conn_api.terminate = 1; - if (!bbs->hidepopups) - uifc.pop(NULL); + free(pubkey); + error_popup(bbs, "clearing session ownership", status); return -1; } if (!bbs->hidepopups) { @@ -501,11 +614,8 @@ ssh_connect(struct bbslist *bbs) } status = cl.GetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, &ssh_channel); if (cryptStatusError(status)) { - if (!bbs->hidepopups) - cryptlib_error_message(status, "getting ssh channel"); - conn_api.terminate = 1; - if (!bbs->hidepopups) - uifc.pop(NULL); + free(pubkey); + error_popup(bbs, "getting ssh channel", status); return -1; } @@ -557,6 +667,7 @@ ssh_connect(struct bbslist *bbs) case 2: break; default: + free(pubkey); if (!bbs->hidepopups) uifc.pop(NULL); return -1; @@ -580,67 +691,8 @@ ssh_connect(struct bbslist *bbs) _beginthread(ssh_output_thread, 0, NULL); _beginthread(ssh_input_thread, 0, NULL); -#if NOTYET - // TODO: Without this sleep, all is woe. - //SLEEP(10); - while (!conn_api.input_thread_running) - SLEEP(1); - if (cryptStatusOK(status)) { - if (!bbs->hidepopups) { - /* Clear ownership */ - uifc.pop(NULL); - uifc.pop("Creating SFTP Channel"); - } - pthread_mutex_lock(&ssh_mutex); - status = cl.SetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, CRYPT_UNUSED); - if (cryptStatusError(status)) - cryptlib_error_message(status, "setting new channel"); - if (cryptStatusOK(status)) { - 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)) { - status = cl.SetAttributeString(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL_ARG1, "sftp", 4); - if (cryptStatusError(status)) - cryptlib_error_message(status, "setting subsystem"); - if (cryptStatusOK(status)) { - status = cl.GetAttribute(ssh_session, CRYPT_SESSINFO_SSH_CHANNEL, &sftp_channel); - if (cryptStatusError(status)) - cryptlib_error_message(status, "getting new channel"); - if (cryptStatusOK(status)) { - // TODO: Do something... - } - } - } - } - } - if (sftp_channel != -1) { - pthread_mutex_lock(&ssh_mutex); - 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); - if (cryptStatusError(status)) { - cryptlib_error_message(status, "activating sftp session"); - } - if (cryptStatusOK(status)) { - sftp_state = sftpc_begin(sftp_send, NULL); - if (sftp_state != NULL) { - if (sftpc_init(sftp_state)) { - sftp_str_t ret = NULL; - sftp_filehandle_t f = NULL; - - if (sftpc_open(sftp_state, ".ssh/authorized_keys", SSH_FXF_READ, NULL, &f)) { - if (sftpc_read(sftp_state, f, 0, 1024, &ret)) { - fprintf(stderr, "First lines... %s\n", ret->c_str); - free_sftp_str(ret); - } - sftpc_close(sftp_state, &f); - } - } - } - } - } -#endif + add_public_key(bbs, pubkey); + free(pubkey); if (!bbs->hidepopups) uifc.pop(NULL); // TODO: Why is this called twice?