diff --git a/backport-Allow-writev-is-seccomp-sandbox.patch b/backport-Allow-writev-is-seccomp-sandbox.patch deleted file mode 100644 index fe35f7d10867a159fe7d05ddd443cc7e27823e32..0000000000000000000000000000000000000000 --- a/backport-Allow-writev-is-seccomp-sandbox.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 6283f4bd83eee714d0f5fc55802eff836b06fea8 Mon Sep 17 00:00:00 2001 -From: Darren Tucker -Date: Sat, 14 Jan 2023 22:02:44 +1100 -Subject: [PATCH] Allow writev is seccomp sandbox. - -This seems to be used by recent glibcs at least in some configurations. -From bz#3512, ok djm@ -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=6283f4bd83eee714d0f5fc55802eff836b06fea8 ---- - sandbox-seccomp-filter.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index cec43c46..4ab49eb6 100644 ---- a/sandbox-seccomp-filter.c -+++ b/sandbox-seccomp-filter.c -@@ -312,6 +312,9 @@ static const struct sock_filter preauth_insns[] = { - #ifdef __NR_write - SC_ALLOW(__NR_write), - #endif -+#ifdef __NR_writev -+ SC_ALLOW(__NR_writev), -+#endif - #ifdef __NR_socketcall - SC_ALLOW_ARG(__NR_socketcall, 0, SYS_SHUTDOWN), - SC_DENY(__NR_socketcall, EACCES), --- -2.27.0 - diff --git a/backport-Defer-seed_rng-until-after-closefrom-call.patch b/backport-Defer-seed_rng-until-after-closefrom-call.patch deleted file mode 100644 index fd61de33e98df34aafc5f5e4c60c012c865010b9..0000000000000000000000000000000000000000 --- a/backport-Defer-seed_rng-until-after-closefrom-call.patch +++ /dev/null @@ -1,39 +0,0 @@ -From cf1a9852d7fc93e4abc4168aed09529a57427cdc Mon Sep 17 00:00:00 2001 -From: Darren Tucker -Date: Wed, 9 Nov 2022 09:23:47 +1100 -Subject: [PATCH] Defer seed_rng until after closefrom call. - -seed_rng will initialize OpenSSL, and some engine providers (eg Intel's -QAT) will open descriptors for their own use. bz#3483, patch from -joel.d.schuetze at intel.com, ok djm@ -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=cf1a9852d7fc93e4abc4168aed09529a57427cdc ---- - sshd.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/sshd.c b/sshd.c -index b4bb7d65..808d91ef 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -1580,8 +1580,6 @@ main(int ac, char **av) - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ - sanitise_stdfd(); - -- seed_rng(); -- - /* Initialize configuration options to their default values. */ - initialize_server_options(&options); - -@@ -1703,6 +1701,8 @@ main(int ac, char **av) - else - closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); - -+ seed_rng(); -+ - /* If requested, redirect the logs to the specified logfile. */ - if (logfile != NULL) - log_redirect_stderr_to(logfile); --- -2.27.0 - diff --git a/backport-adapt-compat_kex_proposal-test-to-portable.patch b/backport-adapt-compat_kex_proposal-test-to-portable.patch deleted file mode 100644 index 287163963a3638f8b3c41df74f987cbcf1b865a1..0000000000000000000000000000000000000000 --- a/backport-adapt-compat_kex_proposal-test-to-portable.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 9fe207565b4ab0fe5d1ac5bb85e39188d96fb214 Mon Sep 17 00:00:00 2001 -From: Damien Miller -Date: Thu, 2 Feb 2023 23:17:49 +1100 -Subject: [PATCH] adapt compat_kex_proposal() test to portable - -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=9fe207565b4ab0fe5d1ac5bb85e39188d96fb214 ---- - Makefile.in | 1 + - regress/unittests/kex/test_proposal.c | 6 +++++- - 2 files changed, 6 insertions(+), 1 deletion(-) - -diff --git a/Makefile.in b/Makefile.in -index 18f6ac9e..c0ebfa04 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -616,6 +616,7 @@ regress/unittests/conversion/test_conversion$(EXEEXT): \ - UNITTESTS_TEST_KEX_OBJS=\ - regress/unittests/kex/tests.o \ - regress/unittests/kex/test_kex.o \ -+ regress/unittests/kex/test_proposal.o \ - $(SKOBJS) - - regress/unittests/kex/test_kex$(EXEEXT): ${UNITTESTS_TEST_KEX_OBJS} \ -diff --git a/regress/unittests/kex/test_proposal.c b/regress/unittests/kex/test_proposal.c -index b89ff59b..d6cf0f5d 100644 ---- a/regress/unittests/kex/test_proposal.c -+++ b/regress/unittests/kex/test_proposal.c -@@ -5,14 +5,18 @@ - * Placed in the public domain - */ - -+#include "includes.h" -+ - #include - #include - #include -+#ifdef HAVE_STDINT_H - #include -+#endif - #include - #include - --#include "test_helper.h" -+#include "../test_helper/test_helper.h" - - #include "compat.h" - #include "ssherr.h" --- -2.27.0 - diff --git a/backport-don-t-test-IPv6-addresses-if-platform-lacks-support.patch b/backport-don-t-test-IPv6-addresses-if-platform-lacks-support.patch deleted file mode 100644 index 4ae18855d13c3d232c1bd278d6d7185afe69608f..0000000000000000000000000000000000000000 --- a/backport-don-t-test-IPv6-addresses-if-platform-lacks-support.patch +++ /dev/null @@ -1,52 +0,0 @@ -From dd1249bd5c45128a908395c61b26996a70f82205 Mon Sep 17 00:00:00 2001 -From: Damien Miller -Date: Sun, 8 Jan 2023 12:08:59 +1100 -Subject: [PATCH] don't test IPv6 addresses if platform lacks support - -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=dd1249bd5c45128a908395c61b26996a70f82205 - ---- - regress/dynamic-forward.sh | 15 +++++++++++---- - 1 file changed, 11 insertions(+), 4 deletions(-) - -diff --git a/regress/dynamic-forward.sh b/regress/dynamic-forward.sh -index f6c2393..1bfe05a 100644 ---- a/regress/dynamic-forward.sh -+++ b/regress/dynamic-forward.sh -@@ -17,6 +17,11 @@ else - fi - trace "will use ProxyCommand $proxycmd" - -+# This is a reasonable proxy for IPv6 support. -+if ! config_defined HAVE_STRUCT_IN6_ADDR ; then -+ SKIP_IPV6=yes -+fi -+ - start_ssh() { - direction="$1" - arg="$2" -@@ -96,14 +101,16 @@ for d in D R; do - stop_ssh - - verbose "PermitRemoteOpen=explicit" -- start_ssh $d \ -- PermitRemoteOpen="127.0.0.1:$PORT [::1]:$PORT localhost:$PORT" -+ permit="127.0.0.1:$PORT [::1]:$PORT localhost:$PORT" -+ test -z "$SKIP_IPV6" || permit="127.0.0.1:$PORT localhost:$PORT" -+ start_ssh $d PermitRemoteOpen="$permit" - check_socks $d Y - stop_ssh - - verbose "PermitRemoteOpen=disallowed" -- start_ssh $d \ -- PermitRemoteOpen="127.0.0.1:1 [::1]:1 localhost:1" -+ permit="127.0.0.1:1 [::1]:1 localhost:1" -+ test -z "$SKIP_IPV6" || permit="127.0.0.1:1 localhost:1" -+ start_ssh $d PermitRemoteOpen="$permit" - check_socks $d N - stop_ssh - done --- -2.27.0 - diff --git a/backport-upstream-Add-scp-s-path-to-test-sshd-s-PATH.patch b/backport-upstream-Add-scp-s-path-to-test-sshd-s-PATH.patch deleted file mode 100644 index ff5a0c97cc727cb444af1a15298287f1b9c270c5..0000000000000000000000000000000000000000 --- a/backport-upstream-Add-scp-s-path-to-test-sshd-s-PATH.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 6e6f88647042b3cde54a628545c2f5fb656a9327 Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Fri, 13 Jan 2023 04:23:00 +0000 -Subject: [PATCH] upstream: Add scp's path to test sshd's PATH. - -If the scp we're testing is fully qualified (eg it's not in the system -PATH) then add its path to the under-test sshd's PATH so we can find -it. Prompted by bz#3518. - -OpenBSD-Regress-ID: 7df4f5a0be3aa135495b7e5a6719d3cbc26cc4c0 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=6e6f88647042b3cde54a628545c2f5fb656a9327 ---- - regress/test-exec.sh | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/regress/test-exec.sh b/regress/test-exec.sh -index c51f8eac..5a6afac5 100644 ---- a/regress/test-exec.sh -+++ b/regress/test-exec.sh -@@ -529,6 +529,13 @@ cat << EOF > $OBJ/sshd_config - Subsystem sftp $SFTPSERVER - EOF - -+# If we're testing a non-installed scp, add its directory to sshd's PATH -+# so we can test it. -+case "$SCP" in -+/*) PATH_WITH_SCP="`dirname $SCP`:$PATH" -+ echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_config ;; -+esac -+ - # This may be necessary if /usr/src and/or /usr/obj are group-writable, - # but if you aren't careful with permissions then the unit tests could - # be abused to locally escalate privileges. --- -2.27.0 - diff --git a/backport-upstream-CVE-2023-25136-fix-double-free-caused.patch b/backport-upstream-CVE-2023-25136-fix-double-free-caused.patch deleted file mode 100644 index c7319f3979ba18734a47cb51bc6a21f983d11ec6..0000000000000000000000000000000000000000 --- a/backport-upstream-CVE-2023-25136-fix-double-free-caused.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 12da7823336434a403f25c7cc0c2c6aed0737a35 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Thu, 2 Feb 2023 12:10:05 +0000 -Subject: [PATCH] upstream: fix double-free caused by compat_kex_proposal(); - bz3522 - -by dtucker@, ok me - -OpenBSD-Commit-ID: 2bfc37cd2d41f67dad64c17a64cf2cd3806a5c80 - -Reference:https://anongit.mindrot.org/openssh.git/patch/?id=12da7823336434a403f25c7cc0c2c6aed0737a35 -Conflict:NA ---- - compat.c | 16 ++++++++-------- - 1 file changed, 8 insertions(+), 8 deletions(-) - -diff --git a/compat.c b/compat.c -index 46dfe3a9..478a9403 100644 ---- a/compat.c -+++ b/compat.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: compat.c,v 1.120 2022/07/01 03:35:45 dtucker Exp $ */ -+/* $OpenBSD: compat.c,v 1.121 2023/02/02 12:10:05 djm Exp $ */ - /* - * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. - * -@@ -190,26 +190,26 @@ compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop) - char * - compat_kex_proposal(struct ssh *ssh, char *p) - { -- char *cp = NULL; -+ char *cp = NULL, *cp2 = NULL; - - if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) - return xstrdup(p); - debug2_f("original KEX proposal: %s", p); - if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) -- if ((p = match_filter_denylist(p, -+ if ((cp = match_filter_denylist(p, - "curve25519-sha256@libssh.org")) == NULL) - fatal("match_filter_denylist failed"); - if ((ssh->compat & SSH_OLD_DHGEX) != 0) { -- cp = p; -- if ((p = match_filter_denylist(p, -+ if ((cp2 = match_filter_denylist(cp ? cp : p, - "diffie-hellman-group-exchange-sha256," - "diffie-hellman-group-exchange-sha1")) == NULL) - fatal("match_filter_denylist failed"); - free(cp); -+ cp = cp2; - } -- debug2_f("compat KEX proposal: %s", p); -- if (*p == '\0') -+ if (cp == NULL || *cp == '\0') - fatal("No supported key exchange algorithms found"); -- return p; -+ debug2_f("compat KEX proposal: %s", cp); -+ return cp; - } - --- -2.23.0 - diff --git a/backport-upstream-Clear-signal-mask-early-in-main-sshd-may-ha.patch b/backport-upstream-Clear-signal-mask-early-in-main-sshd-may-ha.patch deleted file mode 100644 index 29c9afde7aee2cbc1c14bc8f21330d571983b199..0000000000000000000000000000000000000000 --- a/backport-upstream-Clear-signal-mask-early-in-main-sshd-may-ha.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 93f2ce8c050a7a2a628646c00b40b9b53fef93ef Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 16 Dec 2022 06:56:47 +0000 -Subject: [PATCH] upstream: Clear signal mask early in main(); sshd may have - been - -started with one or more signals masked (sigprocmask(2) is not cleared -on fork/exec) and this could interfere with various things, e.g. the -login grace timer. - -Execution environments that fail to clear the signal mask before running -sshd are clearly broken, but apparently they do exist. - -Reported by Sreedhar Balasubramanian; ok dtucker@ - -OpenBSD-Commit-ID: 77078c0b1c53c780269fc0c416f121d05e3010ae -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=93f2ce8c050a7a2a628646c00b40b9b53fef93ef ---- - sshd.c | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/sshd.c b/sshd.c -index cd42bd5..da39226 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: sshd.c,v 1.591 2022/09/17 10:34:29 djm Exp $ */ -+/* $OpenBSD: sshd.c,v 1.594 2022/12/16 06:56:47 djm Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -1650,12 +1650,16 @@ main(int ac, char **av) - int keytype; - Authctxt *authctxt; - struct connection_info *connection_info = NULL; -+ sigset_t sigmask; - - #ifdef HAVE_SECUREWARE - (void)set_auth_parameters(ac, av); - #endif - __progname = ssh_get_progname(av[0]); - -+ sigemptyset(&sigmask); -+ sigprocmask(SIG_SETMASK, &sigmask, NULL); -+ - /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ - saved_argc = ac; - rexec_argc = ac; --- -2.23.0 - diff --git a/backport-upstream-Copy-bytes-from-the_banana-rather-than-bana.patch b/backport-upstream-Copy-bytes-from-the_banana-rather-than-bana.patch deleted file mode 100644 index f1c5b506b07c5a4eece9b5de7478b15ab23ae9af..0000000000000000000000000000000000000000 --- a/backport-upstream-Copy-bytes-from-the_banana-rather-than-bana.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 018d671d78145f03d6f07ae9d64d51321da70325 Mon Sep 17 00:00:00 2001 -From: "tb@openbsd.org" -Date: Wed, 4 Jan 2023 22:48:57 +0000 -Subject: [PATCH] upstream: Copy bytes from the_banana[] rather than banana() - -Fixes test failure due to segfault seen on arm64 with xonly snap. - -ok djm - -OpenBSD-Regress-ID: 86e2aa4bbd1dff1bc4ebb2969c0d6474485be046 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=018d671d78145f03d6f07ae9d64d51321da70325 ---- - regress/unittests/sshkey/test_sshkey.c | 2 +- - 1 file changed, 1 insertions(+), 1 deletions(-) - -diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c -index 982907ce..cc359aea 100644 ---- a/regress/unittests/sshkey/test_sshkey.c -+++ b/regress/unittests/sshkey/test_sshkey.c -@@ -144,7 +144,7 @@ banana(u_char *s, size_t l) - memcpy(s + o, "nanananana", l - o); - break; - } -- memcpy(s + o, banana, sizeof(the_banana)); -+ memcpy(s + o, the_banana, sizeof(the_banana)); - } - } - --- -2.27.0 - diff --git a/backport-upstream-Ensure-that-there-is-a-terminating-newline-.patch b/backport-upstream-Ensure-that-there-is-a-terminating-newline-.patch deleted file mode 100644 index 0753fe9ec6ec42a097bbbe88c1da75e828cd6470..0000000000000000000000000000000000000000 --- a/backport-upstream-Ensure-that-there-is-a-terminating-newline-.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 3c379c9a849a635cc7f05cbe49fe473ccf469ef9 Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Thu, 9 Feb 2023 09:54:11 +0000 -Subject: [PATCH] upstream: Ensure that there is a terminating newline when - adding a new - -entry to known_hosts. bz#3529, with git+openssh at limpsquid.nl, ok deraadt@ -markus@ - -OpenBSD-Commit-ID: fa8d90698da1886570512b96f051e266eac105e0 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=3c379c9a849a635cc7f05cbe49fe473ccf469ef9 ---- - hostfile.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/hostfile.c b/hostfile.c -index bd49e3ac..f5fa8084 100644 ---- a/hostfile.c -+++ b/hostfile.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: hostfile.c,v 1.93 2022/01/06 22:02:52 djm Exp $ */ -+/* $OpenBSD: hostfile.c,v 1.94 2023/02/09 09:54:11 dtucker Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -520,9 +520,17 @@ add_host_to_hostfile(const char *filename, const char *host, - if (key == NULL) - return 1; /* XXX ? */ - hostfile_create_user_ssh_dir(filename, 0); -- f = fopen(filename, "a"); -+ f = fopen(filename, "a+"); - if (!f) - return 0; -+ /* Make sure we have a terminating newline. */ -+ if (fseek(f, -1L, SEEK_END) == 0 && fgetc(f) != '\n') -+ if (fputc('\n', f) != '\n') { -+ error("Failed to add terminating newline to %s: %s", -+ filename, strerror(errno)); -+ fclose(f); -+ return 0; -+ } - success = write_host_entry(f, host, NULL, key, store_hash); - fclose(f); - return success; --- -2.27.0 - diff --git a/backport-upstream-Handle-dynamic-remote-port-forwarding-in-es.patch b/backport-upstream-Handle-dynamic-remote-port-forwarding-in-es.patch deleted file mode 100644 index 331c558e6328fa92204f67eba339a7326d74ea8f..0000000000000000000000000000000000000000 --- a/backport-upstream-Handle-dynamic-remote-port-forwarding-in-es.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 650de7ecd3567b5a5dbf16dd1eb598bd8c20bca8 Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Thu, 10 Nov 2022 23:03:10 +0000 -Subject: [PATCH] upstream: Handle dynamic remote port forwarding in escape - commandline's - --R processing. bz#3499, ok djm@ - -OpenBSD-Commit-ID: 194ee4cfe7ed0e2b8ad0727f493c798a50454208 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=650de7ecd3567b5a5dbf16dd1eb598bd8c20bca8 ---- - clientloop.c | 13 ++++++++++--- - 1 file changed, 10 insertions(+), 3 deletions(-) - -diff --git a/clientloop.c b/clientloop.c -index 289d0b68..02349ccb 100644 ---- a/clientloop.c -+++ b/clientloop.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: clientloop.c,v 1.380 2022/06/03 04:30:46 djm Exp $ */ -+/* $OpenBSD: clientloop.c,v 1.382 2022/11/10 23:03:10 dtucker Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -846,8 +846,15 @@ process_cmdline(struct ssh *ssh) - } - logit("Canceled forwarding."); - } else { -- if (!parse_forward(&fwd, s, dynamic, remote)) { -- logit("Bad forwarding specification."); -+ /* -R specs can be both dynamic or not, so check both. */ -+ if (remote) { -+ if (!parse_forward(&fwd, s, 0, remote) && -+ !parse_forward(&fwd, s, 1, remote)) { -+ logit("Bad remote forwarding specification."); -+ goto out; -+ } -+ } else if (!parse_forward(&fwd, s, dynamic, remote)) { -+ logit("Bad local forwarding specification."); - goto out; - } - if (local || dynamic) { --- -2.27.0 - diff --git a/backport-upstream-Instead-of-skipping-the-all-tokens-test-if-.patch b/backport-upstream-Instead-of-skipping-the-all-tokens-test-if-.patch deleted file mode 100644 index 6e8d770452428f28f905c490ad7653f9f7b70110..0000000000000000000000000000000000000000 --- a/backport-upstream-Instead-of-skipping-the-all-tokens-test-if-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 4d87a00f704e0365e11c3c38b170c1275ec461fc Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Sat, 14 Jan 2023 09:57:08 +0000 -Subject: [PATCH] upstream: Instead of skipping the all-tokens test if we don't - have - -OpenSSL (since we use it to compute the hash), put the hash at the end and -just omit it if we don't have it. Prompted by bz#3521. - -OpenBSD-Regress-ID: c79ecba64250ed3b6417294b6c965e6b12ca5eea -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=4d87a00f704e0365e11c3c38b170c1275ec461fc ---- -diff --git a/regress/percent.sh b/regress/percent.sh -index ed5c604d..3dfa8d2d 100644 ---- a/regress/percent.sh -+++ b/regress/percent.sh -@@ -12,6 +12,7 @@ USER=`id -u -n` - USERID=`id -u` - HOST=`hostname | cut -f1 -d.` - HOSTNAME=`hostname` -+HASH="" - - # Localcommand is evaluated after connection because %T is not available - # until then. Because of this we use a different method of exercising it, -@@ -98,10 +99,13 @@ for i in matchexec localcommand remotecommand controlpath identityagent \ - # containing %d for UserKnownHostsFile - if [ "$i" != "userknownhostsfile" ]; then - trial $i '%d' $HOME -+ in='%%/%i/%h/%d/%L/%l/%n/%p/%r/%u' -+ out="%/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER" - if [ ! -z "${HASH}" ]; then -- trial $i '%%/%C/%i/%h/%d/%L/%l/%n/%p/%r/%u' \ -- "%/$HASH/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER" -+ in="$in/%C" -+ out="$out/$HASH" - fi -+ trial $i "$in" "$out" - fi - done - --- -2.27.0 - diff --git a/backport-upstream-Move-scp-path-setting-to-a-helper-function.patch b/backport-upstream-Move-scp-path-setting-to-a-helper-function.patch deleted file mode 100644 index ce0d08ef90169f643c046bd688391164ff6e6764..0000000000000000000000000000000000000000 --- a/backport-upstream-Move-scp-path-setting-to-a-helper-function.patch +++ /dev/null @@ -1,150 +0,0 @@ -From 625f6bc39840167dafb3bf5b6a3e18503ac986e8 Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Fri, 13 Jan 2023 04:47:34 +0000 -Subject: [PATCH] upstream: Move scp path setting to a helper function. -The - previous - -commit to add scp to the test sshd's path causes the t-envpass test to -fail -when the test scp is given using a fully qualified path. Put this in a -helper function and only call it from the scp tests. - -OpenBSD-Regress-ID: 7533dc1c4265c1de716abb062957994195b36df4 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=625f6bc39840167dafb3bf5b6a3e18503ac986e8 ---- - regress/multiplex.sh | 3 ++- - regress/scp-uri.sh | 4 +++- - regress/scp.sh | 4 +++- - regress/scp3.sh | 6 ++++-- - regress/test-exec.sh | 21 +++++++++++++-------- - 5 files changed, 25 insertions(+), 13 deletions(-) - -diff --git a/regress/multiplex.sh b/regress/multiplex.sh -index 6317099..046194c 100644 ---- a/regress/multiplex.sh -+++ b/regress/multiplex.sh -@@ -1,4 +1,4 @@ --# $OpenBSD: multiplex.sh,v 1.34 2022/06/03 04:31:54 djm Exp $ -+# $OpenBSD: multiplex.sh,v 1.35 2023/01/13 04:47:34 dtucker Exp $ - # Placed in the Public Domain. - - make_tmpdir -@@ -24,6 +24,7 @@ wait_for_mux_master_ready() - fatal "mux master never becomes ready" - } - -+maybe_add_scp_path_to_sshd - start_sshd - - start_mux_master() -diff --git a/regress/scp-uri.sh b/regress/scp-uri.sh -index 20ac3c8..eacbd45 100644 ---- a/regress/scp-uri.sh -+++ b/regress/scp-uri.sh -@@ -1,4 +1,4 @@ --# $OpenBSD: scp-uri.sh,v 1.4 2021/08/10 03:35:45 djm Exp $ -+# $OpenBSD: scp-uri.sh,v 1.5 2023/01/13 04:47:34 dtucker Exp $ - # Placed in the Public Domain. - - tid="scp-uri" -@@ -9,6 +9,8 @@ COPY2=${OBJ}/copy2 - DIR=${COPY}.dd - DIR2=${COPY}.dd2 - -+maybe_add_scp_path_to_sshd -+ - SRC=`dirname ${SCRIPT}` - cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp - chmod 755 ${OBJ}/scp-ssh-wrapper.scp -diff --git a/regress/scp.sh b/regress/scp.sh -index f47c594..ef4399e 100644 ---- a/regress/scp.sh -+++ b/regress/scp.sh -@@ -1,4 +1,4 @@ --# $OpenBSD: scp.sh,v 1.14 2022/05/15 23:48:07 djm Exp $ -+# $OpenBSD: scp.sh,v 1.18 2023/01/13 04:47:34 dtucker Exp $ - # Placed in the Public Domain. - - tid="scp" -@@ -16,6 +16,8 @@ COPY2=${OBJ}/copy2 - DIR=${COPY}.dd - DIR2=${COPY}.dd2 - -+maybe_add_scp_path_to_sshd -+ - SRC=`dirname ${SCRIPT}` - cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp - chmod 755 ${OBJ}/scp-ssh-wrapper.scp -diff --git a/regress/scp3.sh b/regress/scp3.sh -index 47db47c..dfb2d2f 100644 ---- a/regress/scp3.sh -+++ b/regress/scp3.sh -@@ -1,9 +1,9 @@ --# $OpenBSD: scp3.sh,v 1.3 2021/08/10 03:35:45 djm Exp $ -+# $OpenBSD: scp3.sh,v 1.4 2023/01/13 04:47:34 dtucker Exp $ - # Placed in the Public Domain. - - tid="scp3" - --#set -x -+set -x - - COPY2=${OBJ}/copy2 - DIR=${COPY}.dd -@@ -15,6 +15,8 @@ if [ $? -eq 1 ]; then - skip "No scp on remote path." - fi - -+maybe_add_scp_path_to_sshd -+ - SRC=`dirname ${SCRIPT}` - cp ${SRC}/scp-ssh-wrapper.sh ${OBJ}/scp-ssh-wrapper.scp - chmod 755 ${OBJ}/scp-ssh-wrapper.scp -diff --git a/regress/test-exec.sh b/regress/test-exec.sh -index 7e311e8..df43f02 100644 ---- a/regress/test-exec.sh -+++ b/regress/test-exec.sh -@@ -1,4 +1,4 @@ --# $OpenBSD: test-exec.sh,v 1.92 2022/07/25 07:12:45 dtucker Exp $ -+# $OpenBSD: test-exec.sh,v 1.94 2023/01/13 04:47:34 dtucker Exp $ - # Placed in the Public Domain. - - #SUDO=sudo -@@ -509,6 +509,18 @@ skip () - exit $RESULT - } - -+maybe_add_scp_path_to_sshd () -+{ -+ # If we're testing a non-installed scp, add its directory to sshd's -+ # PATH so we can test it. We don't do this for all tests as it -+ # breaks the SetEnv tests. -+ case "$SCP" in -+ /*) PATH_WITH_SCP="`dirname $SCP`:$PATH" -+ echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_config -+ echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_proxy ;; -+ esac -+} -+ - RESULT=0 - PIDFILE=$OBJ/pidfile - -@@ -529,13 +541,6 @@ cat << EOF > $OBJ/sshd_config - Subsystem sftp $SFTPSERVER - EOF - --# If we're testing a non-installed scp, add its directory to sshd's PATH --# so we can test it. --case "$SCP" in --/*) PATH_WITH_SCP="`dirname $SCP`:$PATH" -- echo " SetEnv PATH='$PATH_WITH_SCP'" >>$OBJ/sshd_config ;; --esac -- - # This may be necessary if /usr/src and/or /usr/obj are group-writable, - # but if you aren't careful with permissions then the unit tests could - # be abused to locally escalate privileges. --- -2.23.0 - diff --git a/backport-upstream-Shell-syntax-fix.-From-ren-mingshuai-vi-git.patch b/backport-upstream-Shell-syntax-fix.-From-ren-mingshuai-vi-git.patch deleted file mode 100644 index 9262ca53a4b7203a48f63cc9b59f28204124078b..0000000000000000000000000000000000000000 --- a/backport-upstream-Shell-syntax-fix.-From-ren-mingshuai-vi-git.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 923c3f437f439cfca238fba37e97a7041782f615 Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Sat, 14 Jan 2023 10:05:54 +0000 -Subject: [PATCH] upstream: Shell syntax fix. From ren mingshuai vi github - PR#369. - -OpenBSD-Regress-ID: 6696b2eeefe128099fc3d7ea9f23252cc35156f9 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=923c3f437f439cfca238fba37e97a7041782f615 ---- -diff --git a/regress/yes-head.sh b/regress/yes-head.sh -index 2759eb8c..1bde504f 100644 ---- a/regress/yes-head.sh -+++ b/regress/yes-head.sh -@@ -6,7 +6,7 @@ tid="yes pipe head" - lines=`${SSH} -F $OBJ/ssh_proxy thishost 'sh -c "while true;do echo yes;done | _POSIX2_VERSION=199209 head -2000"' | (sleep 3 ; wc -l)` - if [ $? -ne 0 ]; then - fail "yes|head test failed" -- lines = 0; -++ lines=0 - fi - if [ $lines -ne 2000 ]; then - fail "yes|head returns $lines lines instead of 2000" --- -2.27.0 - diff --git a/backport-upstream-The-idiomatic-way-of-coping-with-signed-cha.patch b/backport-upstream-The-idiomatic-way-of-coping-with-signed-cha.patch deleted file mode 100644 index ea9d05b7ab88a2e2aab158991db51ed725d56206..0000000000000000000000000000000000000000 --- a/backport-upstream-The-idiomatic-way-of-coping-with-signed-cha.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 5a7a7acab2f466dc1d7467b5d05d35268c3137aa Mon Sep 17 00:00:00 2001 -From: "deraadt@openbsd.org" -Date: Thu, 15 Dec 2022 18:20:39 +0000 -Subject: [PATCH] upstream: The idiomatic way of coping with signed char vs - unsigned - -char (which did not come from stdio read functions) in the presence of -ctype macros, is to always cast to (unsigned char). casting to (int) -for a "macro" which is documented to take int, is weird. And sadly wrong, -because of the sing extension risk.. same diff from florian - -OpenBSD-Commit-ID: 65b9a49a68e22ff3a0ebd593f363e9f22dd73fea -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=5a7a7acab2f466dc1d7467b5d05d35268c3137aa ---- - misc.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/misc.c b/misc.c -index 977c097e..41244da9 100644 ---- a/misc.c -+++ b/misc.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: misc.c,v 1.177 2022/08/11 01:56:51 djm Exp $ */ -+/* $OpenBSD: misc.c,v 1.179 2022/12/15 18:20:39 deraadt Exp $ */ - /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * Copyright (c) 2005-2020 Damien Miller. All rights reserved. -@@ -95,7 +95,7 @@ rtrim(char *s) - if ((i = strlen(s)) == 0) - return; - for (i--; i > 0; i--) { -- if (isspace((int)s[i])) -+ if (isspace((unsigned char)s[i])) - s[i] = '\0'; - } - } --- -2.27.0 - diff --git a/backport-upstream-When-OpenSSL-is-not-available-skip-parts-of.patch b/backport-upstream-When-OpenSSL-is-not-available-skip-parts-of.patch deleted file mode 100644 index 5d59c1df96b405654b50fd7ce3a6ac233664e519..0000000000000000000000000000000000000000 --- a/backport-upstream-When-OpenSSL-is-not-available-skip-parts-of.patch +++ /dev/null @@ -1,51 +0,0 @@ -From d77fc611a62f2dfee0b654c31a50a814b13310dd Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Fri, 6 Jan 2023 12:33:33 +0000 -Subject: [PATCH] upstream: When OpenSSL is not available, skip parts of - percent test - -that require it. Based on github pr#368 from ren mingshuai. - -OpenBSD-Regress-ID: 49a375b2cf61ccb95b52e75e2e025cd10988ebb2 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=d77fc611a62f2dfee0b654c31a50a814b13310dd ---- - regress/percent.sh | 14 +++++++++----- - 1 file changed, 9 insertions(+), 5 deletions(-) - -diff --git a/regress/percent.sh b/regress/percent.sh -index bb81779a..ed5c604d 100644 ---- a/regress/percent.sh -+++ b/regress/percent.sh -@@ -79,10 +79,12 @@ for i in matchexec localcommand remotecommand controlpath identityagent \ - trial $i '%T' NONE - fi - # Matches implementation in readconf.c:ssh_connection_hash() -- HASH=`printf "${HOSTNAME}127.0.0.1${PORT}$REMUSER" | -- $OPENSSL_BIN sha1 | cut -f2 -d' '` -+ if [ ! -z "${OPENSSL_BIN}" ]; then -+ HASH=`printf "${HOSTNAME}127.0.0.1${PORT}$REMUSER" | -+ $OPENSSL_BIN sha1 | cut -f2 -d' '` -+ trial $i '%C' $HASH -+ fi - trial $i '%%' '%' -- trial $i '%C' $HASH - trial $i '%i' $USERID - trial $i '%h' 127.0.0.1 - trial $i '%L' $HOST -@@ -96,8 +98,10 @@ for i in matchexec localcommand remotecommand controlpath identityagent \ - # containing %d for UserKnownHostsFile - if [ "$i" != "userknownhostsfile" ]; then - trial $i '%d' $HOME -- trial $i '%%/%C/%i/%h/%d/%L/%l/%n/%p/%r/%u' \ -- "%/$HASH/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER" -+ if [ ! -z "${HASH}" ]; then -+ trial $i '%%/%C/%i/%h/%d/%L/%l/%n/%p/%r/%u' \ -+ "%/$HASH/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER" -+ fi - fi - done - --- -2.27.0 - diff --git a/backport-upstream-avoid-printf-s-NULL-if-using-ssh.patch b/backport-upstream-avoid-printf-s-NULL-if-using-ssh.patch deleted file mode 100644 index 4a21d673aa66107b13f7d1251d2c23660028d9ec..0000000000000000000000000000000000000000 --- a/backport-upstream-avoid-printf-s-NULL-if-using-ssh.patch +++ /dev/null @@ -1,42 +0,0 @@ -From f673b49f3be3eb51074fbb8a405beb6cd0f7d93e Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 13 Jan 2023 02:44:02 +0000 -Subject: [PATCH] upstream: avoid printf("%s", NULL) if using ssh - --oUserKnownHostsFile=none and a hostkey in one of the system known hosts file -changes; ok dtucker@ - -OpenBSD-Commit-ID: 7ca87614bfc6da491315536a7f2301434a9fe614 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=f673b49f3be3eb51074fbb8a405beb6cd0f7d93e ---- - sshconnect.c | 9 ++++++--- - 1 file changed, 6 insertions(+), 3 deletions(-) - -diff --git a/sshconnect.c b/sshconnect.c -index 0fca52b2..792bc34b 100644 ---- a/sshconnect.c -+++ b/sshconnect.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: sshconnect.c,v 1.358 2022/08/26 08:16:27 djm Exp $ */ -+/* $OpenBSD: sshconnect.c,v 1.361 2023/01/13 02:44:02 djm Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -1276,8 +1276,11 @@ check_host_key(char *hostname, const struct ssh_conn_info *cinfo, - } - /* The host key has changed. */ - warn_changed_key(host_key); -- error("Add correct host key in %.100s to get rid of this message.", -- user_hostfiles[0]); -+ if (num_user_hostfiles > 0 || num_system_hostfiles > 0) { -+ error("Add correct host key in %.100s to get rid " -+ "of this message.", num_user_hostfiles > 0 ? -+ user_hostfiles[0] : system_hostfiles[0]); -+ } - error("Offending %s key in %s:%lu", - sshkey_type(host_found->key), - host_found->file, host_found->line); --- -2.27.0 - diff --git a/backport-upstream-fix-bug-in-PermitRemoteOpen-which-caused-it.patch b/backport-upstream-fix-bug-in-PermitRemoteOpen-which-caused-it.patch deleted file mode 100644 index 67f8ecfb7ce80787df84a122d1ed5a3bb1ea5aa0..0000000000000000000000000000000000000000 --- a/backport-upstream-fix-bug-in-PermitRemoteOpen-which-caused-it.patch +++ /dev/null @@ -1,113 +0,0 @@ -From b3daa8dc582348d6ab8150bc1e571b7aa08c5388 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Mon, 2 Jan 2023 07:03:30 +0000 -Subject: [PATCH] upstream: fix bug in PermitRemoteOpen which caused it -to - ignore its - -first argument unless it was one of the special keywords "any" or -"none". - -Reported by Georges Chaudy in bz3515; ok dtucker@ - -OpenBSD-Commit-ID: c5678a39f1ff79993d5ae3cfac5746a4ae148ea5 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=b3daa8dc582348d6ab8150bc1e571b7aa08c5388 ---- - readconf.c | 67 +++++++++++++++++++++++++++++------------------------- - 1 file changed, 36 insertions(+), 31 deletions(-) - -diff --git a/readconf.c b/readconf.c -index 284da26..ccac632 100644 ---- a/readconf.c -+++ b/readconf.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: readconf.c,v 1.369 2022/09/17 10:33:18 djm Exp $ */ -+/* $OpenBSD: readconf.c,v 1.371 2023/01/02 07:03:30 djm Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -1613,45 +1613,50 @@ parse_pubkey_algos: - case oPermitRemoteOpen: - uintptr = &options->num_permitted_remote_opens; - cppptr = &options->permitted_remote_opens; -- arg = argv_next(&ac, &av); -- if (!arg || *arg == '\0') -- fatal("%s line %d: missing %s specification", -- filename, linenum, lookup_opcode_name(opcode)); - uvalue = *uintptr; /* modified later */ -- if (strcmp(arg, "any") == 0 || strcmp(arg, "none") == 0) { -- if (*activep && uvalue == 0) { -- *uintptr = 1; -- *cppptr = xcalloc(1, sizeof(**cppptr)); -- (*cppptr)[0] = xstrdup(arg); -- } -- break; -- } -+ i = 0; - while ((arg = argv_next(&ac, &av)) != NULL) { - arg2 = xstrdup(arg); -- p = hpdelim(&arg); -- if (p == NULL) { -- fatal("%s line %d: missing host in %s", -- filename, linenum, -- lookup_opcode_name(opcode)); -- } -- p = cleanhostname(p); -- /* -- * don't want to use permitopen_port to avoid -- * dependency on channels.[ch] here. -- */ -- if (arg == NULL || -- (strcmp(arg, "*") != 0 && a2port(arg) <= 0)) { -- fatal("%s line %d: bad port number in %s", -- filename, linenum, -- lookup_opcode_name(opcode)); -- } -- if (*activep && uvalue == 0) { -+ /* Allow any/none only in first position */ -+ if (strcasecmp(arg, "none") == 0 || -+ strcasecmp(arg, "any") == 0) { -+ if (i > 0 || ac > 0) { -+ error("%s line %d: keyword %s \"%s\" " -+ "argument must appear alone.", -+ filename, linenum, keyword, arg); -+ goto out; -+ } -+ } else { -+ p = hpdelim(&arg); -+ if (p == NULL) { -+ fatal("%s line %d: missing host in %s", -+ filename, linenum, -+ lookup_opcode_name(opcode)); -+ } -+ p = cleanhostname(p); -+ /* -+ * don't want to use permitopen_port to avoid -+ * dependency on channels.[ch] here. -+ */ -+ if (arg == NULL || (strcmp(arg, "*") != 0 && -+ a2port(arg) <= 0)) { -+ fatal("%s line %d: bad port number " -+ "in %s", filename, linenum, -+ lookup_opcode_name(opcode)); -+ } -+ } -+ -+ if (*activep && uvalue == 0) { - opt_array_append(filename, linenum, - lookup_opcode_name(opcode), - cppptr, uintptr, arg2); - } - free(arg2); -+ i++; - } -+ if (i == 0) -+ fatal("%s line %d: missing %s specification", -+ filename, linenum, lookup_opcode_name(opcode)); - break; - - case oClearAllForwardings: --- -2.23.0 - diff --git a/backport-upstream-honour-user-s-umask-if-it-is-more-restricti.patch b/backport-upstream-honour-user-s-umask-if-it-is-more-restricti.patch deleted file mode 100644 index 63767c4f43ce5d626d919a02d6afe4176307ba24..0000000000000000000000000000000000000000 --- a/backport-upstream-honour-user-s-umask-if-it-is-more-restricti.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 5ee2b8ccfcf4b606f450eb0ff2305e311f68b0be Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Thu, 6 Oct 2022 22:42:37 +0000 -Subject: [PATCH] upstream: honour user's umask if it is more restrictive then - the ssh - -default (022); based on patch from Alex Henrie, ok dtucker@ deraadt@ - -OpenBSD-Commit-ID: fe1b9e15fc9a4f49fc338e848ce14d8727abe82d -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=5ee2b8ccfcf4b606f450eb0ff2305e311f68b0be ---- - ssh.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ssh.c b/ssh.c -index 25be53d5..e711dbd2 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: ssh.c,v 1.576 2022/09/17 10:33:18 djm Exp $ */ -+/* $OpenBSD: ssh.c,v 1.577 2022/10/06 22:42:37 djm Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -679,7 +679,7 @@ main(int ac, char **av) - * writable only by the owner, which is ok for all files for which we - * don't set the modes explicitly. - */ -- umask(022); -+ umask(022 | umask(077)); - - msetlocale(); - --- -2.27.0 - diff --git a/backport-upstream-regression-test-for-PermitRemoteOpen.patch b/backport-upstream-regression-test-for-PermitRemoteOpen.patch deleted file mode 100644 index cfe61055047ad285c56df7c8da1331f049fbe2f6..0000000000000000000000000000000000000000 --- a/backport-upstream-regression-test-for-PermitRemoteOpen.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 845ceecea2ac311b0c267f9ecbd34862e1876fc6 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Mon, 2 Jan 2023 07:03:57 +0000 -Subject: [PATCH] upstream: regression test for PermitRemoteOpen - -OpenBSD-Regress-ID: 8271aafbf5c21950cd5bf966f08e585cebfe630c -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=845ceecea2ac311b0c267f9ecbd34862e1876fc6 ---- - regress/dynamic-forward.sh | 84 ++++++++++++++++++++++++++++++-------- - 1 file changed, 66 insertions(+), 18 deletions(-) - -diff --git a/regress/dynamic-forward.sh b/regress/dynamic-forward.sh -index 84f8ee19..f6c2393d 100644 ---- a/regress/dynamic-forward.sh -+++ b/regress/dynamic-forward.sh -@@ -1,10 +1,12 @@ --# $OpenBSD: dynamic-forward.sh,v 1.13 2017/09/21 19:18:12 markus Exp $ -+# $OpenBSD: dynamic-forward.sh,v 1.14 2023/01/02 07:03:57 djm Exp $ - # Placed in the Public Domain. - - tid="dynamic forwarding" - - FWDPORT=`expr $PORT + 1` - -+cp $OBJ/ssh_config $OBJ/ssh_config.orig -+ - if have_prog nc && nc -h 2>&1 | grep "proxy address" >/dev/null; then - proxycmd="nc -x 127.0.0.1:$FWDPORT -X" - elif have_prog connect; then -@@ -15,16 +17,16 @@ else - fi - trace "will use ProxyCommand $proxycmd" - --start_sshd -- --for d in D R; do -+start_ssh() { -+ direction="$1" -+ arg="$2" - n=0 - error="1" -- trace "start dynamic forwarding, fork to background" -- -+ trace "start dynamic -$direction forwarding, fork to background" -+ (cat $OBJ/ssh_config.orig ; echo "$arg") > $OBJ/ssh_config - while [ "$error" -ne 0 -a "$n" -lt 3 ]; do - n=`expr $n + 1` -- ${SSH} -F $OBJ/ssh_config -f -$d $FWDPORT -q \ -+ ${SSH} -F $OBJ/ssh_config -f -$direction $FWDPORT -q \ - -oExitOnForwardFailure=yes somehost exec sh -c \ - \'"echo \$\$ > $OBJ/remote_pid; exec sleep 444"\' - error=$? -@@ -36,18 +38,9 @@ for d in D R; do - if [ "$error" -ne 0 ]; then - fatal "failed to start dynamic forwarding" - fi -+} - -- for s in 4 5; do -- for h in 127.0.0.1 localhost; do -- trace "testing ssh socks version $s host $h (-$d)" -- ${SSH} -F $OBJ/ssh_config \ -- -o "ProxyCommand ${proxycmd}${s} $h $PORT" \ -- somehost cat ${DATA} > ${COPY} -- test -f ${COPY} || fail "failed copy ${DATA}" -- cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" -- done -- done -- -+stop_ssh() { - if [ -f $OBJ/remote_pid ]; then - remote=`cat $OBJ/remote_pid` - trace "terminate remote shell, pid $remote" -@@ -57,5 +50,60 @@ for d in D R; do - else - fail "no pid file: $OBJ/remote_pid" - fi -+} -+ -+check_socks() { -+ direction=$1 -+ expect_success=$2 -+ for s in 4 5; do -+ for h in 127.0.0.1 localhost; do -+ trace "testing ssh socks version $s host $h (-$direction)" -+ ${SSH} -F $OBJ/ssh_config \ -+ -o "ProxyCommand ${proxycmd}${s} $h $PORT 2>/dev/null" \ -+ somehost cat ${DATA} > ${COPY} -+ r=$? -+ if [ "x$expect_success" = "xY" ] ; then -+ if [ $r -ne 0 ] ; then -+ fail "ssh failed with exit status $r" -+ fi -+ test -f ${COPY} || fail "failed copy ${DATA}" -+ cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" -+ elif [ $r -eq 0 ] ; then -+ fail "ssh unexpectedly succeeded" -+ fi -+ done -+ done -+} -+ -+start_sshd -+ -+for d in D R; do -+ verbose "test -$d forwarding" -+ start_ssh $d -+ check_socks $d Y -+ stop_ssh -+ test "x$d" = "xR" || continue -+ -+ # Test PermitRemoteOpen -+ verbose "PermitRemoteOpen=any" -+ start_ssh $d PermitRemoteOpen=any -+ check_socks $d Y -+ stop_ssh -+ -+ verbose "PermitRemoteOpen=none" -+ start_ssh $d PermitRemoteOpen=none -+ check_socks $d N -+ stop_ssh -+ -+ verbose "PermitRemoteOpen=explicit" -+ start_ssh $d \ -+ PermitRemoteOpen="127.0.0.1:$PORT [::1]:$PORT localhost:$PORT" -+ check_socks $d Y -+ stop_ssh - -+ verbose "PermitRemoteOpen=disallowed" -+ start_ssh $d \ -+ PermitRemoteOpen="127.0.0.1:1 [::1]:1 localhost:1" -+ check_socks $d N -+ stop_ssh - done --- -2.27.0 - diff --git a/backport-upstream-test-compat_kex_proposal-by-dtucker.patch b/backport-upstream-test-compat_kex_proposal-by-dtucker.patch deleted file mode 100644 index a20af602edeab247f6cb62699b1ad823b9b56c5a..0000000000000000000000000000000000000000 --- a/backport-upstream-test-compat_kex_proposal-by-dtucker.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 903c556b938fff2d7bff8da2cc460254430963c5 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Thu, 2 Feb 2023 12:12:52 +0000 -Subject: [PATCH] upstream: test compat_kex_proposal(); by dtucker@ - -OpenBSD-Regress-ID: 0e404ee264db546f9fdbf53390689ab5f8d38bf2 - -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=903c556b938fff2d7bff8da2cc460254430963c5 ---- - regress/unittests/kex/test_proposal.c | 79 +++++++++++++++++++++++++++ - regress/unittests/kex/tests.c | 4 +- - 2 files changed, 82 insertions(+), 1 deletion(-) - create mode 100644 regress/unittests/kex/test_proposal.c - -diff --git a/regress/unittests/kex/test_proposal.c b/regress/unittests/kex/test_proposal.c -new file mode 100644 -index 0000000..b89ff59 ---- /dev/null -+++ b/regress/unittests/kex/test_proposal.c -@@ -0,0 +1,79 @@ -+/* $OpenBSD: test_proposal.c,v 1.1 2023/02/02 12:12:52 djm Exp $ */ -+/* -+ * Regress test KEX -+ * -+ * Placed in the public domain -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "test_helper.h" -+ -+#include "compat.h" -+#include "ssherr.h" -+#include "sshbuf.h" -+#include "kex.h" -+#include "packet.h" -+#include "xmalloc.h" -+ -+void kex_proposal(void); -+ -+#define CURVE25519 "curve25519-sha256@libssh.org" -+#define DHGEX1 "diffie-hellman-group-exchange-sha1" -+#define DHGEX256 "diffie-hellman-group-exchange-sha256" -+#define KEXALGOS CURVE25519","DHGEX256","DHGEX1 -+void -+kex_proposal(void) -+{ -+ size_t i; -+ struct ssh ssh; -+ char *result, *out, *in; -+ struct { -+ char *in; /* TODO: make this const */ -+ char *out; -+ int compat; -+ } tests[] = { -+ { KEXALGOS, KEXALGOS, 0}, -+ { KEXALGOS, DHGEX256","DHGEX1, SSH_BUG_CURVE25519PAD }, -+ { KEXALGOS, CURVE25519, SSH_OLD_DHGEX }, -+ { "a,"KEXALGOS, "a", SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX }, -+ /* TODO: enable once compat_kex_proposal doesn't fatal() */ -+ /* { KEXALGOS, "", SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX }, */ -+ }; -+ -+ TEST_START("compat_kex_proposal"); -+ for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) { -+ ssh.compat = tests[i].compat; -+ /* match entire string */ -+ result = compat_kex_proposal(&ssh, tests[i].in); -+ ASSERT_STRING_EQ(result, tests[i].out); -+ free(result); -+ /* match at end */ -+ in = kex_names_cat("a", tests[i].in); -+ out = kex_names_cat("a", tests[i].out); -+ result = compat_kex_proposal(&ssh, in); -+ ASSERT_STRING_EQ(result, out); -+ free(result); free(in); free(out); -+ /* match at start */ -+ in = kex_names_cat(tests[i].in, "a"); -+ out = kex_names_cat(tests[i].out, "a"); -+ result = compat_kex_proposal(&ssh, in); -+ ASSERT_STRING_EQ(result, out); -+ free(result); free(in); free(out); -+ /* match in middle */ -+ xasprintf(&in, "a,%s,b", tests[i].in); -+ if (*(tests[i].out) == '\0') -+ out = xstrdup("a,b"); -+ else -+ xasprintf(&out, "a,%s,b", tests[i].out); -+ result = compat_kex_proposal(&ssh, in); -+ ASSERT_STRING_EQ(result, out); -+ free(result); free(in); free(out); -+ } -+ TEST_DONE(); -+} -diff --git a/regress/unittests/kex/tests.c b/regress/unittests/kex/tests.c -index e7036ec..2a83daf 100644 ---- a/regress/unittests/kex/tests.c -+++ b/regress/unittests/kex/tests.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: tests.c,v 1.1 2015/01/15 23:41:29 markus Exp $ */ -+/* $OpenBSD: tests.c,v 1.2 2023/02/02 12:12:52 djm Exp $ */ - /* - * Placed in the public domain - */ -@@ -6,9 +6,11 @@ - #include "../test_helper/test_helper.h" - - void kex_tests(void); -+void kex_proposal(void); - - void - tests(void) - { - kex_tests(); -+ kex_proposal(); - } --- -2.27.0 - diff --git a/backport-upstream-use-correct-type-with-sizeof-ok-djm.patch b/backport-upstream-use-correct-type-with-sizeof-ok-djm.patch deleted file mode 100644 index bdd6ac74c2b2e48b1fd3d162534cfc6440601aa8..0000000000000000000000000000000000000000 --- a/backport-upstream-use-correct-type-with-sizeof-ok-djm.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 18376847b8043ba967eabbe23692ef74c9a3fddc Mon Sep 17 00:00:00 2001 -From: "jsg@openbsd.org" -Date: Thu, 13 Oct 2022 09:09:28 +0000 -Subject: [PATCH] upstream: use correct type with sizeof ok djm@ - -OpenBSD-Commit-ID: d6c882c2e8a42ff831a5b3cbc2c961ecb2dd6143 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=18376847b8043ba967eabbe23692ef74c9a3fddc ---- - ssh.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ssh.c b/ssh.c -index e711dbd2..21cbd7c3 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: ssh.c,v 1.577 2022/10/06 22:42:37 djm Exp $ */ -+/* $OpenBSD: ssh.c,v 1.578 2022/10/13 09:09:28 jsg Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -1579,7 +1579,7 @@ main(int ac, char **av) - if (options.hostbased_authentication) { - sensitive_data.nkeys = 10; - sensitive_data.keys = xcalloc(sensitive_data.nkeys, -- sizeof(struct sshkey)); -+ sizeof(*sensitive_data.keys)); - - /* XXX check errors? */ - #define L_PUBKEY(p,o) do { \ --- -2.27.0 - diff --git a/backport-upstream-when-restoring-non-blocking-mode-to-stdio-f.patch b/backport-upstream-when-restoring-non-blocking-mode-to-stdio-f.patch deleted file mode 100644 index c602b7faf6264734fbb9d04c489bb4f0ee893b80..0000000000000000000000000000000000000000 --- a/backport-upstream-when-restoring-non-blocking-mode-to-stdio-f.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 35253af01d8c0ab444c8377402121816e71c71f5 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Wed, 18 Jan 2023 02:00:10 +0000 -Subject: [PATCH] upstream: when restoring non-blocking mode to stdio -fds, - restore - -exactly the flags that ssh started with and don't just clobber them with -zero, as this could also remove the append flag from the set; - -bz3523; ok dtucker@ - -OpenBSD-Commit-ID: 1336b03e881db7564a4b66014eb24c5230e9a0c0 -Conflict:NA -Reference:https://anongit.mindrot.org/openssh.git/commit?id=35253af01d8c0ab444c8377402121816e71c71f5 ---- - channels.c | 19 ++++++++++++++----- - channels.h | 3 ++- - 2 files changed, 16 insertions(+), 6 deletions(-) - -diff --git a/channels.c b/channels.c -index ea4d8da..cee4d2c 100644 ---- a/channels.c -+++ b/channels.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: channels.c,v 1.420 2022/09/19 08:49:50 djm Exp $ */ -+/* $OpenBSD: channels.c,v 1.427 2023/01/18 02:00:10 djm Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -337,16 +337,19 @@ channel_register_fds(struct ssh *ssh, Channel *c, int rfd, int wfd, int efd, - */ - if (rfd != -1 && !isatty(rfd) && - (val = fcntl(rfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { -+ c->restore_flags[0] = val; - c->restore_block |= CHANNEL_RESTORE_RFD; - set_nonblock(rfd); - } - if (wfd != -1 && !isatty(wfd) && - (val = fcntl(wfd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { -+ c->restore_flags[1] = val; - c->restore_block |= CHANNEL_RESTORE_WFD; - set_nonblock(wfd); - } - if (efd != -1 && !isatty(efd) && - (val = fcntl(efd, F_GETFL)) != -1 && !(val & O_NONBLOCK)) { -+ c->restore_flags[2] = val; - c->restore_block |= CHANNEL_RESTORE_EFD; - set_nonblock(efd); - } -@@ -428,10 +431,16 @@ channel_close_fd(struct ssh *ssh, Channel *c, int *fdp) - if (fd == -1) - return 0; - -- if ((*fdp == c->rfd && (c->restore_block & CHANNEL_RESTORE_RFD) != 0) || -- (*fdp == c->wfd && (c->restore_block & CHANNEL_RESTORE_WFD) != 0) || -- (*fdp == c->efd && (c->restore_block & CHANNEL_RESTORE_EFD) != 0)) -- (void)fcntl(*fdp, F_SETFL, 0); /* restore blocking */ -+ /* restore blocking */ -+ if (*fdp == c->rfd && -+ (c->restore_block & CHANNEL_RESTORE_RFD) != 0) -+ (void)fcntl(*fdp, F_SETFL, c->restore_flags[0]); -+ else if (*fdp == c->wfd && -+ (c->restore_block & CHANNEL_RESTORE_WFD) != 0) -+ (void)fcntl(*fdp, F_SETFL, c->restore_flags[1]); -+ else if (*fdp == c->efd && -+ (c->restore_block & CHANNEL_RESTORE_EFD) != 0) -+ (void)fcntl(*fdp, F_SETFL, c->restore_flags[2]); - - if (*fdp == c->rfd) { - c->io_want &= ~SSH_CHAN_IO_RFD; -diff --git a/channels.h b/channels.h -index 7d8a83e..9b1b11e 100644 ---- a/channels.h -+++ b/channels.h -@@ -1,4 +1,4 @@ --/* $OpenBSD: channels.h,v 1.143 2022/05/05 00:56:58 djm Exp $ */ -+/* $OpenBSD: channels.h,v 1.148 2023/01/18 02:00:10 djm Exp $ */ - - /* - * Author: Tatu Ylonen -@@ -153,6 +153,7 @@ struct Channel { - * this way post-IO handlers are not - * accidentally called if a FD gets reused */ - int restore_block; /* fd mask to restore blocking status */ -+ int restore_flags[3]; /* flags to restore */ - struct sshbuf *input; /* data read from socket, to be sent over - * encrypted connection */ - struct sshbuf *output; /* data received over encrypted connection for --- -2.23.0 - diff --git a/bugfix-openssh-add-option-check-username-splash.patch b/bugfix-openssh-add-option-check-username-splash.patch index 3a1b23789498549db877bed669153745e030daa4..1c8af38c65ee1c4e5f1fab3834a62211f7b0868d 100644 --- a/bugfix-openssh-add-option-check-username-splash.patch +++ b/bugfix-openssh-add-option-check-username-splash.patch @@ -14,10 +14,10 @@ this check 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/auth2.c b/auth2.c -index 203ba01..284ea19 100644 +index 4d574bb..c480aab 100644 --- a/auth2.c +++ b/auth2.c -@@ -281,11 +281,13 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) +@@ -278,11 +278,13 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) debug("userauth-request for user %s service %s method %s", user, service, method); debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); @@ -33,10 +33,10 @@ index 203ba01..284ea19 100644 *style++ = 0; diff --git a/servconf.c b/servconf.c -index d72fb62..6888971 100644 +index bcf69fd..b8340d8 100644 --- a/servconf.c +++ b/servconf.c -@@ -201,6 +201,7 @@ initialize_server_options(ServerOptions *options) +@@ -199,6 +199,7 @@ initialize_server_options(ServerOptions *options) options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->version_addendum = NULL; @@ -44,7 +44,7 @@ index d72fb62..6888971 100644 options->fingerprint_hash = -1; options->disable_forwarding = -1; options->expose_userauth_info = -1; -@@ -460,6 +461,8 @@ fill_default_server_options(ServerOptions *options) +@@ -456,6 +457,8 @@ fill_default_server_options(ServerOptions *options) options->ip_qos_bulk = IPTOS_DSCP_CS1; if (options->version_addendum == NULL) options->version_addendum = xstrdup(""); @@ -53,15 +53,15 @@ index d72fb62..6888971 100644 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) options->fwd_opts.streamlocal_bind_mask = 0177; if (options->fwd_opts.streamlocal_bind_unlink == -1) -@@ -553,6 +556,7 @@ typedef enum { +@@ -557,6 +560,7 @@ typedef enum { sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, - sRequiredRSASize, -+ sCheckUserSplash, + sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout, ++ sCheckUserSplash, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; -@@ -726,6 +730,7 @@ static struct { +@@ -730,6 +734,7 @@ static struct { { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, @@ -69,7 +69,7 @@ index d72fb62..6888971 100644 { "rdomain", sRDomain, SSHCFG_ALL }, { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, -@@ -1384,6 +1389,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1443,6 +1448,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, case sUsePAM: intptr = &options->use_pam; goto parse_flag; @@ -80,19 +80,19 @@ index d72fb62..6888971 100644 /* Standard Options */ case sBadOption: diff --git a/servconf.h b/servconf.h -index 77fd779..694addf 100644 +index ccc0181..cb57dac 100644 --- a/servconf.h +++ b/servconf.h @@ -237,6 +237,7 @@ typedef struct { int fingerprint_hash; int expose_userauth_info; u_int64_t timing_secret; -+ int check_user_splash; /* check whether splash exists in username, if exist, disable login */ ++ int check_user_splash; /* check whether splash exists in username, if exist, disable login */ char *sk_provider; int required_rsa_size; /* minimum size of RSA keys */ - } ServerOptions; + diff --git a/sshd_config b/sshd_config -index 6d47368..973aecf 100644 +index 9851748..d57f11d 100644 --- a/sshd_config +++ b/sshd_config @@ -128,3 +128,5 @@ Subsystem sftp /usr/libexec/sftp-server @@ -102,5 +102,5 @@ index 6d47368..973aecf 100644 +#CheckUserSplash yes + -- -2.27.0 +2.23.0 diff --git a/feature-add-SMx-support.patch b/feature-add-SMx-support.patch index 0a9e567431ba9d429a74f4c94113970a34d13fec..e8b0f3c08132f81e8da32131e5c87c03e43f792c 100644 --- a/feature-add-SMx-support.patch +++ b/feature-add-SMx-support.patch @@ -1,13 +1,7 @@ -From 93b312c0263cbf40f66448ff7ddbea7a2def1953 Mon Sep 17 00:00:00 2001 -From: kircher -Date: Fri, 29 Jul 2022 10:45:08 +0800 -Subject: [PATCH] add SMx support in openssh -HostKeyAlgorithms sm2 -KexAlgorithms sm2-sm3 -MACs hmac-sm3 -Ciphers sm4-ctr -PubkeyAcceptedAlgorithms sm2 -FingerprintHash sm3 +From d2e28809c673f914b49147ca3fa31e08b9e885d7 Mon Sep 17 00:00:00 2001 +From: renmingshuai +Date: Sat, 29 Jul 2023 10:50:29 +0800 +Subject: [PATCH] feature add sm2 --- Makefile.in | 4 +- @@ -31,21 +25,21 @@ FingerprintHash sm3 ssh-ecdsa.c | 6 +- ssh-keygen.c | 12 +- ssh-keyscan.c | 12 +- - ssh-sm2.c | 230 +++++++++++++++ + ssh-sm2.c | 381 ++++++++++++++++++++++++ ssh_api.c | 2 + sshconnect2.c | 1 + sshd.c | 7 + - sshkey.c | 62 +++- - sshkey.h | 9 + - 27 files changed, 794 insertions(+), 16 deletions(-) + sshkey.c | 21 ++ + sshkey.h | 2 + + 27 files changed, 899 insertions(+), 14 deletions(-) create mode 100644 kexsm2.c create mode 100644 ssh-sm2.c diff --git a/Makefile.in b/Makefile.in -index 07bf440..1393190 100644 +index 5fec5b3..7dcda3e 100644 --- a/Makefile.in +++ b/Makefile.in -@@ -100,14 +100,14 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ +@@ -102,14 +102,14 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ log.o match.o moduli.o nchan.o packet.o \ readpass.o ttymodes.o xmalloc.o addr.o addrmatch.o \ atomicio.o dispatch.o mac.o misc.o utf8.o \ @@ -56,17 +50,17 @@ index 07bf440..1393190 100644 ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ ssh-ed25519.o digest-openssl.o digest-libc.o \ - hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ + hmac.o ed25519.o hash.o \ - kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o kexsm2.o \ kexgexc.o kexgexs.o \ kexsntrup761x25519.o sntrup761.o kexgen.o \ kexgssc.o \ diff --git a/authfd.c b/authfd.c -index 9f092f7..163b4b5 100644 +index 25a3636..bcc25a7 100644 --- a/authfd.c +++ b/authfd.c -@@ -512,6 +512,8 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, +@@ -583,6 +583,8 @@ ssh_add_identity_constrained(int sock, struct sshkey *key, case KEY_DSA_CERT: case KEY_ECDSA: case KEY_ECDSA_CERT: @@ -76,10 +70,10 @@ index 9f092f7..163b4b5 100644 case KEY_ECDSA_SK_CERT: #endif diff --git a/authfile.c b/authfile.c -index 666730b..dce1e84 100644 +index 445f2dd..3884031 100644 --- a/authfile.c +++ b/authfile.c -@@ -343,6 +343,7 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, +@@ -332,6 +332,7 @@ sshkey_load_private_cert(int type, const char *filename, const char *passphrase, case KEY_RSA: case KEY_DSA: case KEY_ECDSA: @@ -88,10 +82,10 @@ index 666730b..dce1e84 100644 case KEY_ED25519: case KEY_XMSS: diff --git a/cipher.c b/cipher.c -index b54b994..039e414 100644 +index 609450d..7f98413 100644 --- a/cipher.c +++ b/cipher.c -@@ -88,6 +88,7 @@ static const struct sshcipher ciphers[] = { +@@ -86,6 +86,7 @@ static const struct sshcipher ciphers[] = { #endif { "chacha20-poly1305@openssh.com", 8, 64, 0, 16, CFLAG_CHACHAPOLY, NULL }, @@ -126,10 +120,10 @@ index c7ceeb3..520722c 100644 struct sshbuf; struct ssh_digest_ctx; diff --git a/kex.c b/kex.c -index d0a9dee..6284f90 100644 +index 0fbd0ca..e9dfcc2 100644 --- a/kex.c +++ b/kex.c -@@ -124,6 +124,7 @@ static const struct kexalg kexalgs[] = { +@@ -125,6 +125,7 @@ static const struct kexalg kexalgs[] = { SSH_DIGEST_SHA512 }, #endif #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ @@ -138,7 +132,7 @@ index d0a9dee..6284f90 100644 }; static const struct kexalg gss_kexalgs[] = { diff --git a/kex.h b/kex.h -index d26ba26..8b95227 100644 +index 0fac9d3..044ec18 100644 --- a/kex.h +++ b/kex.h @@ -102,6 +102,7 @@ enum kex_exchange { @@ -149,7 +143,7 @@ index d26ba26..8b95227 100644 #ifdef GSSAPI KEX_GSS_GRP1_SHA1, KEX_GSS_GRP14_SHA1, -@@ -277,6 +278,8 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], +@@ -287,6 +288,8 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); @@ -223,7 +217,7 @@ index efb2e55..69ec13b 100644 kex->ec_client_key = NULL; return r; diff --git a/kexgen.c b/kexgen.c -index 31f90f5..f3eff47 100644 +index ca70484..4855d5c 100644 --- a/kexgen.c +++ b/kexgen.c @@ -111,6 +111,7 @@ kex_gen_client(struct ssh *ssh) @@ -242,7 +236,7 @@ index 31f90f5..f3eff47 100644 r = kex_ecdh_dec(kex, server_blob, &shared_secret); break; #endif -@@ -280,6 +282,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) +@@ -298,6 +300,7 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) &shared_secret); break; case KEX_ECDH_SHA2: @@ -687,7 +681,7 @@ index a094888..0a805ad 100644 /* * Configuration file in user's home directory. This file need not be diff --git a/regress/agent.sh b/regress/agent.sh -index f187b67..42a5124 100644 +index 5f10606..3ab40b4 100644 --- a/regress/agent.sh +++ b/regress/agent.sh @@ -87,9 +87,18 @@ fi @@ -764,10 +758,10 @@ index b32502b..f260692 100644 sshkey_verify(ed25519, sig, slen, (const u_char *)data, dlen, NULL, 0, &details); sshkey_sig_details_free(details); diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c -index 3bd71a9..312e8f2 100644 +index c26761e..d335b29 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c -@@ -152,6 +152,7 @@ do_kex_with_key(char *kex, int keytype, int bits) +@@ -151,6 +151,7 @@ do_kex_with_key(char *kex, int keytype, int bits) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; @@ -775,7 +769,7 @@ index 3bd71a9..312e8f2 100644 server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; server2->kex->load_host_public_key = server->kex->load_host_public_key; server2->kex->load_host_private_key = server->kex->load_host_private_key; -@@ -186,6 +187,7 @@ do_kex(char *kex) +@@ -185,6 +186,7 @@ do_kex(char *kex) #endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ do_kex_with_key(kex, KEY_ED25519, 256); @@ -783,7 +777,7 @@ index 3bd71a9..312e8f2 100644 } void -@@ -202,6 +204,7 @@ kex_tests(void) +@@ -201,6 +203,7 @@ kex_tests(void) do_kex("diffie-hellman-group-exchange-sha1"); do_kex("diffie-hellman-group14-sha1"); do_kex("diffie-hellman-group1-sha1"); @@ -792,10 +786,10 @@ index 3bd71a9..312e8f2 100644 do_kex("sntrup761x25519-sha512@openssh.com"); # endif /* USE_SNTRUP761X25519 */ diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c -index b036796..6697be6 100644 +index b705157..5445ab5 100644 --- a/ssh-ecdsa.c +++ b/ssh-ecdsa.c -@@ -66,7 +66,8 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +@@ -256,7 +256,8 @@ ssh_ecdsa_sign(struct sshkey *key, *sigp = NULL; if (key == NULL || key->ecdsa == NULL || @@ -805,21 +799,21 @@ index b036796..6697be6 100644 return SSH_ERR_INVALID_ARGUMENT; if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) -@@ -133,7 +134,8 @@ ssh_ecdsa_verify(const struct sshkey *key, +@@ -332,7 +333,8 @@ ssh_ecdsa_verify(const struct sshkey *key, unsigned char *sigb = NULL, *psig = NULL; if (key == NULL || key->ecdsa == NULL || - sshkey_type_plain(key->type) != KEY_ECDSA || -+ (sshkey_type_plain(key->type) != KEY_ECDSA && -+ sshkey_type_plain(key->type) != KEY_SM2) || - signature == NULL || signaturelen == 0) ++ (sshkey_type_plain(key->type) != KEY_ECDSA && ++ sshkey_type_plain(key->type) != KEY_SM2) || + sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; diff --git a/ssh-keygen.c b/ssh-keygen.c -index b9c4dce..bd6ea16 100644 +index 0bff209..46f4998 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c -@@ -192,6 +192,7 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) +@@ -193,6 +193,7 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) *bitsp = DEFAULT_BITS_DSA; break; case KEY_ECDSA: @@ -827,7 +821,7 @@ index b9c4dce..bd6ea16 100644 if (name != NULL && (nid = sshkey_ecdsa_nid_from_name(name)) > 0) *bitsp = sshkey_curve_nid_to_bits(nid); -@@ -224,6 +225,10 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) +@@ -219,6 +220,10 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) fatal("Invalid RSA key length: maximum is %d bits", OPENSSL_RSA_MAX_MODULUS_BITS); break; @@ -838,7 +832,7 @@ index b9c4dce..bd6ea16 100644 case KEY_ECDSA: if (sshkey_ecdsa_bits_to_nid(*bitsp) == -1) #ifdef OPENSSL_HAS_NISTP521 -@@ -280,6 +285,9 @@ ask_filename(struct passwd *pw, const char *prompt) +@@ -275,6 +280,9 @@ ask_filename(struct passwd *pw, const char *prompt) case KEY_ECDSA: name = _PATH_SSH_CLIENT_ID_ECDSA; break; @@ -848,7 +842,7 @@ index b9c4dce..bd6ea16 100644 case KEY_ECDSA_SK_CERT: case KEY_ECDSA_SK: name = _PATH_SSH_CLIENT_ID_ECDSA_SK; -@@ -391,6 +399,7 @@ do_convert_to_pkcs8(struct sshkey *k) +@@ -386,6 +394,7 @@ do_convert_to_pkcs8(struct sshkey *k) break; #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: @@ -856,7 +850,7 @@ index b9c4dce..bd6ea16 100644 if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) fatal("PEM_write_EC_PUBKEY failed"); break; -@@ -415,6 +424,7 @@ do_convert_to_pem(struct sshkey *k) +@@ -410,6 +419,7 @@ do_convert_to_pem(struct sshkey *k) break; #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: @@ -864,7 +858,7 @@ index b9c4dce..bd6ea16 100644 if (!PEM_write_EC_PUBKEY(stdout, k->ecdsa)) fatal("PEM_write_EC_PUBKEY failed"); break; -@@ -3148,7 +3158,7 @@ usage(void) +@@ -3280,7 +3290,7 @@ usage(void) fprintf(stderr, "usage: ssh-keygen [-q] [-a rounds] [-b bits] [-C comment] [-f output_keyfile]\n" " [-m format] [-N new_passphrase] [-O option]\n" @@ -874,10 +868,10 @@ index b9c4dce..bd6ea16 100644 " ssh-keygen -p [-a rounds] [-f keyfile] [-m format] [-N new_passphrase]\n" " [-P old_passphrase] [-Z cipher]\n" diff --git a/ssh-keyscan.c b/ssh-keyscan.c -index 9ec4d9a..be2af0a 100644 +index 245c73d..b402a21 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c -@@ -63,9 +63,10 @@ int ssh_port = SSH_DEFAULT_PORT; +@@ -68,9 +68,10 @@ int ssh_port = SSH_DEFAULT_PORT; #define KT_XMSS (1<<4) #define KT_ECDSA_SK (1<<5) #define KT_ED25519_SK (1<<6) @@ -889,7 +883,7 @@ index 9ec4d9a..be2af0a 100644 int get_cert = 0; int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519|KT_ECDSA_SK|KT_ED25519_SK; -@@ -261,6 +262,11 @@ keygrab_ssh2(con *c) +@@ -267,6 +268,11 @@ keygrab_ssh2(con *c) "ecdsa-sha2-nistp384," "ecdsa-sha2-nistp521"; break; @@ -901,7 +895,7 @@ index 9ec4d9a..be2af0a 100644 case KT_ECDSA_SK: myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = get_cert ? "sk-ecdsa-sha2-nistp256-cert-v01@openssh.com" : -@@ -290,6 +296,7 @@ keygrab_ssh2(con *c) +@@ -296,6 +302,7 @@ keygrab_ssh2(con *c) c->c_ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC c->c_ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; @@ -909,7 +903,7 @@ index 9ec4d9a..be2af0a 100644 # endif #endif c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; -@@ -730,6 +737,9 @@ main(int argc, char **argv) +@@ -789,6 +796,9 @@ main(int argc, char **argv) case KEY_ECDSA: get_keytypes |= KT_ECDSA; break; @@ -921,10 +915,10 @@ index 9ec4d9a..be2af0a 100644 break; diff --git a/ssh-sm2.c b/ssh-sm2.c new file mode 100644 -index 0000000..c242139 +index 0000000..75e9731 --- /dev/null +++ b/ssh-sm2.c -@@ -0,0 +1,220 @@ +@@ -0,0 +1,381 @@ +#include "includes.h" +#include +#include @@ -939,30 +933,167 @@ index 0000000..c242139 + +#include "openbsd-compat/openssl-compat.h" + ++/* Reuse some ECDSA internals */ ++extern struct sshkey_impl_funcs sshkey_ecdsa_funcs; ++ +const unsigned char *sm2_id = (const unsigned char *)"1234567812345678"; + -+int -+ssh_sm2_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, -+ const u_char *data, size_t datalen, u_int compat) ++static void ++ssh_sm2_cleanup(struct sshkey *k) ++{ ++ EC_KEY_free(k->ecdsa); ++ k->ecdsa = NULL; ++} ++ ++static int ++ssh_sm2_equal(const struct sshkey *a, const struct sshkey *b) ++{ ++ if (!sshkey_ecdsa_funcs.equal(a, b)) ++ return 0; ++ return 1; ++} ++ ++static int ++ssh_sm2_serialize_public(const struct sshkey *key, struct sshbuf *b, ++ enum sshkey_serialize_rep opts) ++{ ++ int r; ++ ++ if ((r = sshkey_ecdsa_funcs.serialize_public(key, b, opts)) != 0) ++ return r; ++ ++ return 0; ++} ++ ++static int ++ssh_sm2_deserialize_public(const char *ktype, struct sshbuf *b, ++ struct sshkey *key) ++{ ++ int r; ++ ++ if ((r = sshkey_ecdsa_funcs.deserialize_public(ktype, b, key)) != 0) ++ return r; ++ return 0; ++} ++ ++static int ++ssh_sm2_serialize_private(const struct sshkey *key, struct sshbuf *b, ++ enum sshkey_serialize_rep opts) ++{ ++ int r; ++ ++ if ((r = sshkey_ecdsa_funcs.serialize_private(key, b, opts)) != 0) ++ return r; ++ ++ return 0; ++} ++ ++static int ++ssh_sm2_deserialize_private(const char *ktype, struct sshbuf *b, ++ struct sshkey *key) ++{ ++ int r; ++ ++ if ((r = sshkey_ecdsa_funcs.deserialize_private(ktype, b, key)) != 0) ++ return r; ++ ++ return 0; ++} ++ ++static int ++ssh_sm2_generate(struct sshkey *k, int bits) ++{ ++ EC_KEY *private; ++ ++ k->ecdsa_nid = NID_sm2; ++ if ((private = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) ++ return SSH_ERR_ALLOC_FAIL; ++ if (EC_KEY_generate_key(private) != 1) { ++ EC_KEY_free(private); ++ return SSH_ERR_LIBCRYPTO_ERROR; ++ } ++ EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); ++ k->ecdsa = private; ++ return 0; ++} ++ ++static int ++ssh_sm2_copy_public(const struct sshkey *from, struct sshkey *to) ++{ ++ int r; ++ ++ if ((r = sshkey_ecdsa_funcs.copy_public(from, to)) != 0) ++ return r; ++ return 0; ++} ++ ++static int ++sm2_get_sig(EVP_PKEY *pkey, const u_char *data, ++ size_t datalen, u_char *sig, size_t *slen) ++{ ++ EVP_PKEY_CTX *pctx = NULL; ++ EVP_MD_CTX *mctx = NULL; ++ int ret = SSH_ERR_INTERNAL_ERROR; ++ ++ if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if ((mctx = EVP_MD_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (EVP_PKEY_CTX_set1_id(pctx, sm2_id, 16) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ EVP_MD_CTX_set_pkey_ctx(mctx, pctx); ++ ++ if ((EVP_DigestSignInit(mctx, NULL, EVP_sm3(), NULL, pkey)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((EVP_DigestSignUpdate(mctx, data, datalen)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ++ if ((EVP_DigestSignFinal(mctx, sig, slen)) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } ++ ret = 0; ++ ++out: ++ EVP_PKEY_CTX_free(pctx); ++ EVP_MD_CTX_free(mctx); ++ return ret; ++} ++ ++static int ++ssh_sm2_sign(struct sshkey *key, ++ u_char **sigp, size_t *lenp, ++ const u_char *data, size_t datalen, ++ const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) +{ + u_char *sig = NULL; -+ size_t slen = 0; ++ size_t slen = 0; + int pkey_len = 0; + int r = 0; + int len = 0; + EVP_PKEY *key_sm2 = NULL; -+ struct sshbuf *b = NULL; -+ EVP_PKEY_CTX *pctx = NULL; -+ EVP_MD_CTX *mctx = NULL; -+ int ret = SSH_ERR_INTERNAL_ERROR; ++ struct sshbuf *b = NULL; ++ int ret = SSH_ERR_INTERNAL_ERROR; + -+ if (lenp != NULL) -+ *lenp = 0; -+ if (sigp != NULL) -+ *sigp = NULL; ++ if (lenp != NULL) ++ *lenp = 0; ++ if (sigp != NULL) ++ *sigp = NULL; + + if (key == NULL || key->ecdsa == NULL || -+ sshkey_type_plain(key->type) != KEY_SM2) ++ sshkey_type_plain(key->type) != KEY_SM2) + return SSH_ERR_INVALID_ARGUMENT; + + if ((key_sm2 = EVP_PKEY_new()) == NULL) { @@ -974,177 +1105,201 @@ index 0000000..c242139 + goto out; + } + -+ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { -+ ret = SSH_ERR_INVALID_ARGUMENT; -+ goto out; -+ } ++ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { ++ ret = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } + + slen = pkey_len; -+ -+ if ((sig = OPENSSL_malloc(pkey_len)) == NULL) { ++ ++ if ((sig = OPENSSL_malloc(pkey_len)) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; -+ } ++ } + -+ if ((pctx = EVP_PKEY_CTX_new(key_sm2, NULL)) == NULL) { ++ if (ret = sm2_get_sig(key_sm2, data, datalen, sig, &slen)) { ++ goto out; ++ } ++ ++ if ((b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; -+ goto out; ++ goto out; + } + -+ if (EVP_PKEY_CTX_set1_id(pctx, sm2_id, 16) != 1) { -+ ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ if ((r = sshbuf_put_cstring(b, "sm2")) != 0 || ++ (r = sshbuf_put_string(b, sig, slen)) != 0) ++ goto out; ++ len = sshbuf_len(b); ++ if (sigp != NULL) { ++ if ((*sigp = malloc(len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ memcpy(*sigp, sshbuf_ptr(b), len); ++ } ++ if (lenp != NULL) ++ *lenp = len; ++ ret = 0; ++ ++out: ++ EVP_PKEY_free(key_sm2); ++ if (sig != NULL) { ++ explicit_bzero(sig, slen); ++ OPENSSL_free(sig); ++ } ++ sshbuf_free(b); ++ return ret; ++} ++ ++static int ++sm2_verify_sig(EVP_PKEY *pkey, const u_char *data, ++ size_t datalen, const u_char *sig, size_t slen) ++{ ++ EVP_PKEY_CTX *pctx = NULL; ++ EVP_MD_CTX *mctx = NULL; ++ int ret = SSH_ERR_INTERNAL_ERROR; ++ ++ if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; + } -+ ++ + if ((mctx = EVP_MD_CTX_new()) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; + } + ++ if (EVP_PKEY_CTX_set1_id(pctx, sm2_id, 16) != 1) { ++ ret = SSH_ERR_INTERNAL_ERROR; ++ goto out; ++ } + EVP_MD_CTX_set_pkey_ctx(mctx, pctx); + -+ if ((EVP_DigestSignInit(mctx, NULL, EVP_sm3(), NULL, key_sm2)) != 1) { ++ if ((EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, pkey)) != 1) { + ret = SSH_ERR_INTERNAL_ERROR; + goto out; + } + -+ if ((EVP_DigestSignUpdate(mctx, data, datalen)) != 1) { ++ if ((EVP_DigestVerifyUpdate(mctx, data, datalen)) != 1) { + ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ goto out; + } -+ -+ if ((EVP_DigestSignFinal(mctx, sig, &slen)) != 1) { ++ ++ if ((EVP_DigestVerifyFinal(mctx, sig, slen)) != 1) { + ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ goto out; + } + -+ if ((b = sshbuf_new()) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if ((r = sshbuf_put_cstring(b, "sm2")) != 0 || -+ (r = sshbuf_put_string(b, sig, slen)) != 0) -+ goto out; -+ len = sshbuf_len(b); -+ if (sigp != NULL) { -+ if ((*sigp = malloc(len)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ memcpy(*sigp, sshbuf_ptr(b), len); -+ } -+ if (lenp != NULL) -+ *lenp = len; + ret = 0; -+ +out: -+ EVP_PKEY_free(key_sm2); -+ if (sig != NULL) { -+ explicit_bzero(sig, slen); -+ OPENSSL_free(sig); -+ } + EVP_PKEY_CTX_free(pctx); + EVP_MD_CTX_free(mctx); -+ sshbuf_free(b); + return ret; +} + -+int ++static int +ssh_sm2_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, -+ const u_char *data, size_t datalen, u_int compat) ++ const u_char *data, size_t datalen, const char *alg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ + const u_char *sig = NULL; + char *ktype = NULL; + size_t slen = 0; -+ int pkey_len = 0; -+ int r = 0; -+ int len = 0; ++ int pkey_len = 0; ++ int r = 0; ++ int len = 0; + EVP_PKEY *key_sm2 = NULL; -+ struct sshbuf *b = NULL; -+ EVP_PKEY_CTX *pctx = NULL; -+ EVP_MD_CTX *mctx = NULL; -+ int ret = SSH_ERR_INTERNAL_ERROR; ++ struct sshbuf *b = NULL; ++ int ret = SSH_ERR_INTERNAL_ERROR; + -+ if (key == NULL || -+ sshkey_type_plain(key->type) != KEY_SM2 || -+ signature == NULL || signaturelen == 0) -+ return SSH_ERR_INVALID_ARGUMENT; ++ if (key == NULL || ++ sshkey_type_plain(key->type) != KEY_SM2 || ++ signature == NULL || signaturelen == 0) ++ return SSH_ERR_INVALID_ARGUMENT; + -+ if ((b = sshbuf_from(signature, signaturelen)) == NULL) -+ return SSH_ERR_ALLOC_FAIL; ++ if ((b = sshbuf_from(signature, signaturelen)) == NULL) ++ return SSH_ERR_ALLOC_FAIL; + -+ if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || -+ (r = sshbuf_get_string_direct(b, &sig, &slen)) != 0) -+ goto out; ++ if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 || ++ (r = sshbuf_get_string_direct(b, &sig, &slen)) != 0) ++ goto out; + + if (strcmp("sm2", ktype) != 0) { -+ ret = SSH_ERR_KEY_TYPE_MISMATCH; -+ goto out; ++ ret = SSH_ERR_KEY_TYPE_MISMATCH; ++ goto out; + } + -+ if (sshbuf_len(b) != 0) { -+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; -+ goto out; -+ } -+ -+ if ((key_sm2 = EVP_PKEY_new()) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if ((EVP_PKEY_set1_EC_KEY(key_sm2, key->ecdsa)) != 1) { -+ ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; -+ } -+ -+ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { -+ ret = SSH_ERR_INVALID_ARGUMENT; -+ goto out; -+ } -+ -+ if ((pctx = EVP_PKEY_CTX_new(key_sm2, NULL)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if (EVP_PKEY_CTX_set1_id(pctx, sm2_id, 16) != 1) { -+ ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; -+ } -+ -+ if ((mctx = EVP_MD_CTX_new()) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } ++ if (sshbuf_len(b) != 0) { ++ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; ++ goto out; ++ } + -+ EVP_MD_CTX_set_pkey_ctx(mctx, pctx); ++ if ((key_sm2 = EVP_PKEY_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + -+ if ((EVP_DigestVerifyInit(mctx, NULL, EVP_sm3(), NULL, key_sm2)) != 1) { ++ if ((EVP_PKEY_set1_EC_KEY(key_sm2, key->ecdsa)) != 1) { + ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ goto out; + } -+ -+ if ((EVP_DigestVerifyUpdate(mctx, data, datalen)) != 1) { -+ ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ ++ if ((pkey_len = EVP_PKEY_size(key_sm2)) == 0) { ++ ret = SSH_ERR_INVALID_ARGUMENT; ++ goto out; + } -+ -+ if ((EVP_DigestVerifyFinal(mctx, sig, slen)) != 1) { -+ ret = SSH_ERR_INTERNAL_ERROR; -+ goto out; ++ ++ if (ret = sm2_verify_sig(key_sm2, data, datalen, sig, slen)) { ++ goto out; + } + + ret = 0; +out: + EVP_PKEY_free(key_sm2); -+ EVP_PKEY_CTX_free(pctx); -+ EVP_MD_CTX_free(mctx); -+ sshbuf_free(b); ++ sshbuf_free(b); + free(ktype); + return ret; +} ++ ++static const struct sshkey_impl_funcs sshkey_sm2_funcs = { ++ /* .size = */ NULL, ++ /* .alloc = */ NULL, ++ /* .cleanup = */ ssh_sm2_cleanup, ++ /* .equal = */ ssh_sm2_equal, ++ /* .ssh_serialize_public = */ ssh_sm2_serialize_public, ++ /* .ssh_deserialize_public = */ ssh_sm2_deserialize_public, ++ /* .ssh_serialize_private = */ ssh_sm2_serialize_private, ++ /* .ssh_deserialize_private = */ssh_sm2_deserialize_private, ++ /* .generate = */ ssh_sm2_generate, ++ /* .copy_public = */ ssh_sm2_copy_public, ++ /* .sign = */ ssh_sm2_sign, ++ /* .verify = */ ssh_sm2_verify, ++}; ++ ++const struct sshkey_impl sshkey_sm2_impl = { ++ /* .name = */ "sm2", ++ /* .shortname = */ "SM2", ++ /* .sigalg = */ NULL, ++ /* .type = */ KEY_SM2, ++ /* .nid = */ NID_sm2, ++ /* .cert = */ 0, ++ /* .sigonly = */ 0, ++ /* .keybits = */ 256, ++ /* .funcs = */ &sshkey_sm2_funcs, ++}; ++ ++const struct sshkey_impl sshkey_sm2_cert_impl = { ++ /* .name = */ "sm2-cert", ++ /* .shortname = */ "SM2-CERT", ++ /* .sigalg = */ NULL, ++ /* .type = */ KEY_SM2_CERT, ++ /* .nid = */ NID_sm2, ++ /* .cert = */ 1, ++ /* .sigonly = */ 0, ++ /* .keybits = */ 256, ++ /* .funcs = */ &sshkey_sm2_funcs, ++}; diff --git a/ssh_api.c b/ssh_api.c index d3c6617..adc2598 100644 --- a/ssh_api.c @@ -1166,10 +1321,10 @@ index d3c6617..adc2598 100644 #endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; diff --git a/sshconnect2.c b/sshconnect2.c -index fafc0a2..9a01f1a 100644 +index 3acfdb6..3fbff57 100644 --- a/sshconnect2.c +++ b/sshconnect2.c -@@ -327,6 +327,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, +@@ -326,6 +326,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; @@ -1178,10 +1333,10 @@ index fafc0a2..9a01f1a 100644 # ifdef GSSAPI if (options.gss_keyex) { diff --git a/sshd.c b/sshd.c -index 8424e33..57d70fe 100644 +index f366457..52c66ed 100644 --- a/sshd.c +++ b/sshd.c -@@ -706,6 +706,7 @@ list_hostkey_types(void) +@@ -695,6 +695,7 @@ list_hostkey_types(void) /* FALLTHROUGH */ case KEY_DSA: case KEY_ECDSA: @@ -1189,7 +1344,7 @@ index 8424e33..57d70fe 100644 case KEY_ED25519: case KEY_ECDSA_SK: case KEY_ED25519_SK: -@@ -727,6 +728,7 @@ list_hostkey_types(void) +@@ -716,6 +717,7 @@ list_hostkey_types(void) /* FALLTHROUGH */ case KEY_DSA_CERT: case KEY_ECDSA_CERT: @@ -1197,7 +1352,7 @@ index 8424e33..57d70fe 100644 case KEY_ED25519_CERT: case KEY_ECDSA_SK_CERT: case KEY_ED25519_SK_CERT: -@@ -753,6 +755,7 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) +@@ -742,6 +744,7 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) case KEY_RSA_CERT: case KEY_DSA_CERT: case KEY_ECDSA_CERT: @@ -1205,7 +1360,7 @@ index 8424e33..57d70fe 100644 case KEY_ED25519_CERT: case KEY_ECDSA_SK_CERT: case KEY_ED25519_SK_CERT: -@@ -769,8 +772,10 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) +@@ -758,8 +761,10 @@ get_hostkey_by_type(int type, int nid, int need_private, struct ssh *ssh) continue; switch (type) { case KEY_ECDSA: @@ -1216,7 +1371,7 @@ index 8424e33..57d70fe 100644 case KEY_ECDSA_SK_CERT: if (key->ecdsa_nid != nid) continue; -@@ -1983,6 +1988,7 @@ main(int ac, char **av) +@@ -2012,6 +2017,7 @@ main(int ac, char **av) case KEY_RSA: case KEY_DSA: case KEY_ECDSA: @@ -1224,7 +1379,7 @@ index 8424e33..57d70fe 100644 case KEY_ED25519: case KEY_ECDSA_SK: case KEY_ED25519_SK: -@@ -2572,6 +2578,7 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2573,6 +2579,7 @@ do_ssh2_kex(struct ssh *ssh) kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; @@ -1233,19 +1388,28 @@ index 8424e33..57d70fe 100644 # ifdef GSSAPI if (options.gss_keyex) { diff --git a/sshkey.c b/sshkey.c -index b0c2189..51f8e51 100644 +index 1735159..1aee244 100644 --- a/sshkey.c +++ b/sshkey.c -@@ -159,6 +159,8 @@ static const struct keytype keytypes[] = { - # endif /* OPENSSL_HAS_ECC */ - #endif /* WITH_OPENSSL */ - { "null", "null", NULL, KEY_NULL, 0, 0, 0 }, -+ { "sm2", "SM2", NULL, KEY_SM2, NID_sm2, 0, 0 }, -+ { "sm2-cert", "SM2-CERT", NULL, KEY_SM2_CERT, NID_sm2, 1, 0 }, - { NULL, NULL, NULL, -1, -1, 0, 0 } +@@ -130,6 +130,8 @@ extern const struct sshkey_impl sshkey_dsa_cert_impl; + extern const struct sshkey_impl sshkey_xmss_impl; + extern const struct sshkey_impl sshkey_xmss_cert_impl; + #endif ++extern const struct sshkey_impl sshkey_sm2_impl; ++extern const struct sshkey_impl sshkey_sm2_cert_impl; + + static int ssh_gss_equal(const struct sshkey *, const struct sshkey *) + { +@@ -237,6 +239,8 @@ const struct sshkey_impl * const keyimpls[] = { + &sshkey_xmss_cert_impl, + #endif + &sshkey_gss_kex_impl, ++ &sshkey_sm2_impl, ++ &sshkey_sm2_cert_impl, + NULL }; -@@ -233,6 +235,8 @@ key_type_is_ecdsa_variant(int type) +@@ -340,6 +344,8 @@ key_type_is_ecdsa_variant(int type) case KEY_ECDSA_CERT: case KEY_ECDSA_SK: case KEY_ECDSA_SK_CERT: @@ -1254,25 +1418,7 @@ index b0c2189..51f8e51 100644 return 1; } return 0; -@@ -342,6 +346,8 @@ sshkey_size(const struct sshkey *k) - case KEY_ECDSA_CERT: - case KEY_ECDSA_SK: - case KEY_ECDSA_SK_CERT: -+ case KEY_SM2: -+ case KEY_SM2_CERT: - return sshkey_curve_nid_to_bits(k->ecdsa_nid); - #endif /* WITH_OPENSSL */ - case KEY_ED25519: -@@ -366,6 +372,8 @@ sshkey_type_is_valid_ca(int type) - case KEY_ED25519: - case KEY_ED25519_SK: - case KEY_XMSS: -+ case KEY_SM2: -+ case KEY_SM2_CERT: - return 1; - default: - return 0; -@@ -445,6 +453,8 @@ sshkey_type_plain(int type) +@@ -548,6 +554,8 @@ sshkey_type_plain(int type) return KEY_ED25519_SK; case KEY_XMSS_CERT: return KEY_XMSS; @@ -1281,7 +1427,16 @@ index b0c2189..51f8e51 100644 default: return type; } -@@ -540,6 +550,8 @@ sshkey_curve_name_to_nid(const char *name) +@@ -564,6 +572,8 @@ sshkey_type_certified(int type) + return KEY_DSA_CERT; + case KEY_ECDSA: + return KEY_ECDSA_CERT; ++ case KEY_SM2: ++ return KEY_SM2_CERT; + case KEY_ECDSA_SK: + return KEY_ECDSA_SK_CERT; + case KEY_ED25519: +@@ -670,6 +680,8 @@ sshkey_curve_name_to_nid(const char *name) else if (strcmp(name, "nistp521") == 0) return NID_secp521r1; # endif /* OPENSSL_HAS_NISTP521 */ @@ -1290,7 +1445,7 @@ index b0c2189..51f8e51 100644 else return -1; } -@@ -556,6 +568,8 @@ sshkey_curve_nid_to_bits(int nid) +@@ -686,6 +698,8 @@ sshkey_curve_nid_to_bits(int nid) case NID_secp521r1: return 521; # endif /* OPENSSL_HAS_NISTP521 */ @@ -1299,7 +1454,7 @@ index b0c2189..51f8e51 100644 default: return 0; } -@@ -590,6 +604,8 @@ sshkey_curve_nid_to_name(int nid) +@@ -720,6 +734,8 @@ sshkey_curve_nid_to_name(int nid) case NID_secp521r1: return "nistp521"; # endif /* OPENSSL_HAS_NISTP521 */ @@ -1308,195 +1463,7 @@ index b0c2189..51f8e51 100644 default: return NULL; } -@@ -695,6 +711,8 @@ sshkey_new(int type) - case KEY_ECDSA_CERT: - case KEY_ECDSA_SK: - case KEY_ECDSA_SK_CERT: -+ case KEY_SM2: -+ case KEY_SM2_CERT: - /* Cannot do anything until we know the group */ - break; - #endif /* WITH_OPENSSL */ -@@ -749,6 +767,8 @@ sshkey_free(struct sshkey *k) - /* FALLTHROUGH */ - case KEY_ECDSA: - case KEY_ECDSA_CERT: -+ case KEY_SM2: -+ case KEY_SM2_CERT: - EC_KEY_free(k->ecdsa); - k->ecdsa = NULL; - break; -@@ -858,6 +878,8 @@ sshkey_equal_public(const struct sshkey *a, const struct sshkey *b) - /* FALLTHROUGH */ - case KEY_ECDSA_CERT: - case KEY_ECDSA: -+ case KEY_SM2: -+ case KEY_SM2_CERT: - if (a->ecdsa == NULL || b->ecdsa == NULL || - EC_KEY_get0_public_key(a->ecdsa) == NULL || - EC_KEY_get0_public_key(b->ecdsa) == NULL) -@@ -933,6 +955,7 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, - #ifdef WITH_OPENSSL - case KEY_DSA_CERT: - case KEY_ECDSA_CERT: -+ case KEY_SM2_CERT: - case KEY_ECDSA_SK_CERT: - case KEY_RSA_CERT: - #endif /* WITH_OPENSSL */ -@@ -962,6 +985,7 @@ to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain, - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - case KEY_ECDSA_SK: -+ case KEY_SM2: - if (key->ecdsa == NULL) - return SSH_ERR_INVALID_ARGUMENT; - if ((ret = sshbuf_put_cstring(b, typename)) != 0 || -@@ -1436,6 +1460,8 @@ sshkey_read(struct sshkey *ret, char **cpp) - case KEY_DSA: - case KEY_ECDSA: - case KEY_ECDSA_SK: -+ case KEY_SM2: -+ case KEY_SM2_CERT: - case KEY_ED25519: - case KEY_ED25519_SK: - case KEY_DSA_CERT: -@@ -1535,6 +1561,7 @@ sshkey_read(struct sshkey *ret, char **cpp) - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: -+ case KEY_SM2: - EC_KEY_free(ret->ecdsa); - ret->ecdsa = k->ecdsa; - ret->ecdsa_nid = k->ecdsa_nid; -@@ -1795,7 +1822,7 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k) - } - - static int --ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) -+ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap, int sm2) - { - EC_KEY *private; - int ret = SSH_ERR_INTERNAL_ERROR; -@@ -1804,6 +1831,9 @@ ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) - return SSH_ERR_INVALID_ARGUMENT; - if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) - return SSH_ERR_KEY_LENGTH; -+ if (sm2 && bits == 256) { -+ *nid = NID_sm2; -+ } - *ecdsap = NULL; - if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; -@@ -1857,7 +1887,11 @@ sshkey_generate(int type, u_int bits, struct sshkey **keyp) - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: - ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid, -- &k->ecdsa); -+ &k->ecdsa, 0); -+ break; -+ case KEY_SM2: -+ ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid, -+ &k->ecdsa, 1); - break; - # endif /* OPENSSL_HAS_ECC */ - case KEY_RSA: -@@ -1993,6 +2027,8 @@ sshkey_from_private(const struct sshkey *k, struct sshkey **pkp) - case KEY_ECDSA_CERT: - case KEY_ECDSA_SK: - case KEY_ECDSA_SK_CERT: -+ case KEY_SM2: -+ case KEY_SM2_CERT: - n->ecdsa_nid = k->ecdsa_nid; - n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); - if (n->ecdsa == NULL) { -@@ -2548,6 +2584,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: -+ case KEY_SM2_CERT: - case KEY_ECDSA_SK_CERT: - /* Skip nonce */ - if (sshbuf_get_string_direct(b, NULL, NULL) != 0) { -@@ -2557,6 +2594,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, - /* FALLTHROUGH */ - case KEY_ECDSA: - case KEY_ECDSA_SK: -+ case KEY_SM2: - if ((key = sshkey_new(type)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; -@@ -2865,6 +2903,10 @@ sshkey_sign(struct sshkey *key, - case KEY_ECDSA: - r = ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat); - break; -+ case KEY_SM2: -+ case KEY_SM2_CERT: -+ r = ssh_sm2_sign(key, sigp, lenp, data, datalen, compat); -+ break; - # endif /* OPENSSL_HAS_ECC */ - case KEY_RSA_CERT: - case KEY_RSA: -@@ -2920,6 +2962,9 @@ sshkey_verify(const struct sshkey *key, - case KEY_ECDSA_CERT: - case KEY_ECDSA: - return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat); -+ case KEY_SM2: -+ case KEY_SM2_CERT: -+ return ssh_sm2_verify(key, sig, siglen, data, dlen, compat); - case KEY_ECDSA_SK_CERT: - case KEY_ECDSA_SK: - return ssh_ecdsa_sk_verify(key, sig, siglen, data, dlen, -@@ -2963,6 +3008,9 @@ sshkey_to_certified(struct sshkey *k) - case KEY_ECDSA: - newtype = KEY_ECDSA_CERT; - break; -+ case KEY_SM2: -+ newtype = KEY_SM2_CERT; -+ break; - case KEY_ECDSA_SK: - newtype = KEY_ECDSA_SK_CERT; - break; -@@ -3067,6 +3115,7 @@ sshkey_certify_custom(struct sshkey *k, struct sshkey *ca, const char *alg, - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: -+ case KEY_SM2_CERT: - case KEY_ECDSA_SK_CERT: - if ((ret = sshbuf_put_cstring(cert, - sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 || -@@ -3380,6 +3429,7 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: -+ case KEY_SM2: - if ((r = sshbuf_put_cstring(b, - sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 || - (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 || -@@ -3388,6 +3438,7 @@ sshkey_private_serialize_opt(struct sshkey *key, struct sshbuf *buf, - goto out; - break; - case KEY_ECDSA_CERT: -+ case KEY_SM2_CERT: - if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; -@@ -3605,6 +3656,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: -+ case KEY_SM2: - if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; -@@ -3624,6 +3676,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) - goto out; - /* FALLTHROUGH */ - case KEY_ECDSA_CERT: -+ case KEY_SM2_CERT: - if ((r = sshbuf_get_bignum2(buf, &exponent)) != 0) - goto out; - if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) { -@@ -4519,6 +4572,7 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, +@@ -3424,6 +3440,7 @@ sshkey_private_to_blob_pem_pkcs8(struct sshkey *key, struct sshbuf *buf, break; #ifdef OPENSSL_HAS_ECC case KEY_ECDSA: @@ -1504,7 +1471,7 @@ index b0c2189..51f8e51 100644 if (format == SSHKEY_PRIVATE_PEM) { success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa, cipher, passphrase, len, NULL, NULL); -@@ -4580,6 +4634,7 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, +@@ -3485,6 +3502,7 @@ sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob, #ifdef WITH_OPENSSL case KEY_DSA: case KEY_ECDSA: @@ -1512,7 +1479,7 @@ index b0c2189..51f8e51 100644 case KEY_RSA: break; /* see below */ #endif /* WITH_OPENSSL */ -@@ -4760,6 +4815,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, +@@ -3665,6 +3683,9 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk); prv->type = KEY_ECDSA; prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa); @@ -1523,18 +1490,10 @@ index b0c2189..51f8e51 100644 sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL || sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa), diff --git a/sshkey.h b/sshkey.h -index 43eef5e..3b84096 100644 +index 8d662d1..c8d2662 100644 --- a/sshkey.h +++ b/sshkey.h -@@ -31,6 +31,7 @@ - #ifdef WITH_OPENSSL - #include - #include -+#include - # ifdef OPENSSL_HAS_ECC - # include - # include -@@ -65,6 +66,8 @@ enum sshkey_types { +@@ -68,6 +68,8 @@ enum sshkey_types { KEY_DSA_CERT, KEY_ECDSA_CERT, KEY_ED25519_CERT, @@ -1543,19 +1502,6 @@ index 43eef5e..3b84096 100644 KEY_XMSS, KEY_XMSS_CERT, KEY_ECDSA_SK, -@@ -323,6 +326,12 @@ int ssh_xmss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - int ssh_xmss_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat); -+int ssh_sm2_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, -+ const u_char *data, size_t datalen, u_int compat); -+int ssh_sm2_verify(const struct sshkey *key, -+ const u_char *signature, size_t signaturelen, -+ const u_char *data, size_t datalen, u_int compat); -+ - #endif - - #if !defined(WITH_OPENSSL) -- 2.23.0 diff --git a/openssh-5.8p2-sigpipe.patch b/openssh-5.8p2-sigpipe.patch index 4147dcba40cd88ebc3f5baffc099c70a7a481727..554e346823032615b391193dcf42ab5da83929c9 100644 --- a/openssh-5.8p2-sigpipe.patch +++ b/openssh-5.8p2-sigpipe.patch @@ -1,4 +1,3 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-5.8p2-sigpipe.patch diff -up openssh-5.8p2/ssh-keyscan.c.sigpipe openssh-5.8p2/ssh-keyscan.c --- openssh-5.8p2/ssh-keyscan.c.sigpipe 2011-08-23 18:30:33.873025916 +0200 +++ openssh-5.8p2/ssh-keyscan.c 2011-08-23 18:32:24.574025362 +0200 diff --git a/openssh-6.6.1p1-log-in-chroot.patch b/openssh-6.6.1p1-log-in-chroot.patch index 9e626a5fc0c42aa807c0fdc0e5606258488a0c84..941c69499ae80bddd73d7904a244691d100dfca1 100644 --- a/openssh-6.6.1p1-log-in-chroot.patch +++ b/openssh-6.6.1p1-log-in-chroot.patch @@ -1,4 +1,3 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-6.6.1p1-log-in-chroot.patch diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c --- openssh-8.6p1/log.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 +++ openssh-8.6p1/log.c 2021-04-19 14:43:08.544843434 +0200 diff --git a/openssh-6.6p1-allow-ip-opts.patch b/openssh-6.6p1-allow-ip-opts.patch index 953d6133e925b55e1288da9d4d3a9bea36ce5b97..be8d3409e666cd893d3921a8186413bace4d5c6c 100644 --- a/openssh-6.6p1-allow-ip-opts.patch +++ b/openssh-6.6p1-allow-ip-opts.patch @@ -1,7 +1,7 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c --- openssh/sshd.c.ip-opts 2016-07-25 13:58:48.998507834 +0200 +++ openssh/sshd.c 2016-07-25 14:01:28.346469878 +0200 -@@ -1507,12 +1507,29 @@ check_ip_options(struct ssh *ssh) +@@ -1507,12 +1507,32 @@ check_ip_options(struct ssh *ssh) if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, &option_size) >= 0 && option_size != 0) { @@ -21,11 +21,14 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c + case 130: + case 133: + case 134: -+ i += opts[i + 1]; -+ break; ++ if (i + 1 < option_size && opts[i + 1] >= 2) { ++ i += opts[i + 1]; ++ break; ++ } ++ /* FALLTHROUGH */ + default: + /* Fail, fatally, if we detect either loose or strict -+ * source routing options. */ ++ * or incorrect source routing options. */ + text[0] = '\0'; + for (i = 0; i < option_size; i++) + snprintf(text + i*3, sizeof(text) - i*3, diff --git a/openssh-6.6p1-keycat.patch b/openssh-6.6p1-keycat.patch index 2e0318fae2e9e46b47d930032fb3c40baf3d1b1e..529b5089993a57b47f137e1790d238de7a0fbc2d 100644 --- a/openssh-6.6p1-keycat.patch +++ b/openssh-6.6p1-keycat.patch @@ -1,4 +1,3 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-6.6p1-keycat.patch diff -up openssh/misc.c.keycat openssh/misc.c --- openssh/misc.c.keycat 2015-06-24 10:57:50.158849606 +0200 +++ openssh/misc.c 2015-06-24 11:04:23.989868638 +0200 @@ -65,7 +64,7 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) +ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o -+ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS) $(CHANNELLIBS) ++ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) diff --git a/openssh-6.6p1-kuserok.patch b/openssh-6.6p1-kuserok.patch index 6f14a991b0aff5c966877ce2efdd436566a2a533..6e2c76afe4e1af82773cc5eb34359b7afb466ca8 100644 --- a/openssh-6.6p1-kuserok.patch +++ b/openssh-6.6p1-kuserok.patch @@ -91,7 +91,7 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c + * configuring krb5.conf or using a suitable plugin to meet the needs of the + * given environment. + * -+ * The Fedora and RHEL version of openssh contain two patches which modify the ++ * The openEuler version of openssh contain two patches which modify the + * access control behavior: + * - openssh-6.6p1-kuserok.patch + * - openssh-6.6p1-force_krb.patch @@ -106,8 +106,8 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c + * rejected. Nevertheless the patch ignores the fact that krb5_kuserok() does + * no only check .k5login but other sources as well and checking .k5login can + * be disabled for all applications in krb5.conf as well. With this new -+ * option KerberosUseKuserok set to 'no' (and this is the default for RHEL7 -+ * and Fedora 21) openssh can only use krb5_aname_to_localname() with the ++ * option KerberosUseKuserok set to 'no' (and this is the default for ++ * openEuler) openssh can only use krb5_aname_to_localname() with the + * restrictions mentioned above. + * + * openssh-6.6p1-force_krb.patch adds a ksu like behaviour to ssh, i.e. when @@ -196,11 +196,11 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c sPort, sHostKeyFile, sLoginGraceTime, sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, -- sKerberosGetAFSToken, sKerberosUniqueCCache, -+ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, - sPasswordAuthentication, - sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, +- sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication, ++ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication, + sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, @@ -478,12 +481,14 @@ static struct { { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index d13a22741a40cd0bb6c67a79616936753fa7940d..494f4c6a1a0cb956a83cedf2b83c45511546f99a 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -1,38 +1,7 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-6.7p1-coverity.patch - ---- - auth-krb5.c | 2 ++ - auth-options.c | 1 + - channels.c | 6 ++++-- - dns.c | 1 + - gss-genr.c | 3 ++- - kexgssc.c | 4 +++- - krl.c | 4 ++++ - loginrec.c | 4 ++++ - misc.c | 3 +++ - moduli.c | 1 + - monitor.c | 4 ++-- - monitor_wrap.c | 6 +++--- - openbsd-compat/bindresvport.c | 2 +- - openbsd-compat/bsd-pselect.c | 8 ++++---- - readconf.c | 1 + - scp.c | 4 ++-- - servconf.c | 5 +++-- - serverloop.c | 2 +- - session.c | 2 ++ - sftp.c | 3 ++- - ssh-agent.c | 5 +++-- - ssh-keygen.c | 7 +++++++ - ssh.c | 1 + - sshd.c | 9 +++++++-- - sshsig.c | 1 + - 25 files changed, 65 insertions(+), 24 deletions(-) - -diff --git a/auth-krb5.c b/auth-krb5.c -index d80c3ab..71ea1e3 100644 ---- a/auth-krb5.c -+++ b/auth-krb5.c -@@ -426,6 +426,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm +diff -up openssh-8.5p1/auth-krb5.c.coverity openssh-8.5p1/auth-krb5.c +--- openssh-8.5p1/auth-krb5.c.coverity 2021-03-24 12:03:33.724967756 +0100 ++++ openssh-8.5p1/auth-krb5.c 2021-03-24 12:03:33.782968159 +0100 +@@ -426,6 +426,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, umask(old_umask); if (tmpfd == -1) { logit("mkstemp(): %.100s", strerror(oerrno)); @@ -40,7 +9,7 @@ index d80c3ab..71ea1e3 100644 return oerrno; } -@@ -433,6 +434,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm +@@ -433,6 +434,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, oerrno = errno; logit("fchmod(): %.100s", strerror(oerrno)); close(tmpfd); @@ -48,11 +17,10 @@ index d80c3ab..71ea1e3 100644 return oerrno; } /* make sure the KRB5CCNAME is set for non-standard location */ -diff --git a/auth-options.c b/auth-options.c -index 7cb2a64..a4b1db4 100644 ---- a/auth-options.c -+++ b/auth-options.c -@@ -723,6 +723,7 @@ serialise_array(struct sshbuf *m, char **a, size_t n) +diff -up openssh-8.5p1/auth-options.c.coverity openssh-8.5p1/auth-options.c +--- openssh-8.5p1/auth-options.c.coverity 2021-03-02 11:31:47.000000000 +0100 ++++ openssh-8.5p1/auth-options.c 2021-03-24 12:03:33.782968159 +0100 +@@ -706,6 +708,7 @@ serialise_array(struct sshbuf *m, char * return r; } /* success */ @@ -60,54 +28,10 @@ index 7cb2a64..a4b1db4 100644 return 0; } -diff --git a/channels.c b/channels.c -index 300c753..ea4d8da 100644 ---- a/channels.c -+++ b/channels.c -@@ -4081,7 +4081,7 @@ int - channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) - { - int r, success = 0, idx = -1; -- char *host_to_connect, *listen_host, *listen_path; -+ char *host_to_connect = NULL, *listen_host = NULL, *listen_path = NULL; - int port_to_connect, listen_port; - - /* Send the forward request to the remote side. */ -@@ -4109,7 +4109,6 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) - success = 1; - if (success) { - /* Record that connection to this host/port is permitted. */ -- host_to_connect = listen_host = listen_path = NULL; - port_to_connect = listen_port = 0; - if (fwd->connect_path != NULL) { - host_to_connect = xstrdup(fwd->connect_path); -@@ -4130,6 +4129,9 @@ channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) - host_to_connect, port_to_connect, - listen_host, listen_path, listen_port, NULL); - } -+ free(host_to_connect); -+ free(listen_host); -+ free(listen_path); - return idx; - } - -diff --git a/dns.c b/dns.c -index f2310be..15218f1 100644 ---- a/dns.c -+++ b/dns.c -@@ -259,6 +259,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, - &hostkey_digest, &hostkey_digest_len, hostkey)) { - error("Error calculating key fingerprint."); - freerrset(fingerprints); -+ free(dnskey_digest); - return -1; - } - -diff --git a/gss-genr.c b/gss-genr.c -index 9f9745b..810b382 100644 ---- a/gss-genr.c -+++ b/gss-genr.c -@@ -168,8 +168,9 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, +diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c +--- openssh-8.5p1/gss-genr.c.coverity 2021-03-26 11:52:46.613942552 +0100 ++++ openssh-8.5p1/gss-genr.c 2021-03-26 11:54:37.881726318 +0100 +@@ -167,8 +167,9 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup enclen = __b64_ntop(digest, ssh_digest_bytes(SSH_DIGEST_MD5), encoded, ssh_digest_bytes(SSH_DIGEST_MD5) * 2); @@ -118,10 +42,9 @@ index 9f9745b..810b382 100644 for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (sshbuf_len(buf) != 0 && -diff --git a/kexgssc.c b/kexgssc.c -index 1c62740..080cf04 100644 ---- a/kexgssc.c -+++ b/kexgssc.c +diff -up openssh-8.5p1/kexgssc.c.coverity openssh-8.5p1/kexgssc.c +--- openssh-8.5p1/kexgssc.c.coverity 2021-03-24 12:03:33.711967665 +0100 ++++ openssh-8.5p1/kexgssc.c 2021-03-24 12:03:33.783968166 +0100 @@ -98,8 +98,10 @@ kexgss_client(struct ssh *ssh) default: fatal_f("Unexpected KEX type %d", kex->kex_type); @@ -134,11 +57,10 @@ index 1c62740..080cf04 100644 token_ptr = GSS_C_NO_BUFFER; -diff --git a/krl.c b/krl.c -index 473a9d7..ae19762 100644 ---- a/krl.c -+++ b/krl.c -@@ -1209,6 +1209,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp, +diff -up openssh-8.5p1/krl.c.coverity openssh-8.5p1/krl.c +--- openssh-8.5p1/krl.c.coverity 2021-03-02 11:31:47.000000000 +0100 ++++ openssh-8.5p1/krl.c 2021-03-24 12:03:33.783968166 +0100 +@@ -1209,6 +1209,7 @@ ssh_krl_from_blob(struct sshbuf *buf, st sshkey_free(key); sshbuf_free(copy); sshbuf_free(sect); @@ -146,7 +68,7 @@ index 473a9d7..ae19762 100644 return r; } -@@ -1261,6 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) +@@ -1261,6 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, cons return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); free(rb.blob); @@ -154,7 +76,7 @@ index 473a9d7..ae19762 100644 if (erb != NULL) { KRL_DBG(("revoked by key SHA1")); return SSH_ERR_KEY_REVOKED; -@@ -1271,6 +1273,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) +@@ -1271,6 +1273,7 @@ is_key_revoked(struct ssh_krl *krl, cons return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb); free(rb.blob); @@ -162,7 +84,7 @@ index 473a9d7..ae19762 100644 if (erb != NULL) { KRL_DBG(("revoked by key SHA256")); return SSH_ERR_KEY_REVOKED; -@@ -1282,6 +1285,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) +@@ -1282,6 +1285,7 @@ is_key_revoked(struct ssh_krl *krl, cons return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); free(rb.blob); @@ -170,11 +92,10 @@ index 473a9d7..ae19762 100644 if (erb != NULL) { KRL_DBG(("revoked by explicit key")); return SSH_ERR_KEY_REVOKED; -diff --git a/loginrec.c b/loginrec.c -index 4f21499..e0606be 100644 ---- a/loginrec.c -+++ b/loginrec.c -@@ -691,9 +691,11 @@ construct_utmp(struct logininfo *li, +diff -up openssh-8.5p1/loginrec.c.coverity openssh-8.5p1/loginrec.c +--- openssh-8.5p1/loginrec.c.coverity 2021-03-24 13:18:53.793225885 +0100 ++++ openssh-8.5p1/loginrec.c 2021-03-24 13:21:27.948404751 +0100 +@@ -690,9 +690,11 @@ construct_utmp(struct logininfo *li, */ /* Use strncpy because we don't necessarily want null termination */ @@ -186,7 +107,7 @@ index 4f21499..e0606be 100644 strncpy(ut->ut_host, li->hostname, MIN_SIZEOF(ut->ut_host, li->hostname)); # endif -@@ -1691,6 +1693,7 @@ record_failed_login(struct ssh *ssh, const char *username, const char *hostname, +@@ -1690,6 +1692,7 @@ record_failed_login(struct ssh *ssh, con memset(&ut, 0, sizeof(ut)); /* strncpy because we don't necessarily want nul termination */ @@ -194,7 +115,7 @@ index 4f21499..e0606be 100644 strncpy(ut.ut_user, username, sizeof(ut.ut_user)); strlcpy(ut.ut_line, "ssh:notty", sizeof(ut.ut_line)); -@@ -1700,6 +1703,7 @@ record_failed_login(struct ssh *ssh, const char *username, const char *hostname, +@@ -1699,6 +1702,7 @@ record_failed_login(struct ssh *ssh, con ut.ut_pid = getpid(); /* strncpy because we don't necessarily want nul termination */ @@ -202,11 +123,10 @@ index 4f21499..e0606be 100644 strncpy(ut.ut_host, hostname, sizeof(ut.ut_host)); if (ssh_packet_connection_is_on_socket(ssh) && -diff --git a/misc.c b/misc.c -index e4d3120..5420e24 100644 ---- a/misc.c -+++ b/misc.c -@@ -1492,6 +1492,8 @@ sanitise_stdfd(void) +diff -up openssh-8.5p1/misc.c.coverity openssh-8.5p1/misc.c +--- openssh-8.5p1/misc.c.coverity 2021-03-24 12:03:33.745967902 +0100 ++++ openssh-8.5p1/misc.c 2021-03-24 13:31:47.037079617 +0100 +@@ -1425,6 +1425,8 @@ sanitise_stdfd(void) } if (nullfd > STDERR_FILENO) close(nullfd); @@ -215,7 +135,7 @@ index e4d3120..5420e24 100644 } char * -@@ -2625,6 +2627,7 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) +@@ -2511,6 +2513,7 @@ stdfd_devnull(int do_stdin, int do_stdou } if (devnull > STDERR_FILENO) close(devnull); @@ -223,23 +143,10 @@ index e4d3120..5420e24 100644 return ret; } -diff --git a/moduli.c b/moduli.c -index 9f660ef..2669edd 100644 ---- a/moduli.c -+++ b/moduli.c -@@ -476,6 +476,7 @@ write_checkpoint(char *cpfile, u_int32_t lineno) - else - logit("failed to write to checkpoint file '%s': %s", cpfile, - strerror(errno)); -+ /* coverity[leaked_storage : FALSE] */ - } - - static unsigned long -diff --git a/monitor.c b/monitor.c -index fc05db6..dca2fe7 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -397,7 +397,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) +diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c +--- openssh-7.4p1/monitor.c.coverity 2016-12-23 16:40:26.888788688 +0100 ++++ openssh-7.4p1/monitor.c 2016-12-23 16:40:26.900788691 +0100 +@@ -411,7 +411,7 @@ monitor_child_preauth(Authctxt *_authctx mm_get_keystate(ssh, pmonitor); /* Drain any buffered messages from the child */ @@ -248,7 +155,7 @@ index fc05db6..dca2fe7 100644 ; if (pmonitor->m_recvfd >= 0) -@@ -1684,7 +1684,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1678,7 +1678,7 @@ mm_answer_pty(struct ssh *ssh, int sock, s->ptymaster = s->ptyfd; debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd); @@ -257,11 +164,10 @@ index fc05db6..dca2fe7 100644 return (0); error: -diff --git a/monitor_wrap.c b/monitor_wrap.c -index e125eca..c394d68 100644 ---- a/monitor_wrap.c -+++ b/monitor_wrap.c -@@ -612,10 +612,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen) +diff -up openssh-7.4p1/monitor_wrap.c.coverity openssh-7.4p1/monitor_wrap.c +--- openssh-7.4p1/monitor_wrap.c.coverity 2016-12-23 16:40:26.892788689 +0100 ++++ openssh-7.4p1/monitor_wrap.c 2016-12-23 16:40:26.900788691 +0100 +@@ -525,10 +525,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd, if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 || (tmp2 = dup(pmonitor->m_recvfd)) == -1) { error_f("cannot allocate fds for pty"); @@ -275,11 +181,10 @@ index e125eca..c394d68 100644 return 0; } close(tmp1); -diff --git a/openbsd-compat/bindresvport.c b/openbsd-compat/bindresvport.c -index 346c7fe..f42792f 100644 ---- a/openbsd-compat/bindresvport.c -+++ b/openbsd-compat/bindresvport.c -@@ -59,7 +59,7 @@ bindresvport_sa(int sd, struct sockaddr *sa) +diff -up openssh-7.4p1/openbsd-compat/bindresvport.c.coverity openssh-7.4p1/openbsd-compat/bindresvport.c +--- openssh-7.4p1/openbsd-compat/bindresvport.c.coverity 2016-12-19 05:59:41.000000000 +0100 ++++ openssh-7.4p1/openbsd-compat/bindresvport.c 2016-12-23 16:40:26.901788691 +0100 +@@ -58,7 +58,7 @@ bindresvport_sa(int sd, struct sockaddr struct sockaddr_in6 *in6; u_int16_t *portp; u_int16_t port; @@ -288,10 +193,9 @@ index 346c7fe..f42792f 100644 int i; if (sa == NULL) { -diff --git a/openbsd-compat/bsd-pselect.c b/openbsd-compat/bsd-pselect.c -index b363208..cf7157c 100644 ---- a/openbsd-compat/bsd-pselect.c -+++ b/openbsd-compat/bsd-pselect.c +diff -up openssh-8.7p1/openbsd-compat/bsd-pselect.c.coverity openssh-8.7p1/openbsd-compat/bsd-pselect.c +--- openssh-8.7p1/openbsd-compat/bsd-pselect.c.coverity 2021-08-30 16:36:11.357288009 +0200 ++++ openssh-8.7p1/openbsd-compat/bsd-pselect.c 2021-08-30 16:37:21.791897976 +0200 @@ -113,13 +113,13 @@ pselect_notify_setup(void) static void pselect_notify_parent(void) @@ -319,11 +223,10 @@ index b363208..cf7157c 100644 debug2_f("reading"); FD_CLR(notify_pipe[0], readset); } -diff --git a/readconf.c b/readconf.c -index 1e1b78d..b6c998e 100644 ---- a/readconf.c -+++ b/readconf.c -@@ -1933,6 +1933,7 @@ parse_pubkey_algos: +diff -up openssh-8.5p1/readconf.c.coverity openssh-8.5p1/readconf.c +--- openssh-8.5p1/readconf.c.coverity 2021-03-24 12:03:33.778968131 +0100 ++++ openssh-8.5p1/readconf.c 2021-03-24 12:03:33.785968180 +0100 +@@ -1847,6 +1847,7 @@ parse_pubkey_algos: } else if (r != 0) { error("%.200s line %d: glob failed for %s.", filename, linenum, arg2); @@ -331,11 +234,10 @@ index 1e1b78d..b6c998e 100644 goto out; } free(arg2); -diff --git a/scp.c b/scp.c -index 6146260..74f5b10 100644 ---- a/scp.c -+++ b/scp.c -@@ -187,11 +187,11 @@ killchild(int signo) +diff -up openssh-8.7p1/scp.c.coverity openssh-8.7p1/scp.c +--- openssh-8.7p1/scp.c.coverity 2021-08-30 16:23:35.389741329 +0200 ++++ openssh-8.7p1/scp.c 2021-08-30 16:27:04.854555296 +0200 +@@ -186,11 +186,11 @@ killchild(int signo) { if (do_cmd_pid > 1) { kill(do_cmd_pid, signo ? signo : SIGTERM); @@ -349,11 +251,10 @@ index 6146260..74f5b10 100644 } if (signo) -diff --git a/servconf.c b/servconf.c -index 8b9540d..d72fb62 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -2081,8 +2081,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, +diff -up openssh-7.4p1/servconf.c.coverity openssh-7.4p1/servconf.c +--- openssh-7.4p1/servconf.c.coverity 2016-12-23 16:40:26.896788690 +0100 ++++ openssh-7.4p1/servconf.c 2016-12-23 16:40:26.901788691 +0100 +@@ -1638,8 +1638,9 @@ process_server_config_line(ServerOptions if (*activep && *charptr == NULL) { *charptr = tilde_expand_filename(arg, getuid()); /* increase optional counter */ @@ -365,11 +266,10 @@ index 8b9540d..d72fb62 100644 } break; -diff --git a/serverloop.c b/serverloop.c -index b4c0d82..62c7e90 100644 ---- a/serverloop.c -+++ b/serverloop.c -@@ -546,7 +546,7 @@ server_request_tun(struct ssh *ssh) +diff -up openssh-8.7p1/serverloop.c.coverity openssh-8.7p1/serverloop.c +--- openssh-8.7p1/serverloop.c.coverity 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/serverloop.c 2021-08-30 16:28:22.416226981 +0200 +@@ -547,7 +547,7 @@ server_request_tun(struct ssh *ssh) debug_f("invalid tun"); goto done; } @@ -378,30 +278,10 @@ index b4c0d82..62c7e90 100644 if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != (int)tun) goto done; -diff --git a/session.c b/session.c -index 58cf557..cdb301b 100644 ---- a/session.c -+++ b/session.c -@@ -1222,12 +1222,14 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) - /* Environment specified by admin */ - for (i = 0; i < options.num_setenv; i++) { - cp = xstrdup(options.setenv[i]); -+ /* coverity[overwrite_var : FALSE] */ - if ((value = strchr(cp, '=')) == NULL) { - /* shouldn't happen; vars are checked in servconf.c */ - fatal("Invalid config SetEnv: %s", options.setenv[i]); - } - *value++ = '\0'; - child_set_env(&env, &envsize, cp, value); -+ free(cp); - } - - /* SSH_CLIENT deprecated */ -diff --git a/sftp.c b/sftp.c -index c3c347e..c18a354 100644 ---- a/sftp.c -+++ b/sftp.c -@@ -226,7 +226,7 @@ killchild(int signo) +diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c +--- openssh-7.4p1/sftp.c.coverity 2016-12-19 05:59:41.000000000 +0100 ++++ openssh-7.4p1/sftp.c 2016-12-23 16:40:26.903788691 +0100 +@@ -224,7 +224,7 @@ killchild(int signo) pid = sshpid; if (pid > 1) { kill(pid, SIGTERM); @@ -410,19 +290,10 @@ index c3c347e..c18a354 100644 } _exit(1); -@@ -1029,6 +1029,7 @@ do_globbed_ls(struct sftp_conn *conn, const char *path, - if (lflag & LS_LONG_VIEW) { - if (g.gl_statv[i] == NULL) { - error("no stat information for %s", fname); -+ free(fname); - continue; - } - lname = ls_file(fname, g.gl_statv[i], 1, -diff --git a/ssh-agent.c b/ssh-agent.c -index 50d0638..a292a9e 100644 ---- a/ssh-agent.c -+++ b/ssh-agent.c -@@ -1391,6 +1391,7 @@ sanitize_pkcs11_provider(const char *provider) +diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c +--- openssh-7.4p1/ssh-agent.c.coverity 2016-12-19 05:59:41.000000000 +0100 ++++ openssh-7.4p1/ssh-agent.c 2016-12-23 16:40:26.903788691 +0100 +@@ -869,6 +869,7 @@ sanitize_pkcs11_provider(const char *pro if (pkcs11_uri_parse(provider, uri) != 0) { error("Failed to parse PKCS#11 URI"); @@ -430,7 +301,7 @@ index 50d0638..a292a9e 100644 return NULL; } /* validate also provider from URI */ -@@ -2080,8 +2081,8 @@ main(int ac, char **av) +@@ -1220,8 +1220,8 @@ main(int ac, char **av) sanitise_stdfd(); /* drop */ @@ -441,43 +312,10 @@ index 50d0638..a292a9e 100644 platform_disable_tracing(0); /* strict=no */ -diff --git a/ssh-keygen.c b/ssh-keygen.c -index 6ae72ab..076dd33 100644 ---- a/ssh-keygen.c -+++ b/ssh-keygen.c -@@ -2365,6 +2365,9 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, - r = ssh_krl_revoke_key_sha256(krl, blob, blen); - if (r != 0) - fatal_fr(r, "revoke key failed"); -+ freezero(blob, blen); -+ blob = NULL; -+ blen = 0; - } else { - if (strncasecmp(cp, "key:", 4) == 0) { - cp += 4; -@@ -3023,6 +3026,7 @@ do_moduli_screen(const char *out_file, char **opts, size_t nopts) - } else if (strncmp(opts[i], "start-line=", 11) == 0) { - start_lineno = strtoul(opts[i]+11, NULL, 10); - } else if (strncmp(opts[i], "checkpoint=", 11) == 0) { -+ free(checkpoint); - checkpoint = xstrdup(opts[i]+11); - } else if (strncmp(opts[i], "generator=", 10) == 0) { - generator_wanted = (u_int32_t)strtonum( -@@ -3064,6 +3068,9 @@ do_moduli_screen(const char *out_file, char **opts, size_t nopts) - #else /* WITH_OPENSSL */ - fatal("Moduli screening is not supported"); - #endif /* WITH_OPENSSL */ -+ free(checkpoint); -+ if (in != stdin) -+ fclose(in); - } - - /* Read and confirm a passphrase */ -diff --git a/ssh.c b/ssh.c -index a5155f4..68558d4 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -1755,6 +1755,7 @@ control_persist_detach(void) +diff -up openssh-8.5p1/ssh.c.coverity openssh-8.5p1/ssh.c +--- openssh-8.5p1/ssh.c.coverity 2021-03-24 12:03:33.779968138 +0100 ++++ openssh-8.5p1/ssh.c 2021-03-24 12:03:33.786968187 +0100 +@@ -1746,6 +1746,7 @@ control_persist_detach(void) close(muxserver_sock); muxserver_sock = -1; options.control_master = SSHCTL_MASTER_NO; @@ -485,11 +323,10 @@ index a5155f4..68558d4 100644 muxclient(options.control_path); /* muxclient() doesn't return on success. */ fatal("Failed to connect to new control master"); -diff --git a/sshd.c b/sshd.c -index e05dd82..a4a1b79 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -595,8 +595,10 @@ privsep_preauth(struct ssh *ssh) +diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c +--- openssh-7.4p1/sshd.c.coverity 2016-12-23 16:40:26.897788690 +0100 ++++ openssh-7.4p1/sshd.c 2016-12-23 16:40:26.904788692 +0100 +@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt) privsep_preauth_child(ssh); setproctitle("%s", "[net]"); @@ -501,7 +338,7 @@ index e05dd82..a4a1b79 100644 return 0; } -@@ -2560,8 +2562,11 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2519,8 +2524,11 @@ do_ssh2_kex(struct ssh *ssh) if (newstr) myproposal[PROPOSAL_KEX_ALGS] = newstr; @@ -514,18 +351,16 @@ index e05dd82..a4a1b79 100644 } #endif -diff --git a/sshsig.c b/sshsig.c -index eb2a931..3e91c14 100644 ---- a/sshsig.c -+++ b/sshsig.c -@@ -551,6 +551,7 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp) - oerrno = errno; - sshbuf_free(b); - ssh_digest_free(ctx); -+ ctx = NULL; - explicit_bzero(hash, sizeof(hash)); - errno = oerrno; - return r; --- -2.27.0 - +diff -up openssh-8.5p1/ssh-keygen.c.coverity openssh-8.5p1/ssh-keygen.c +--- openssh-8.5p1/ssh-keygen.c.coverity 2021-03-24 12:03:33.780968145 +0100 ++++ openssh-8.5p1/ssh-keygen.c 2021-03-24 12:03:33.787968194 +0100 +@@ -2332,6 +2332,9 @@ update_krl_from_file(struct passwd *pw, + r = ssh_krl_revoke_key_sha256(krl, blob, blen); + if (r != 0) + fatal_fr(r, "revoke key failed"); ++ freezero(blob, blen); ++ blob = NULL; ++ blen = 0; + } else { + if (strncasecmp(cp, "key:", 4) == 0) { + cp += 4; diff --git a/openssh-7.3p1-x11-max-displays.patch b/openssh-7.3p1-x11-max-displays.patch index f2b331eabf02957870aae6b0a7d1933cf8d6fc31..2b702d416c44f2ccefdc1784793654ed48b32e41 100644 --- a/openssh-7.3p1-x11-max-displays.patch +++ b/openssh-7.3p1-x11-max-displays.patch @@ -1,19 +1,7 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-7.3p1-x11-max-displays.patch - ---- - channels.c | 23 ++++++++++++++--------- - channels.h | 2 +- - servconf.c | 12 +++++++++++- - servconf.h | 2 ++ - session.c | 5 +++-- - sshd_config.5 | 7 +++++++ - 6 files changed, 38 insertions(+), 13 deletions(-) - -diff --git a/channels.c b/channels.c -index 7230540..040a4c6 100644 ---- a/channels.c -+++ b/channels.c -@@ -101,8 +101,8 @@ +diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c +--- openssh-7.4p1/channels.c.x11max 2016-12-23 15:46:32.071506625 +0100 ++++ openssh-7.4p1/channels.c 2016-12-23 15:46:32.139506636 +0100 +@@ -152,8 +152,8 @@ static int all_opens_permitted = 0; #define FWD_PERMIT_ANY_HOST "*" /* -- X11 forwarding */ @@ -24,7 +12,7 @@ index 7230540..040a4c6 100644 /* Per-channel callback for pre/post IO actions */ typedef void chan_fn(struct ssh *, Channel *c); -@@ -4801,7 +4801,7 @@ rdynamic_connect_finish(struct ssh *ssh, Channel *c) +@@ -4228,7 +4228,7 @@ channel_send_window_changes(void) */ int x11_create_display_inet(struct ssh *ssh, int x11_display_offset, @@ -33,7 +21,7 @@ index 7230540..040a4c6 100644 u_int *display_numberp, int **chanids) { Channel *nc = NULL; -@@ -4814,10 +4814,15 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, +@@ -4240,10 +4241,15 @@ x11_create_display_inet(int x11_display_ if (chanids == NULL) return -1; @@ -51,7 +39,7 @@ index 7230540..040a4c6 100644 memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; -@@ -4870,7 +4875,7 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, +@@ -4295,7 +4301,7 @@ x11_create_display_inet(int x11_display_ if (num_socks > 0) break; } @@ -60,7 +48,7 @@ index 7230540..040a4c6 100644 error("Failed to allocate internet-domain X11 display socket."); return -1; } -@@ -5054,7 +5059,7 @@ x11_connect_display(struct ssh *ssh) +@@ -4441,7 +4447,7 @@ x11_connect_display(void) memset(&hints, 0, sizeof(hints)); hints.ai_family = ssh->chanctxt->IPv4or6; hints.ai_socktype = SOCK_STREAM; @@ -69,7 +57,7 @@ index 7230540..040a4c6 100644 if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { error("%.100s: unknown host. (%s)", buf, ssh_gai_strerror(gaierr)); -@@ -5070,7 +5075,7 @@ x11_connect_display(struct ssh *ssh) +@@ -4457,7 +4463,7 @@ x11_connect_display(void) /* Connect it to the display. */ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { debug2("connect %.100s port %u: %.100s", buf, @@ -78,33 +66,33 @@ index 7230540..040a4c6 100644 close(sock); continue; } -@@ -5080,7 +5085,7 @@ x11_connect_display(struct ssh *ssh) +@@ -4466,8 +4472,8 @@ x11_connect_display(void) + } freeaddrinfo(aitop); if (!ai) { - error("connect %.100s port %u: %.100s", buf, +- error("connect %.100s port %u: %.100s", buf, - 6000 + display_number, strerror(errno)); ++ error("connect %.100s port %u: %.100s", buf, + X11_PORT_MIN + display_number, strerror(errno)); return -1; } set_nodelay(sock); -diff --git a/channels.h b/channels.h -index 828c1b6..7d8a83e 100644 ---- a/channels.h -+++ b/channels.h -@@ -361,7 +361,7 @@ int permitopen_port(const char *); +diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h +--- openssh-7.4p1/channels.h.x11max 2016-12-19 05:59:41.000000000 +0100 ++++ openssh-7.4p1/channels.h 2016-12-23 15:46:32.139506636 +0100 +@@ -293,7 +293,7 @@ int permitopen_port(const char *); - void channel_set_x11_refuse_time(struct ssh *, u_int); + void channel_set_x11_refuse_time(struct ssh *, time_t); int x11_connect_display(struct ssh *); -int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **); +int x11_create_display_inet(struct ssh *, int, int, int, int, u_int *, int **); void x11_request_forwarding_with_spoofing(struct ssh *, int, const char *, const char *, const char *, int); -diff --git a/servconf.c b/servconf.c -index 13c4a08..fdba127 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -115,6 +115,7 @@ initialize_server_options(ServerOptions *options) +diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c +--- openssh-7.4p1/servconf.c.x11max 2016-12-23 15:46:32.133506635 +0100 ++++ openssh-7.4p1/servconf.c 2016-12-23 15:47:27.320519121 +0100 +@@ -95,6 +95,7 @@ initialize_server_options(ServerOptions options->print_lastlog = -1; options->x11_forwarding = -1; options->x11_display_offset = -1; @@ -112,7 +100,7 @@ index 13c4a08..fdba127 100644 options->x11_use_localhost = -1; options->permit_tty = -1; options->permit_user_rc = -1; -@@ -330,6 +331,8 @@ fill_default_server_options(ServerOptions *options) +@@ -243,6 +244,8 @@ fill_default_server_options(ServerOption options->x11_forwarding = 0; if (options->x11_display_offset == -1) options->x11_display_offset = 10; @@ -121,16 +109,16 @@ index 13c4a08..fdba127 100644 if (options->x11_use_localhost == -1) options->x11_use_localhost = 1; if (options->xauth_location == NULL) -@@ -518,7 +521,7 @@ typedef enum { - sPasswordAuthentication, - sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, +@@ -419,7 +422,7 @@ typedef enum { + sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication, + sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, + sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost, sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, sPermitUserEnvironment, sAllowTcpForwarding, sCompression, sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, -@@ -652,6 +655,7 @@ static struct { +@@ -540,6 +543,7 @@ static struct { { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, @@ -138,7 +126,7 @@ index 13c4a08..fdba127 100644 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, -@@ -1680,6 +1684,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1316,6 +1320,10 @@ process_server_config_line(ServerOptions *intptr = value; break; @@ -149,7 +137,7 @@ index 13c4a08..fdba127 100644 case sX11UseLocalhost: intptr = &options->x11_use_localhost; goto parse_flag; -@@ -2678,6 +2686,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) +@@ -2063,6 +2071,7 @@ copy_set_server_options(ServerOptions *d M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); M_CP_INTOPT(x11_display_offset); M_CP_INTOPT(x11_forwarding); @@ -157,7 +145,7 @@ index 13c4a08..fdba127 100644 M_CP_INTOPT(x11_use_localhost); M_CP_INTOPT(permit_tty); M_CP_INTOPT(permit_user_rc); -@@ -2953,6 +2962,7 @@ dump_config(ServerOptions *o) +@@ -2315,6 +2324,7 @@ dump_config(ServerOptions *o) #endif dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); @@ -165,11 +153,10 @@ index 13c4a08..fdba127 100644 dump_cfg_int(sMaxAuthTries, o->max_authtries); dump_cfg_int(sMaxSessions, o->max_sessions); dump_cfg_int(sClientAliveInterval, o->client_alive_interval); -diff --git a/servconf.h b/servconf.h -index 37d3a6f..77fd779 100644 ---- a/servconf.h -+++ b/servconf.h -@@ -45,6 +45,7 @@ +diff -up openssh-7.4p1/servconf.h.x11max openssh-7.4p1/servconf.h +--- openssh-7.4p1/servconf.h.x11max 2016-12-23 15:46:32.133506635 +0100 ++++ openssh-7.4p1/servconf.h 2016-12-23 15:46:32.140506636 +0100 +@@ -55,6 +55,7 @@ #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ @@ -177,7 +164,7 @@ index 37d3a6f..77fd779 100644 /* Magic name for internal sftp-server */ #define INTERNAL_SFTP_NAME "internal-sftp" -@@ -105,6 +106,7 @@ typedef struct { +@@ -85,6 +86,7 @@ typedef struct { int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ int x11_display_offset; /* What DISPLAY number to start * searching at */ @@ -185,14 +172,13 @@ index 37d3a6f..77fd779 100644 int x11_use_localhost; /* If true, use localhost for fake X11 server. */ char *xauth_location; /* Location of xauth program */ int permit_tty; /* If false, deny pty allocation */ -diff --git a/session.c b/session.c -index 6040d51..dd7d148 100644 ---- a/session.c -+++ b/session.c -@@ -2612,8 +2612,9 @@ session_setup_x11fwd(struct ssh *ssh, Session *s) +diff -up openssh-7.4p1/session.c.x11max openssh-7.4p1/session.c +--- openssh-7.4p1/session.c.x11max 2016-12-23 15:46:32.136506636 +0100 ++++ openssh-7.4p1/session.c 2016-12-23 15:46:32.141506636 +0100 +@@ -2518,8 +2518,9 @@ session_setup_x11fwd(Session *s) return 0; } - if (x11_create_display_inet(ssh, options.x11_display_offset, + if (x11_create_display_inet(ssh, options.x11_display_offset, - options.x11_use_localhost, s->single_connection, - &s->display_number, &s->x11_chanids) == -1) { + options.x11_use_localhost, options.x11_max_displays, @@ -201,19 +187,18 @@ index 6040d51..dd7d148 100644 debug("x11_create_display_inet failed."); return 0; } -diff --git a/sshd_config.5 b/sshd_config.5 -index 4396b93..440fe92 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -1280,6 +1280,7 @@ Available keywords are - .Cm StreamLocalBindUnlink , +diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5 +--- openssh-7.4p1/sshd_config.5.x11max 2016-12-23 15:46:32.134506635 +0100 ++++ openssh-7.4p1/sshd_config.5 2016-12-23 15:46:32.141506636 +0100 +@@ -1133,6 +1133,7 @@ Available keywords are .Cm TrustedUserCAKeys , + .Cm UnusedConnectionTimeout , .Cm X11DisplayOffset , +.Cm X11MaxDisplays , .Cm X11Forwarding and .Cm X11UseLocalhost . -@@ -1847,6 +1848,12 @@ Specifies the first display number available for +@@ -1566,6 +1567,12 @@ Specifies the first display number avail X11 forwarding. This prevents sshd from interfering with real X11 servers. The default is 10. @@ -226,6 +211,3 @@ index 4396b93..440fe92 100644 .It Cm X11Forwarding Specifies whether X11 forwarding is permitted. The argument must be --- -2.27.0 - diff --git a/openssh-7.4p1-systemd.patch b/openssh-7.4p1-systemd.patch index 3ed0333491809613f8db4d6de2218bbb485d0cc5..1242aac8d4647dd097be70d150f67bfd8cd2fec5 100644 --- a/openssh-7.4p1-systemd.patch +++ b/openssh-7.4p1-systemd.patch @@ -1,17 +1,14 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-7.4p1-systemd.patch +commit 0e22b79bfde45a7cf7a2e51a68ec11c4285f3b31 +Author: Jakub Jelen +Date: Mon Nov 21 15:04:06 2016 +0100 ---- - configure.ac | 24 ++++++++++++++++++++++++ - contrib/sshd.service | 16 ++++++++++++++++ - sshd.c | 9 +++++++++ - 3 files changed, 49 insertions(+) - create mode 100644 contrib/sshd.service + systemd stuff diff --git a/configure.ac b/configure.ac -index bbe133e..6f7dc48 100644 +index 2ffc369..162ce92 100644 --- a/configure.ac +++ b/configure.ac -@@ -4822,6 +4822,29 @@ AC_SUBST([GSSLIBS]) +@@ -4265,6 +4265,30 @@ AC_ARG_WITH([kerberos5], AC_SUBST([K5LIBS]) AC_SUBST([CHANNELLIBS]) @@ -37,11 +34,12 @@ index bbe133e..6f7dc48 100644 + fi + fi ] +) ++ + # Looking for programs, paths and files PRIVSEP_PATH=/var/empty -@@ -5621,6 +5644,7 @@ echo " libldns support: $LDNS_MSG" +@@ -5097,6 +5121,7 @@ echo " libedit support: $LIBEDIT_MSG" echo " Solaris process contract support: $SPC_MSG" echo " Solaris project support: $SP_MSG" echo " Solaris privilege support: $SPP_MSG" @@ -72,10 +70,10 @@ index 0000000..e0d4923 +WantedBy=multi-user.target + diff --git a/sshd.c b/sshd.c -index 0d4cfef..2a9b96d 100644 +index 816611c..b8b9d13 100644 --- a/sshd.c +++ b/sshd.c -@@ -88,6 +88,10 @@ +@@ -85,6 +85,10 @@ #include #endif @@ -86,7 +84,7 @@ index 0d4cfef..2a9b96d 100644 #include "xmalloc.h" #include "ssh.h" #include "ssh2.h" -@@ -2121,6 +2125,11 @@ main(int ac, char **av) +@@ -1888,6 +1892,11 @@ main(int ac, char **av) } } @@ -98,6 +96,3 @@ index 0d4cfef..2a9b96d 100644 /* Accept a connection and return in a forked child */ server_accept_loop(&sock_in, &sock_out, &newsock, config_s); --- -2.27.0 - diff --git a/openssh-7.5p1-sandbox.patch b/openssh-7.5p1-sandbox.patch index 7217c6419144681ee08064f1d606708d1087c6b1..90640a02490027f7d3b52da4c33d39ac47718fc9 100644 --- a/openssh-7.5p1-sandbox.patch +++ b/openssh-7.5p1-sandbox.patch @@ -21,7 +21,7 @@ index ca75cc7..6e7de31 100644 + SC_ALLOW(__NR_flock), +#endif #ifdef __NR_futex - SC_ALLOW(__NR_futex), + SC_FUTEX(__NR_futex), #endif @@ -178,6 +181,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_gettimeofday diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index 68629742e88acc3975d265cfd3335640c4c71533..748c4b608e5808f30d1775976ddf7c988d963351 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -1,55 +1,7 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-7.6p1-audit.patch - ---- - Makefile.in | 2 +- - audit-bsm.c | 45 ++++++- - audit-linux.c | 301 +++++++++++++++++++++++++++++++++++++++++++--- - audit.c | 129 ++++++++++++++++++-- - audit.h | 22 +++- - auditstub.c | 52 ++++++++ - auth.c | 3 - - auth.h | 5 + - auth2-hostbased.c | 16 ++- - auth2-pubkey.c | 16 ++- - auth2.c | 3 - - cipher.c | 21 +--- - cipher.h | 20 ++- - kex.c | 61 ++++++++-- - kex.h | 2 + - mac.c | 14 +++ - mac.h | 1 + - monitor.c | 194 ++++++++++++++++++++++++++++-- - monitor.h | 8 +- - monitor_wrap.c | 130 +++++++++++++++++++- - monitor_wrap.h | 11 +- - packet.c | 98 +++++++++++++-- - packet.h | 1 + - session.c | 84 +++++++++++-- - session.h | 10 +- - sshd.c | 103 +++++++++++++--- - sshkey.c | 32 +++++ - sshkey.h | 1 + - 28 files changed, 1274 insertions(+), 111 deletions(-) - create mode 100644 auditstub.c - -diff --git a/Makefile.in b/Makefile.in -index 45f7a93..9b4c06b 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -114,7 +114,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kexsntrup761x25519.o sntrup761.o kexgen.o \ - kexgssc.o \ - sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ -- sshbuf-io.o -+ sshbuf-io.o auditstub.o - - SKOBJS= ssh-sk-client.o - -diff --git a/audit-bsm.c b/audit-bsm.c -index ccfcf6f..a49abb9 100644 ---- a/audit-bsm.c -+++ b/audit-bsm.c -@@ -373,12 +373,25 @@ audit_connection_from(const char *host, int port) +diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c +--- openssh-8.6p1/audit-bsm.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/audit-bsm.c 2021-04-19 16:47:35.753062106 +0200 +@@ -373,13 +373,26 @@ audit_connection_from(const char *host, #endif } @@ -67,16 +19,17 @@ index ccfcf6f..a49abb9 100644 /* not implemented */ } -+void + void +audit_count_session_open(void) +{ + /* not necessary */ +} + - void ++void audit_session_open(struct logininfo *li) { -@@ -391,6 +404,12 @@ audit_session_close(struct logininfo *li) + /* not implemented */ +@@ -391,6 +404,12 @@ audit_session_close(struct logininfo *li /* not implemented */ } @@ -89,7 +42,7 @@ index ccfcf6f..a49abb9 100644 void audit_event(struct ssh *ssh, ssh_audit_event_t event) { -@@ -452,4 +471,28 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) +@@ -452,4 +471,28 @@ audit_event(struct ssh *ssh, ssh_audit_e debug("%s: unhandled event %d", __func__, event); } } @@ -118,10 +71,234 @@ index ccfcf6f..a49abb9 100644 + /* not implemented */ +} #endif /* BSM */ -diff --git a/audit-linux.c b/audit-linux.c -index 3fcbe5c..a823c30 100644 ---- a/audit-linux.c -+++ b/audit-linux.c +diff -up openssh-8.6p1/audit.c.audit openssh-8.6p1/audit.c +--- openssh-8.6p1/audit.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/audit.c 2021-04-19 16:47:35.753062106 +0200 +@@ -34,6 +34,12 @@ + #include "log.h" + #include "hostfile.h" + #include "auth.h" ++#include "ssh-gss.h" ++#include "monitor_wrap.h" ++#include "xmalloc.h" ++#include "misc.h" ++#include "servconf.h" ++#include "ssherr.h" + + /* + * Care must be taken when using this since it WILL NOT be initialized when +@@ -41,6 +47,7 @@ + * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using. + */ + extern Authctxt *the_authctxt; ++extern ServerOptions options; + + /* Maybe add the audit class to struct Authmethod? */ + ssh_audit_event_t +@@ -69,13 +76,10 @@ audit_classify_auth(const char *method) + const char * + audit_username(void) + { +- static const char unknownuser[] = "(unknown user)"; +- static const char invaliduser[] = "(invalid user)"; ++ static const char unknownuser[] = "(unknown)"; + +- if (the_authctxt == NULL || the_authctxt->user == NULL) ++ if (the_authctxt == NULL || the_authctxt->user == NULL || !the_authctxt->valid) + return (unknownuser); +- if (!the_authctxt->valid) +- return (invaliduser); + return (the_authctxt->user); + } + +@@ -109,6 +113,35 @@ audit_event_lookup(ssh_audit_event_t ev) + return(event_lookup[i].name); + } + ++void ++audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key) ++{ ++ char *fp; ++ ++ fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); ++ if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0) ++ *rv = -SSH_ERR_INTERNAL_ERROR; ++ free(fp); ++} ++ ++void ++audit_unsupported(struct ssh *ssh, int what) ++{ ++ PRIVSEP(audit_unsupported_body(ssh, what)); ++} ++ ++void ++audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) ++{ ++ PRIVSEP(audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid())); ++} ++ ++void ++audit_session_key_free(struct ssh *ssh, int ctos) ++{ ++ PRIVSEP(audit_session_key_free_body(ssh, ctos, getpid(), getuid())); ++} ++ + # ifndef CUSTOM_SSH_AUDIT_EVENTS + /* + * Null implementations of audit functions. +@@ -138,6 +171,17 @@ audit_event(struct ssh *ssh, ssh_audit_e + } + + /* ++ * Called when a child process has called, or will soon call, ++ * audit_session_open. ++ */ ++void ++audit_count_session_open(void) ++{ ++ debug("audit count session open euid %d user %s", geteuid(), ++ audit_username()); ++} ++ ++/* + * Called when a user session is started. Argument is the tty allocated to + * the session, or NULL if no tty was allocated. + * +@@ -172,13 +216,82 @@ audit_session_close(struct logininfo *li + /* + * This will be called when a user runs a non-interactive command. Note that + * it may be called multiple times for a single connection since SSH2 allows +- * multiple sessions within a single connection. ++ * multiple sessions within a single connection. Returns a "handle" for ++ * audit_end_command. + */ +-void +-audit_run_command(const char *command) ++int ++audit_run_command(struct ssh *ssh, const char *command) + { + debug("audit run command euid %d user %s command '%.200s'", geteuid(), + audit_username(), command); ++ return 0; ++} ++ ++/* ++ * This will be called when the non-interactive command finishes. Note that ++ * it may be called multiple times for a single connection since SSH2 allows ++ * multiple sessions within a single connection. "handle" should come from ++ * the corresponding audit_run_command. ++ */ ++void ++audit_end_command(struct ssh *ssh, int handle, const char *command) ++{ ++ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(), ++ audit_username(), command); ++} ++ ++/* ++ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. ++ * ++ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. ++ */ ++int ++audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) ++{ ++ debug("audit %s key usage euid %d user %s fingerprint %s, result %d", ++ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), ++ fp, rv); ++} ++ ++/* ++ * This will be called when the protocol negotiation fails. ++ */ ++void ++audit_unsupported_body(struct ssh *ssh, int what) ++{ ++ debug("audit unsupported protocol euid %d type %d", geteuid(), what); ++} ++ ++/* ++ * This will be called on succesfull protocol negotiation. ++ */ ++void ++audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, ++ uid_t uid) ++{ ++ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u", ++ (unsigned)geteuid(), ctos, enc, mac, compress, pfs, (long)pid, ++ (unsigned)uid); ++} ++ ++/* ++ * This will be called on succesfull session key discard ++ */ ++void ++audit_session_key_free_body(struct ssh *, int ctos, pid_t pid, uid_t uid) ++{ ++ debug("audit session key discard euid %u direction %d from pid %ld uid %u", ++ (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid); ++} ++ ++/* ++ * This will be called on destroy private part of the server key ++ */ ++void ++audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) ++{ ++ debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u", ++ geteuid(), fp, (long)pid, (unsigned)uid); + } + # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ + #endif /* SSH_AUDIT_EVENTS */ +diff -up openssh-8.6p1/audit.h.audit openssh-8.6p1/audit.h +--- openssh-8.6p1/audit.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/audit.h 2021-04-19 16:47:35.753062106 +0200 +@@ -26,6 +26,7 @@ + # define _SSH_AUDIT_H + + #include "loginrec.h" ++#include "sshkey.h" + + struct ssh; + +@@ -45,13 +46,32 @@ enum ssh_audit_event_type { + SSH_CONNECTION_ABANDON, /* closed without completing auth */ + SSH_AUDIT_UNKNOWN + }; ++ ++enum ssh_audit_kex { ++ SSH_AUDIT_UNSUPPORTED_CIPHER, ++ SSH_AUDIT_UNSUPPORTED_MAC, ++ SSH_AUDIT_UNSUPPORTED_COMPRESSION ++}; + typedef enum ssh_audit_event_type ssh_audit_event_t; + ++int listening_for_clients(void); ++ + void audit_connection_from(const char *, int); + void audit_event(struct ssh *, ssh_audit_event_t); ++void audit_count_session_open(void); + void audit_session_open(struct logininfo *); + void audit_session_close(struct logininfo *); +-void audit_run_command(const char *); ++int audit_run_command(struct ssh *, const char *); ++void audit_end_command(struct ssh *, int, const char *); + ssh_audit_event_t audit_classify_auth(const char *); ++int audit_keyusage(struct ssh *, int, char *, int); ++void audit_key(struct ssh *, int, int *, const struct sshkey *); ++void audit_unsupported(struct ssh *, int); ++void audit_kex(struct ssh *, int, char *, char *, char *, char *); ++void audit_unsupported_body(struct ssh *, int); ++void audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t); ++void audit_session_key_free(struct ssh *, int ctos); ++void audit_session_key_free_body(struct ssh *, int ctos, pid_t, uid_t); ++void audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); + + #endif /* _SSH_AUDIT_H */ +diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c +--- openssh-8.6p1/audit-linux.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/audit-linux.c 2021-04-19 16:47:35.753062106 +0200 @@ -33,27 +33,40 @@ #include "log.h" @@ -133,10 +310,11 @@ index 3fcbe5c..a823c30 100644 +#include "servconf.h" #include "canohost.h" #include "packet.h" +- +#include "cipher.h" +#include "channels.h" +#include "session.h" - ++ +#define AUDIT_LOG_SIZE 256 + +extern ServerOptions options; @@ -170,7 +348,7 @@ index 3fcbe5c..a823c30 100644 saved_errno = errno; close(audit_fd); -@@ -65,9 +78,96 @@ linux_audit_record_event(int uid, const char *username, const char *hostname, +@@ -65,9 +78,96 @@ linux_audit_record_event(int uid, const rc = 0; errno = saved_errno; @@ -268,7 +446,7 @@ index 3fcbe5c..a823c30 100644 /* Below is the sshd audit API code */ void -@@ -76,49 +176,210 @@ audit_connection_from(const char *host, int port) +@@ -76,49 +176,210 @@ audit_connection_from(const char *host, /* not implemented */ } @@ -358,371 +536,142 @@ index 3fcbe5c..a823c30 100644 + + case SSH_CONNECTION_CLOSE: + if (user_login_count) { -+ while (user_login_count--) -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ ssh_remote_ipaddr(ssh), -+ "ssh", 1, AUDIT_USER_END); -+ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ ssh_remote_ipaddr(ssh), -+ "ssh", 1, AUDIT_USER_LOGOUT); -+ } -+ break; -+ -+ case SSH_CONNECTION_ABANDON: - case SSH_INVALID_USER: -- linux_audit_record_event(-1, audit_username(), NULL, -- ssh_remote_ipaddr(ssh), "sshd", 0); -+ linux_audit_user_logxxx(-1, audit_username(), -+ ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); - break; - default: - debug("%s: unhandled event %d", __func__, event); - break; - } - } -+ -+void -+audit_unsupported_body(struct ssh *ssh, int what) -+{ -+#ifdef AUDIT_CRYPTO_SESSION -+ char buf[AUDIT_LOG_SIZE]; -+ const static char *name[] = { "cipher", "mac", "comp" }; -+ char *s; -+ int audit_fd; -+ -+ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", -+ name[what], ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), -+ ssh_local_port(ssh)); -+ free(s); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) -+ /* no problem, the next instruction will be fatal() */ -+ return; -+ audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, -+ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 0); -+ audit_close(audit_fd); -+#endif -+} -+ -+const static char *direction[] = { "from-server", "from-client", "both" }; -+ -+void -+audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, -+ char *pfs, pid_t pid, uid_t uid) -+{ -+#ifdef AUDIT_CRYPTO_SESSION -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ const struct sshcipher *cipher = cipher_by_name(enc); -+ char *s; -+ -+ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s pfs=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", -+ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, pfs, -+ (intmax_t)pid, (intmax_t)uid, -+ ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ssh_local_port(ssh)); -+ free(s); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno == EINVAL || errno == EPROTONOSUPPORT || -+ errno == EAFNOSUPPORT) -+ return; /* No audit support in kernel */ -+ else -+ fatal("cannot open audit"); /* Must prevent login */ -+ } -+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, -+ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ fatal("cannot write into audit"); /* Must prevent login */ -+#endif -+} -+ -+void -+audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ char *s; -+ -+ snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", -+ direction[ctos], (intmax_t)pid, (intmax_t)uid, -+ ssh_remote_port(ssh), -+ (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), -+ ssh_local_port(ssh)); -+ free(s); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno != EINVAL && errno != EPROTONOSUPPORT && -+ errno != EAFNOSUPPORT) -+ error("cannot open audit"); -+ return; -+ } -+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, -+ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ error("cannot write into audit"); -+} -+ -+void -+audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) -+{ -+ char buf[AUDIT_LOG_SIZE]; -+ int audit_fd, audit_ok; -+ -+ snprintf(buf, sizeof(buf), "op=destroy kind=server fp=%s direction=? spid=%jd suid=%jd ", -+ fp, (intmax_t)pid, (intmax_t)uid); -+ audit_fd = audit_open(); -+ if (audit_fd < 0) { -+ if (errno != EINVAL && errno != EPROTONOSUPPORT && -+ errno != EAFNOSUPPORT) -+ error("cannot open audit"); -+ return; -+ } -+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, -+ buf, NULL, -+ listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh), -+ NULL, 1); -+ audit_close(audit_fd); -+ /* do not abort if the error is EPERM and sshd is run as non root user */ -+ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) -+ error("cannot write into audit"); -+} - #endif /* USE_LINUX_AUDIT */ -diff --git a/audit.c b/audit.c -index dd2f035..c8d54b1 100644 ---- a/audit.c -+++ b/audit.c -@@ -34,6 +34,12 @@ - #include "log.h" - #include "hostfile.h" - #include "auth.h" -+#include "ssh-gss.h" -+#include "monitor_wrap.h" -+#include "xmalloc.h" -+#include "misc.h" -+#include "servconf.h" -+#include "ssherr.h" - - /* - * Care must be taken when using this since it WILL NOT be initialized when -@@ -41,6 +47,7 @@ - * audit_event(CONNECTION_ABANDON) is called. Test for NULL before using. - */ - extern Authctxt *the_authctxt; -+extern ServerOptions options; - - /* Maybe add the audit class to struct Authmethod? */ - ssh_audit_event_t -@@ -69,13 +76,10 @@ audit_classify_auth(const char *method) - const char * - audit_username(void) - { -- static const char unknownuser[] = "(unknown user)"; -- static const char invaliduser[] = "(invalid user)"; -+ static const char unknownuser[] = "(unknown)"; - -- if (the_authctxt == NULL || the_authctxt->user == NULL) -+ if (the_authctxt == NULL || the_authctxt->user == NULL || !the_authctxt->valid) - return (unknownuser); -- if (!the_authctxt->valid) -- return (invaliduser); - return (the_authctxt->user); - } - -@@ -109,6 +113,35 @@ audit_event_lookup(ssh_audit_event_t ev) - return(event_lookup[i].name); - } - -+void -+audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key) -+{ -+ char *fp; -+ -+ fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); -+ if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0) -+ *rv = -SSH_ERR_INTERNAL_ERROR; -+ free(fp); -+} -+ -+void -+audit_unsupported(struct ssh *ssh, int what) -+{ -+ PRIVSEP(audit_unsupported_body(ssh, what)); -+} -+ -+void -+audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) -+{ -+ PRIVSEP(audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid())); -+} -+ -+void -+audit_session_key_free(struct ssh *ssh, int ctos) -+{ -+ PRIVSEP(audit_session_key_free_body(ssh, ctos, getpid(), getuid())); -+} -+ - # ifndef CUSTOM_SSH_AUDIT_EVENTS - /* - * Null implementations of audit functions. -@@ -137,6 +170,17 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) - audit_username(), event, audit_event_lookup(event)); - } - -+/* -+ * Called when a child process has called, or will soon call, -+ * audit_session_open. -+ */ -+void -+audit_count_session_open(void) -+{ -+ debug("audit count session open euid %d user %s", geteuid(), -+ audit_username()); -+} -+ - /* - * Called when a user session is started. Argument is the tty allocated to - * the session, or NULL if no tty was allocated. -@@ -172,13 +216,82 @@ audit_session_close(struct logininfo *li) - /* - * This will be called when a user runs a non-interactive command. Note that - * it may be called multiple times for a single connection since SSH2 allows -- * multiple sessions within a single connection. -+ * multiple sessions within a single connection. Returns a "handle" for -+ * audit_end_command. - */ --void --audit_run_command(const char *command) -+int -+audit_run_command(struct ssh *ssh, const char *command) - { - debug("audit run command euid %d user %s command '%.200s'", geteuid(), - audit_username(), command); -+ return 0; -+} -+ -+/* -+ * This will be called when the non-interactive command finishes. Note that -+ * it may be called multiple times for a single connection since SSH2 allows -+ * multiple sessions within a single connection. "handle" should come from -+ * the corresponding audit_run_command. -+ */ -+void -+audit_end_command(struct ssh *ssh, int handle, const char *command) -+{ -+ debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(), -+ audit_username(), command); -+} -+ -+/* -+ * This will be called when user is successfully autherized by the RSA1/RSA/DSA key. -+ * -+ * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. -+ */ -+int -+audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) -+{ -+ debug("audit %s key usage euid %d user %s fingerprint %s, result %d", -+ host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), -+ fp, rv); -+} ++ while (user_login_count--) ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ ssh_remote_ipaddr(ssh), ++ "ssh", 1, AUDIT_USER_END); ++ linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ ssh_remote_ipaddr(ssh), ++ "ssh", 1, AUDIT_USER_LOGOUT); ++ } ++ break; ++ ++ case SSH_CONNECTION_ABANDON: + case SSH_INVALID_USER: +- linux_audit_record_event(-1, audit_username(), NULL, +- ssh_remote_ipaddr(ssh), "sshd", 0); ++ linux_audit_user_logxxx(-1, audit_username(), ++ ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + default: + debug("%s: unhandled event %d", __func__, event); + break; + } + } + -+/* -+ * This will be called when the protocol negotiation fails. -+ */ +void +audit_unsupported_body(struct ssh *ssh, int what) +{ -+ debug("audit unsupported protocol euid %d type %d", geteuid(), what); ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ const static char *name[] = { "cipher", "mac", "comp" }; ++ char *s; ++ int audit_fd; ++ ++ snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", ++ name[what], ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ++ ssh_local_port(ssh)); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) ++ /* no problem, the next instruction will be fatal() */ ++ return; ++ audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 0); ++ audit_close(audit_fd); ++#endif +} + -+/* -+ * This will be called on succesfull protocol negotiation. -+ */ ++const static char *direction[] = { "from-server", "from-client", "both" }; ++ +void -+audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, -+ uid_t uid) ++audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, ++ char *pfs, pid_t pid, uid_t uid) +{ -+ debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u", -+ (unsigned)geteuid(), ctos, enc, mac, compress, pfs, (long)pid, -+ (unsigned)uid); ++#ifdef AUDIT_CRYPTO_SESSION ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ const struct sshcipher *cipher = cipher_by_name(enc); ++ char *s; ++ ++ snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s pfs=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", ++ direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, pfs, ++ (intmax_t)pid, (intmax_t)uid, ++ ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ssh_local_port(ssh)); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno == EINVAL || errno == EPROTONOSUPPORT || ++ errno == EAFNOSUPPORT) ++ return; /* No audit support in kernel */ ++ else ++ fatal("cannot open audit"); /* Must prevent login */ ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ fatal("cannot write into audit"); /* Must prevent login */ ++#endif +} + -+/* -+ * This will be called on succesfull session key discard -+ */ +void -+audit_session_key_free_body(struct ssh *, int ctos, pid_t pid, uid_t uid) ++audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) +{ -+ debug("audit session key discard euid %u direction %d from pid %ld uid %u", -+ (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid); ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; ++ char *s; ++ ++ snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", ++ direction[ctos], (intmax_t)pid, (intmax_t)uid, ++ ssh_remote_port(ssh), ++ (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ++ ssh_local_port(ssh)); ++ free(s); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); +} + -+/* -+ * This will be called on destroy private part of the server key -+ */ +void +audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) +{ -+ debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u", -+ geteuid(), fp, (long)pid, (unsigned)uid); - } - # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ - #endif /* SSH_AUDIT_EVENTS */ -diff --git a/audit.h b/audit.h -index 38cb5ad..45d66cc 100644 ---- a/audit.h -+++ b/audit.h -@@ -26,6 +26,7 @@ - # define _SSH_AUDIT_H - - #include "loginrec.h" -+#include "sshkey.h" - - struct ssh; - -@@ -45,13 +46,32 @@ enum ssh_audit_event_type { - SSH_CONNECTION_ABANDON, /* closed without completing auth */ - SSH_AUDIT_UNKNOWN - }; -+ -+enum ssh_audit_kex { -+ SSH_AUDIT_UNSUPPORTED_CIPHER, -+ SSH_AUDIT_UNSUPPORTED_MAC, -+ SSH_AUDIT_UNSUPPORTED_COMPRESSION -+}; - typedef enum ssh_audit_event_type ssh_audit_event_t; - -+int listening_for_clients(void); ++ char buf[AUDIT_LOG_SIZE]; ++ int audit_fd, audit_ok; + - void audit_connection_from(const char *, int); - void audit_event(struct ssh *, ssh_audit_event_t); -+void audit_count_session_open(void); - void audit_session_open(struct logininfo *); - void audit_session_close(struct logininfo *); --void audit_run_command(const char *); -+int audit_run_command(struct ssh *, const char *); -+void audit_end_command(struct ssh *, int, const char *); - ssh_audit_event_t audit_classify_auth(const char *); -+int audit_keyusage(struct ssh *, int, char *, int); -+void audit_key(struct ssh *, int, int *, const struct sshkey *); -+void audit_unsupported(struct ssh *, int); -+void audit_kex(struct ssh *, int, char *, char *, char *, char *); -+void audit_unsupported_body(struct ssh *, int); -+void audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t); -+void audit_session_key_free(struct ssh *, int ctos); -+void audit_session_key_free_body(struct ssh *, int ctos, pid_t, uid_t); -+void audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); - - #endif /* _SSH_AUDIT_H */ -diff --git a/auditstub.c b/auditstub.c -new file mode 100644 -index 0000000..639a798 ---- /dev/null -+++ b/auditstub.c ++ snprintf(buf, sizeof(buf), "op=destroy kind=server fp=%s direction=? spid=%jd suid=%jd ", ++ fp, (intmax_t)pid, (intmax_t)uid); ++ audit_fd = audit_open(); ++ if (audit_fd < 0) { ++ if (errno != EINVAL && errno != EPROTONOSUPPORT && ++ errno != EAFNOSUPPORT) ++ error("cannot open audit"); ++ return; ++ } ++ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, ++ buf, NULL, ++ listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh), ++ NULL, 1); ++ audit_close(audit_fd); ++ /* do not abort if the error is EPERM and sshd is run as non root user */ ++ if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) ++ error("cannot write into audit"); ++} + #endif /* USE_LINUX_AUDIT */ +diff -up openssh-8.6p1/auditstub.c.audit openssh-8.6p1/auditstub.c +--- openssh-8.6p1/auditstub.c.audit 2021-04-19 16:47:35.754062114 +0200 ++++ openssh-8.6p1/auditstub.c 2021-04-19 16:47:35.754062114 +0200 @@ -0,0 +1,52 @@ +/* $Id: auditstub.c,v 1.1 jfch Exp $ */ + @@ -776,48 +725,23 @@ index 0000000..639a798 +audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) +{ +} -diff --git a/auth.c b/auth.c -index a449f27..1a477f8 100644 ---- a/auth.c -+++ b/auth.c -@@ -499,9 +499,6 @@ getpwnamallow(struct ssh *ssh, const char *user) - record_failed_login(ssh, user, - auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); - #endif +diff -up openssh-8.6p1/auth2.c.audit openssh-8.6p1/auth2.c +--- openssh-8.6p1/auth2.c.audit 2021-04-19 16:47:35.682061561 +0200 ++++ openssh-8.6p1/auth2.c 2021-04-19 16:47:35.754062114 +0200 +@@ -298,9 +298,6 @@ input_userauth_request(int type, u_int32 + authctxt->valid = 0; + /* Invalid user, fake password information */ + authctxt->pw = fakepw(); -#ifdef SSH_AUDIT_EVENTS -- audit_event(ssh, SSH_INVALID_USER); --#endif /* SSH_AUDIT_EVENTS */ - return (NULL); - } - if (!allowed_user(ssh, pw)) -diff --git a/auth.h b/auth.h -index fe32bee..6500eab 100644 ---- a/auth.h -+++ b/auth.h -@@ -197,6 +197,9 @@ struct passwd * getpwnamallow(struct ssh *, const char *user); - char *expand_authorized_keys(const char *, struct passwd *pw); - char *authorized_principals_file(struct passwd *); - -+int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); -+ - int auth_key_is_revoked(struct sshkey *); - - const char *auth_get_canonical_hostname(struct ssh *, int); -@@ -213,6 +216,8 @@ struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *); - int get_hostkey_index(struct sshkey *, int, struct ssh *); - int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *, - u_char **, size_t *, const u_char *, size_t, const char *); -+int hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); - - /* Key / cert options linkage to auth layer */ - const struct sshauthopt *auth_options(struct ssh *); -diff --git a/auth2-hostbased.c b/auth2-hostbased.c -index 0ac78d3..ee38cdb 100644 ---- a/auth2-hostbased.c -+++ b/auth2-hostbased.c -@@ -163,7 +163,7 @@ userauth_hostbased(struct ssh *ssh, const char *method) +- PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); +-#endif + } + #ifdef USE_PAM + if (options.use_pam) +diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c +--- openssh-8.6p1/auth2-hostbased.c.audit 2021-04-19 16:47:35.656061361 +0200 ++++ openssh-8.6p1/auth2-hostbased.c 2021-04-19 16:47:35.754062114 +0200 +@@ -158,7 +158,7 @@ userauth_hostbased(struct ssh *ssh) authenticated = 0; if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser, chost, key)) && @@ -826,7 +750,7 @@ index 0ac78d3..ee38cdb 100644 sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0) authenticated = 1; -@@ -180,6 +180,20 @@ done: +@@ -175,6 +175,20 @@ done: return authenticated; } @@ -847,11 +771,10 @@ index 0ac78d3..ee38cdb 100644 /* return 1 if given hostkey is allowed */ int hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, -diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index 95165b8..06f8155 100644 ---- a/auth2-pubkey.c -+++ b/auth2-pubkey.c -@@ -236,7 +236,7 @@ userauth_pubkey(struct ssh *ssh, const char *method) +diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c +--- openssh-8.6p1/auth2-pubkey.c.audit 2021-04-19 16:47:35.726061899 +0200 ++++ openssh-8.6p1/auth2-pubkey.c 2021-04-19 16:47:35.754062114 +0200 +@@ -213,7 +213,7 @@ userauth_pubkey(struct ssh *ssh) /* test for correct signature */ authenticated = 0; if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) && @@ -860,7 +783,7 @@ index 95165b8..06f8155 100644 sshbuf_ptr(b), sshbuf_len(b), (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, ssh->compat, &sig_details)) == 0) { -@@ -329,6 +329,20 @@ done: +@@ -305,6 +305,20 @@ done: return authenticated; } @@ -881,24 +804,43 @@ index 95165b8..06f8155 100644 static int match_principals_file(struct passwd *pw, char *file, struct sshkey_cert *cert, struct sshauthopt **authoptsp) -diff --git a/auth2.c b/auth2.c -index 7510c25..203ba01 100644 ---- a/auth2.c -+++ b/auth2.c -@@ -302,9 +302,6 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) - authctxt->valid = 0; - /* Invalid user, fake password information */ - authctxt->pw = fakepw(); +diff -up openssh-8.6p1/auth.c.audit openssh-8.6p1/auth.c +--- openssh-8.6p1/auth.c.audit 2021-04-19 16:47:35.681061553 +0200 ++++ openssh-8.6p1/auth.c 2021-04-19 16:47:35.754062114 +0200 +@@ -597,9 +597,6 @@ getpwnamallow(struct ssh *ssh, const cha + record_failed_login(ssh, user, + auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); + #endif -#ifdef SSH_AUDIT_EVENTS -- PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); --#endif - } - #ifdef USE_PAM - if (options.use_pam) -diff --git a/cipher.c b/cipher.c -index 02aea40..609450d 100644 ---- a/cipher.c -+++ b/cipher.c +- audit_event(ssh, SSH_INVALID_USER); +-#endif /* SSH_AUDIT_EVENTS */ + return (NULL); + } + if (!allowed_user(ssh, pw)) +diff -up openssh-8.6p1/auth.h.audit openssh-8.6p1/auth.h +--- openssh-8.6p1/auth.h.audit 2021-04-19 16:47:35.697061676 +0200 ++++ openssh-8.6p1/auth.h 2021-04-19 16:47:35.754062114 +0200 +@@ -212,6 +214,8 @@ struct sshkey *get_hostkey_private_by_ty + int get_hostkey_index(struct sshkey *, int, struct ssh *); + int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); ++int hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); + + /* Key / cert options linkage to auth layer */ + const struct sshauthopt *auth_options(struct ssh *); +@@ -239,6 +241,8 @@ struct passwd * getpwnamallow(struct ssh + char *, const char *, const char *, const char *, struct sshauthopt **); + int auth_check_authkeys_file(struct passwd *, FILE *, char *, + struct sshkey *, const char *, const char *, struct sshauthopt **); ++int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); + FILE *auth_openkeyfile(const char *, struct passwd *, int); + FILE *auth_openprincipals(const char *, struct passwd *, int); + +diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c +--- openssh-8.6p1/cipher.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/cipher.c 2021-04-19 16:47:35.755062122 +0200 @@ -64,25 +64,6 @@ struct sshcipher_ctx { const struct sshcipher *cipher; }; @@ -925,7 +867,7 @@ index 02aea40..609450d 100644 static const struct sshcipher ciphers[] = { #ifdef WITH_OPENSSL #ifndef OPENSSL_NO_DES -@@ -420,7 +401,7 @@ cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, +@@ -422,7 +403,7 @@ cipher_get_length(struct sshcipher_ctx * void cipher_free(struct sshcipher_ctx *cc) { @@ -934,10 +876,9 @@ index 02aea40..609450d 100644 return; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { chachapoly_free(cc->cp_ctx); -diff --git a/cipher.h b/cipher.h -index 1a591cd..48980ed 100644 ---- a/cipher.h -+++ b/cipher.h +diff -up openssh-8.6p1/cipher.h.audit openssh-8.6p1/cipher.h +--- openssh-8.6p1/cipher.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/cipher.h 2021-04-19 16:47:35.755062122 +0200 @@ -47,7 +47,25 @@ #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 @@ -965,19 +906,18 @@ index 1a591cd..48980ed 100644 struct sshcipher_ctx; const struct sshcipher *cipher_by_name(const char *); -diff --git a/kex.c b/kex.c -index 050bece..14c7643 100644 ---- a/kex.c -+++ b/kex.c +diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c +--- openssh-8.6p1/kex.c.audit 2021-04-19 16:47:35.743062030 +0200 ++++ openssh-8.6p1/kex.c 2021-04-19 16:47:35.755062122 +0200 @@ -65,6 +65,7 @@ - #include "ssherr.h" #include "sshbuf.h" #include "digest.h" + #include "xmalloc.h" +#include "audit.h" #ifdef GSSAPI #include "ssh-gss.h" -@@ -836,12 +837,16 @@ kex_start_rekex(struct ssh *ssh) +@@ -816,12 +817,16 @@ kex_start_rekex(struct ssh *ssh) } static int @@ -996,7 +936,7 @@ index 050bece..14c7643 100644 if ((enc->cipher = cipher_by_name(name)) == NULL) { error_f("unsupported cipher %s", name); free(name); -@@ -862,8 +867,12 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) +@@ -842,8 +847,12 @@ choose_mac(struct ssh *ssh, struct sshma { char *name = match_list(client, server, NULL); @@ -1010,7 +950,7 @@ index 050bece..14c7643 100644 if (mac_setup(mac, name) < 0) { error_f("unsupported MAC %s", name); free(name); -@@ -876,12 +885,16 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) +@@ -856,12 +865,16 @@ choose_mac(struct ssh *ssh, struct sshma } static int @@ -1029,7 +969,7 @@ index 050bece..14c7643 100644 #ifdef WITH_ZLIB if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; -@@ -1044,7 +1057,7 @@ kex_choose_conf(struct ssh *ssh) +@@ -1002,7 +1015,7 @@ kex_choose_conf(struct ssh *ssh) nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; @@ -1038,7 +978,7 @@ index 050bece..14c7643 100644 sprop[nenc])) != 0) { kex->failed_choice = peer[nenc]; peer[nenc] = NULL; -@@ -1059,7 +1072,7 @@ kex_choose_conf(struct ssh *ssh) +@@ -1017,7 +1030,7 @@ kex_choose_conf(struct ssh *ssh) peer[nmac] = NULL; goto out; } @@ -1047,7 +987,7 @@ index 050bece..14c7643 100644 sprop[ncomp])) != 0) { kex->failed_choice = peer[ncomp]; peer[ncomp] = NULL; -@@ -1082,6 +1095,10 @@ kex_choose_conf(struct ssh *ssh) +@@ -1040,6 +1053,10 @@ kex_choose_conf(struct ssh *ssh) dh_need = MAXIMUM(dh_need, newkeys->enc.block_size); dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len); dh_need = MAXIMUM(dh_need, newkeys->mac.key_len); @@ -1058,7 +998,7 @@ index 050bece..14c7643 100644 } /* XXX need runden? */ kex->we_need = need; -@@ -1339,6 +1356,36 @@ dump_digest(const char *msg, const u_char *digest, int len) +@@ -1297,6 +1314,36 @@ dump_digest(const char *msg, const u_cha } #endif @@ -1095,11 +1035,10 @@ index 050bece..14c7643 100644 /* * Send a plaintext error message to the peer, suffixed by \r\n. * Only used during banner exchange, and there only for the server. -diff --git a/kex.h b/kex.h -index 240dca8..eed3fe0 100644 ---- a/kex.h -+++ b/kex.h -@@ -233,6 +233,8 @@ int kexgss_client(struct ssh *); +diff -up openssh-8.6p1/kex.h.audit openssh-8.6p1/kex.h +--- openssh-8.6p1/kex.h.audit 2021-04-19 16:47:35.683061568 +0200 ++++ openssh-8.6p1/kex.h 2021-04-19 16:47:35.756062129 +0200 +@@ -226,6 +226,8 @@ int kexgss_client(struct ssh *); int kexgss_server(struct ssh *); #endif @@ -1108,10 +1047,9 @@ index 240dca8..eed3fe0 100644 int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); -diff --git a/mac.c b/mac.c -index f3dda66..bf051ba 100644 ---- a/mac.c -+++ b/mac.c +diff -up openssh-8.6p1/mac.c.audit openssh-8.6p1/mac.c +--- openssh-8.6p1/mac.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/mac.c 2021-04-19 16:47:35.756062129 +0200 @@ -239,6 +239,20 @@ mac_clear(struct sshmac *mac) mac->umac_ctx = NULL; } @@ -1133,21 +1071,31 @@ index f3dda66..bf051ba 100644 /* XXX copied from ciphers_valid */ #define MAC_SEP "," int -diff --git a/mac.h b/mac.h -index 0b119d7..5fb593b 100644 ---- a/mac.h -+++ b/mac.h -@@ -49,5 +49,6 @@ int mac_compute(struct sshmac *, u_int32_t, const u_char *, int, +diff -up openssh-8.6p1/mac.h.audit openssh-8.6p1/mac.h +--- openssh-8.6p1/mac.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/mac.h 2021-04-19 16:47:35.756062129 +0200 +@@ -49,5 +49,6 @@ int mac_compute(struct sshmac *, u_int3 int mac_check(struct sshmac *, u_int32_t, const u_char *, size_t, const u_char *, size_t); void mac_clear(struct sshmac *); +void mac_destroy(struct sshmac *); #endif /* SSHMAC_H */ -diff --git a/monitor.c b/monitor.c -index a4d9062..fc05db6 100644 ---- a/monitor.c -+++ b/monitor.c +diff -up openssh-8.6p1/Makefile.in.audit openssh-8.6p1/Makefile.in +--- openssh-8.6p1/Makefile.in.audit 2021-04-19 16:47:35.731061937 +0200 ++++ openssh-8.6p1/Makefile.in 2021-04-19 16:47:35.756062129 +0200 +@@ -112,7 +112,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kexsntrup761x25519.o sntrup761.o kexgen.o \ + kexgssc.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ +- sshbuf-io.o ++ sshbuf-io.o auditstub.o + + SKOBJS= ssh-sk-client.o + +diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c +--- openssh-8.6p1/monitor.c.audit 2021-04-19 16:47:35.707061753 +0200 ++++ openssh-8.6p1/monitor.c 2021-04-19 16:47:35.756062129 +0200 @@ -93,6 +93,7 @@ #include "compat.h" #include "ssh2.h" @@ -1165,7 +1113,7 @@ index a4d9062..fc05db6 100644 /* State exported from the child */ static struct sshbuf *child_state; -@@ -155,6 +158,11 @@ int mm_answer_gss_updatecreds(struct ssh *, int, struct sshbuf *); +@@ -157,6 +160,11 @@ int mm_answer_gss_updatecreds(struct ssh #ifdef SSH_AUDIT_EVENTS int mm_answer_audit_event(struct ssh *, int, struct sshbuf *); int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); @@ -1177,7 +1125,7 @@ index a4d9062..fc05db6 100644 #endif static Authctxt *authctxt; -@@ -213,6 +221,10 @@ struct mon_table mon_dispatch_proto20[] = { +@@ -215,6 +223,10 @@ struct mon_table mon_dispatch_proto20[] #endif #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, @@ -1188,7 +1136,7 @@ index a4d9062..fc05db6 100644 #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, -@@ -247,6 +259,11 @@ struct mon_table mon_dispatch_postauth20[] = { +@@ -249,6 +261,11 @@ struct mon_table mon_dispatch_postauth20 #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, @@ -1200,7 +1148,7 @@ index a4d9062..fc05db6 100644 #endif {0, 0, NULL} }; -@@ -1453,8 +1470,10 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1444,8 +1461,10 @@ mm_answer_keyverify(struct ssh *ssh, int int r, ret, req_presence = 0, req_verify = 0, valid_data = 0; int encoded_ret; struct sshkey_sig_details *sig_details = NULL; @@ -1212,7 +1160,7 @@ index a4d9062..fc05db6 100644 (r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || (r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) -@@ -1463,6 +1482,8 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1454,6 +1473,8 @@ mm_answer_keyverify(struct ssh *ssh, int if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal_f("bad key, not previously allowed"); @@ -1221,7 +1169,7 @@ index a4d9062..fc05db6 100644 /* Empty signature algorithm means NULL. */ if (*sigalg == '\0') { -@@ -1478,14 +1499,19 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1469,14 +1490,19 @@ mm_answer_keyverify(struct ssh *ssh, int case MM_USERKEY: valid_data = monitor_valid_userblob(ssh, data, datalen); auth_method = "publickey"; @@ -1241,16 +1189,16 @@ index a4d9062..fc05db6 100644 break; } if (!valid_data) -@@ -1497,8 +1523,6 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1488,8 +1514,6 @@ mm_answer_keyverify(struct ssh *ssh, int SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); - ret = sshkey_verify(key, signature, signaturelen, data, datalen, - sigalg, ssh->compat, &sig_details); - debug3_f("%s %s signature using %s %s%s%s", auth_method, - sshkey_type(key), sigalg == NULL ? "default" : sigalg, - (ret == 0) ? "verified" : "unverified", -@@ -1586,13 +1610,19 @@ mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw) + debug3_f("%s %s signature using %s %s%s%s", auth_method, + sshkey_type(key), sigalg == NULL ? "default" : sigalg, + (ret == 0) ? "verified" : "unverified", +@@ -1576,13 +1600,19 @@ mm_record_login(struct ssh *ssh, Session } static void @@ -1271,7 +1219,7 @@ index a4d9062..fc05db6 100644 session_unused(s->self); } -@@ -1659,7 +1689,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1649,7 +1679,7 @@ mm_answer_pty(struct ssh *ssh, int sock, error: if (s != NULL) @@ -1280,7 +1228,7 @@ index a4d9062..fc05db6 100644 if ((r = sshbuf_put_u32(m, 0)) != 0) fatal_fr(r, "assemble 0"); mm_request_send(sock, MONITOR_ANS_PTY, m); -@@ -1678,7 +1708,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1668,7 +1698,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, i if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) fatal_fr(r, "parse tty"); if ((s = session_by_tty(tty)) != NULL) @@ -1289,7 +1237,7 @@ index a4d9062..fc05db6 100644 sshbuf_reset(m); free(tty); return (0); -@@ -1700,6 +1730,8 @@ mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req) +@@ -1690,6 +1720,8 @@ mm_answer_term(struct ssh *ssh, int sock sshpam_cleanup(); #endif @@ -1298,7 +1246,7 @@ index a4d9062..fc05db6 100644 while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); -@@ -1746,12 +1778,47 @@ mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m) +@@ -1736,12 +1768,47 @@ mm_answer_audit_command(struct ssh *ssh, { char *cmd; int r; @@ -1347,7 +1295,7 @@ index a4d9062..fc05db6 100644 free(cmd); return (0); } -@@ -1823,6 +1890,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1813,6 +1880,7 @@ monitor_apply_keystate(struct ssh *ssh, void mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { @@ -1355,7 +1303,7 @@ index a4d9062..fc05db6 100644 debug3_f("Waiting for new keys"); if ((child_state = sshbuf_new()) == NULL) -@@ -1830,6 +1898,19 @@ mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1820,6 +1888,19 @@ mm_get_keystate(struct ssh *ssh, struct mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, child_state); debug3_f("GOT new keys"); @@ -1375,7 +1323,7 @@ index a4d9062..fc05db6 100644 } -@@ -2121,3 +2202,102 @@ mm_answer_gss_updatecreds(struct ssh *ssh, int socket, struct sshbuf *m) { +@@ -2111,3 +2192,102 @@ mm_answer_gss_updatecreds(struct ssh *ss #endif /* GSSAPI */ @@ -1478,10 +1426,9 @@ index a4d9062..fc05db6 100644 + return 0; +} +#endif /* SSH_AUDIT_EVENTS */ -diff --git a/monitor.h b/monitor.h -index ae77ce0..e26c803 100644 ---- a/monitor.h -+++ b/monitor.h +diff -up openssh-8.6p1/monitor.h.audit openssh-8.6p1/monitor.h +--- openssh-8.6p1/monitor.h.audit 2021-04-19 16:47:35.707061753 +0200 ++++ openssh-8.6p1/monitor.h 2021-04-19 16:47:35.757062137 +0200 @@ -65,7 +65,13 @@ enum monitor_reqtype { MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, @@ -1497,11 +1444,10 @@ index ae77ce0..e26c803 100644 MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, -diff --git a/monitor_wrap.c b/monitor_wrap.c -index 7fd3282..2117679 100644 ---- a/monitor_wrap.c -+++ b/monitor_wrap.c -@@ -520,7 +520,7 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, +diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c +--- openssh-8.6p1/monitor_wrap.c.audit 2021-04-19 16:47:35.685061584 +0200 ++++ openssh-8.6p1/monitor_wrap.c 2021-04-19 16:47:35.757062137 +0200 +@@ -520,7 +520,7 @@ mm_key_allowed(enum mm_keytype type, con */ int @@ -1510,7 +1456,7 @@ index 7fd3282..2117679 100644 const u_char *data, size_t datalen, const char *sigalg, u_int compat, struct sshkey_sig_details **sig_detailsp) { -@@ -536,7 +536,8 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, +@@ -536,7 +536,8 @@ mm_sshkey_verify(const struct sshkey *ke *sig_detailsp = NULL; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); @@ -1520,7 +1466,7 @@ index 7fd3282..2117679 100644 (r = sshbuf_put_string(m, sig, siglen)) != 0 || (r = sshbuf_put_string(m, data, datalen)) != 0 || (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0) -@@ -569,6 +570,22 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, +@@ -569,6 +570,22 @@ mm_sshkey_verify(const struct sshkey *ke return 0; } @@ -1543,7 +1489,7 @@ index 7fd3282..2117679 100644 void mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { -@@ -921,11 +938,12 @@ mm_audit_event(struct ssh *ssh, ssh_audit_event_t event) +@@ -921,11 +938,12 @@ mm_audit_event(struct ssh *ssh, ssh_audi sshbuf_free(m); } @@ -1558,7 +1504,7 @@ index 7fd3282..2117679 100644 debug3("%s entering command %s", __func__, command); -@@ -935,6 +953,30 @@ mm_audit_run_command(const char *command) +@@ -935,6 +953,30 @@ mm_audit_run_command(const char *command fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); @@ -1589,7 +1535,7 @@ index 7fd3282..2117679 100644 sshbuf_free(m); } #endif /* SSH_AUDIT_EVENTS */ -@@ -1095,3 +1137,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) +@@ -1095,3 +1137,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc } #endif /* GSSAPI */ @@ -1673,11 +1619,10 @@ index 7fd3282..2117679 100644 + sshbuf_free(m); +} +#endif /* SSH_AUDIT_EVENTS */ -diff --git a/monitor_wrap.h b/monitor_wrap.h -index 7bc2b0f..be94793 100644 ---- a/monitor_wrap.h -+++ b/monitor_wrap.h -@@ -61,7 +61,9 @@ int mm_user_key_allowed(struct ssh *ssh, struct passwd *, struct sshkey *, int, +diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h +--- openssh-8.6p1/monitor_wrap.h.audit 2021-04-19 16:47:35.685061584 +0200 ++++ openssh-8.6p1/monitor_wrap.h 2021-04-19 16:47:35.757062137 +0200 +@@ -61,7 +61,9 @@ int mm_user_key_allowed(struct ssh *, st struct sshauthopt **); int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, const char *, struct sshkey *); @@ -1702,10 +1647,9 @@ index 7bc2b0f..be94793 100644 #endif struct Session; -diff --git a/packet.c b/packet.c -index 3f64d2d..c3328f3 100644 ---- a/packet.c -+++ b/packet.c +diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c +--- openssh-8.6p1/packet.c.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/packet.c 2021-04-19 16:48:46.885608837 +0200 @@ -81,6 +81,7 @@ #endif @@ -1714,7 +1658,7 @@ index 3f64d2d..c3328f3 100644 #include "compat.h" #include "ssh2.h" #include "cipher.h" -@@ -506,6 +507,13 @@ ssh_packet_get_connection_out(struct ssh *ssh) +@@ -506,6 +507,13 @@ ssh_packet_get_connection_out(struct ssh return ssh->state->connection_out; } @@ -1728,7 +1672,7 @@ index 3f64d2d..c3328f3 100644 /* * Returns the IP-address of the remote host as a string. The returned * string must not be freed. -@@ -583,22 +591,19 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) +@@ -583,22 +591,19 @@ ssh_packet_close_internal(struct ssh *ss { struct session_state *state = ssh->state; u_int mode; @@ -1756,7 +1700,7 @@ index 3f64d2d..c3328f3 100644 for (mode = 0; mode < MODE_MAX; mode++) { kex_free_newkeys(state->newkeys[mode]); /* current keys */ state->newkeys[mode] = NULL; -@@ -634,8 +639,18 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) +@@ -634,8 +639,18 @@ ssh_packet_close_internal(struct ssh *ss #endif /* WITH_ZLIB */ cipher_free(state->send_context); cipher_free(state->receive_context); @@ -1775,7 +1719,7 @@ index 3f64d2d..c3328f3 100644 free(ssh->local_ipaddr); ssh->local_ipaddr = NULL; free(ssh->remote_ipaddr); -@@ -892,6 +907,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode) +@@ -892,6 +907,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod (unsigned long long)state->p_send.bytes, (unsigned long long)state->p_send.blocks); kex_free_newkeys(state->newkeys[mode]); @@ -1783,7 +1727,7 @@ index 3f64d2d..c3328f3 100644 state->newkeys[mode] = NULL; } /* note that both bytes and the seqnr are not reset */ -@@ -2183,6 +2199,72 @@ ssh_packet_get_output(struct ssh *ssh) +@@ -2173,6 +2189,72 @@ ssh_packet_get_output(struct ssh *ssh) return (void *)ssh->state->output; } @@ -1856,21 +1800,19 @@ index 3f64d2d..c3328f3 100644 /* Reset after_authentication and reset compression in post-auth privsep */ static int ssh_packet_set_postauth(struct ssh *ssh) -diff --git a/packet.h b/packet.h -index 176488b..46ef703 100644 ---- a/packet.h -+++ b/packet.h -@@ -220,4 +220,5 @@ const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); +diff -up openssh-8.6p1/packet.h.audit openssh-8.6p1/packet.h +--- openssh-8.6p1/packet.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/packet.h 2021-04-19 16:47:35.758062145 +0200 +@@ -218,4 +218,5 @@ const u_char *sshpkt_ptr(struct ssh *, s # undef EC_POINT #endif +void packet_destroy_all(struct ssh *, int, int); #endif /* PACKET_H */ -diff --git a/session.c b/session.c -index dd7d148..4602cd3 100644 ---- a/session.c -+++ b/session.c -@@ -135,7 +135,7 @@ extern char *__progname; +diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c +--- openssh-8.6p1/session.c.audit 2021-04-19 16:47:35.722061868 +0200 ++++ openssh-8.6p1/session.c 2021-04-19 16:47:35.758062145 +0200 +@@ -136,7 +136,7 @@ extern char *__progname; extern int debug_flag; extern u_int utmp_len; extern int startup_pipe; @@ -1879,7 +1821,7 @@ index dd7d148..4602cd3 100644 extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; extern char *tun_fwd_ifnames; /* serverloop.c */ -@@ -643,6 +643,14 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) +@@ -644,6 +644,14 @@ do_exec_pty(struct ssh *ssh, Session *s, /* Parent. Close the slave side of the pseudo tty. */ close(ttyfd); @@ -1894,7 +1836,7 @@ index dd7d148..4602cd3 100644 /* Enter interactive session. */ s->ptymaster = ptymaster; ssh_packet_set_interactive(ssh, 1, -@@ -735,15 +743,19 @@ do_exec(struct ssh *ssh, Session *s, const char *command) +@@ -736,15 +744,19 @@ do_exec(struct ssh *ssh, Session *s, con s->self); #ifdef SSH_AUDIT_EVENTS @@ -1916,7 +1858,7 @@ index dd7d148..4602cd3 100644 #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); -@@ -1549,8 +1561,11 @@ do_child(struct ssh *ssh, Session *s, const char *command) +@@ -1550,8 +1562,11 @@ do_child(struct ssh *ssh, Session *s, co sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); /* remove hostkey from the child's memory */ @@ -1929,7 +1871,7 @@ index dd7d148..4602cd3 100644 /* Force a password change */ if (s->authctxt->force_pwchange) { -@@ -1762,6 +1777,9 @@ session_unused(int id) +@@ -1763,6 +1778,9 @@ session_unused(int id) sessions[id].ttyfd = -1; sessions[id].ptymaster = -1; sessions[id].x11_chanids = NULL; @@ -1939,11 +1881,10 @@ index dd7d148..4602cd3 100644 sessions[id].next_unused = sessions_first_unused; sessions_first_unused = id; } -@@ -1840,6 +1858,19 @@ session_open(Authctxt *authctxt, int chanid) - return 1; +@@ -1843,6 +1861,19 @@ session_open(Authctxt *authctxt, int cha } -+Session * + Session * +session_by_id(int id) +{ + if (id >= 0 && id < sessions_nalloc) { @@ -1956,10 +1897,11 @@ index dd7d148..4602cd3 100644 + return NULL; +} + - Session * ++Session * session_by_tty(char *tty) { -@@ -2448,6 +2479,32 @@ session_exit_message(struct ssh *ssh, Session *s, int status) + int i; +@@ -2450,6 +2481,32 @@ session_exit_message(struct ssh *ssh, Se chan_write_failed(ssh, c); } @@ -1992,7 +1934,7 @@ index dd7d148..4602cd3 100644 void session_close(struct ssh *ssh, Session *s) { -@@ -2461,6 +2518,10 @@ session_close(struct ssh *ssh, Session *s) +@@ -2463,6 +2520,10 @@ session_close(struct ssh *ssh, Session * if (s->ttyfd != -1) session_pty_cleanup(s); @@ -2003,7 +1945,7 @@ index dd7d148..4602cd3 100644 free(s->term); free(s->display); free(s->x11_chanids); -@@ -2535,14 +2596,14 @@ session_close_by_channel(struct ssh *ssh, int id, void *arg) +@@ -2537,14 +2598,14 @@ session_close_by_channel(struct ssh *ssh } void @@ -2020,7 +1962,7 @@ index dd7d148..4602cd3 100644 else session_close(ssh, s); } -@@ -2669,6 +2730,15 @@ do_authenticated2(struct ssh *ssh, Authctxt *authctxt) +@@ -2671,6 +2732,15 @@ do_authenticated2(struct ssh *ssh, Authc server_loop2(ssh, authctxt); } @@ -2036,7 +1978,7 @@ index dd7d148..4602cd3 100644 void do_cleanup(struct ssh *ssh, Authctxt *authctxt) { -@@ -2732,7 +2802,7 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +@@ -2734,7 +2804,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au * or if running in monitor. */ if (!use_privsep || mm_is_monitor()) @@ -2045,10 +1987,9 @@ index dd7d148..4602cd3 100644 } /* Return a name for the remote host that fits inside utmp_size */ -diff --git a/session.h b/session.h -index ce59dab..bcd4b1d 100644 ---- a/session.h -+++ b/session.h +diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h +--- openssh-8.6p1/session.h.audit 2021-04-16 05:55:25.000000000 +0200 ++++ openssh-8.6p1/session.h 2021-04-19 16:47:35.758062145 +0200 @@ -61,6 +61,12 @@ struct Session { char *name; char *val; @@ -2065,7 +2006,7 @@ index ce59dab..bcd4b1d 100644 @@ -71,10 +77,12 @@ void session_unused(int); int session_input_channel_req(struct ssh *, Channel *, const char *); void session_close_by_pid(struct ssh *ssh, pid_t, int); - void session_close_by_channel(struct ssh *, int, void *); + void session_close_by_channel(struct ssh *, int, int, void *); -void session_destroy_all(struct ssh *, void (*)(Session *)); +void session_destroy_all(struct ssh *, void (*)(struct ssh*, Session *)); void session_pty_cleanup2(Session *); @@ -2076,11 +2017,10 @@ index ce59dab..bcd4b1d 100644 Session *session_by_tty(char *); void session_close(struct ssh *, Session *); void do_setusercontext(struct passwd *); -diff --git a/sshd.c b/sshd.c -index 2fb129d..13a217d 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -125,6 +125,7 @@ +diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c +--- openssh-8.6p1/sshd.c.audit 2021-04-19 16:47:35.727061907 +0200 ++++ openssh-8.6p1/sshd.c 2021-04-19 16:47:35.759062152 +0200 +@@ -122,6 +122,7 @@ #include "ssh-gss.h" #endif #include "monitor_wrap.h" @@ -2088,7 +2028,7 @@ index 2fb129d..13a217d 100644 #include "ssh-sandbox.h" #include "auth-options.h" #include "version.h" -@@ -263,8 +264,8 @@ struct sshbuf *loginmsg; +@@ -260,8 +261,8 @@ struct sshbuf *loginmsg; struct passwd *privsep_pw = NULL; /* Prototypes for various functions defined later in this file. */ @@ -2099,7 +2039,7 @@ index 2fb129d..13a217d 100644 static void do_ssh2_kex(struct ssh *); static char *listener_proctitle; -@@ -282,6 +283,15 @@ close_listen_socks(void) +@@ -279,6 +280,15 @@ close_listen_socks(void) num_listen_socks = 0; } @@ -2115,10 +2055,10 @@ index 2fb129d..13a217d 100644 static void close_startup_pipes(void) { -@@ -376,18 +386,45 @@ grace_alarm_handler(int sig) - ssh_remote_port(the_active_state)); +@@ -377,18 +387,45 @@ grace_alarm_handler(int sig) + ssh_remote_port(the_active_state)); } - + -/* Destroy the host and server keys. They will no longer be needed. */ +/* + * Destroy the host and server keys. They will no longer be needed. Careful, @@ -2164,7 +2104,7 @@ index 2fb129d..13a217d 100644 sshkey_free(sensitive_data.host_certificates[i]); sensitive_data.host_certificates[i] = NULL; } -@@ -396,20 +433,38 @@ destroy_sensitive_data(void) +@@ -397,20 +434,38 @@ destroy_sensitive_data(void) /* Demote private to public keys for network child */ void @@ -2204,7 +2144,7 @@ index 2fb129d..13a217d 100644 } /* Certs do not need demotion */ } -@@ -437,7 +492,7 @@ reseed_prngs(void) +@@ -438,7 +493,7 @@ reseed_prngs(void) } static void @@ -2213,7 +2153,7 @@ index 2fb129d..13a217d 100644 { gid_t gidset[1]; -@@ -452,7 +507,7 @@ privsep_preauth_child(void) +@@ -453,7 +508,7 @@ privsep_preauth_child(void) reseed_prngs(); /* Demote the private keys to public keys. */ @@ -2222,7 +2162,7 @@ index 2fb129d..13a217d 100644 #ifdef WITH_SELINUX sshd_selinux_change_privsep_preauth_context(); -@@ -491,7 +546,7 @@ privsep_preauth(struct ssh *ssh) +@@ -492,7 +547,7 @@ privsep_preauth(struct ssh *ssh) if (use_privsep == PRIVSEP_ON) box = ssh_sandbox_init(pmonitor); @@ -2231,7 +2171,7 @@ index 2fb129d..13a217d 100644 if (pid == -1) { fatal("fork of unprivileged child failed"); } else if (pid != 0) { -@@ -536,7 +591,7 @@ privsep_preauth(struct ssh *ssh) +@@ -537,7 +592,7 @@ privsep_preauth(struct ssh *ssh) /* Arrange for logging to be sent to the monitor */ set_log_handler(mm_log_handler, pmonitor); @@ -2240,7 +2180,7 @@ index 2fb129d..13a217d 100644 setproctitle("%s", "[net]"); if (box != NULL) ssh_sandbox_child(box); -@@ -588,7 +643,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) +@@ -589,7 +644,7 @@ privsep_postauth(struct ssh *ssh, Authct set_log_handler(mm_log_handler, pmonitor); /* Demote the private keys to public keys. */ @@ -2249,16 +2189,16 @@ index 2fb129d..13a217d 100644 reseed_prngs(); -@@ -1142,7 +1197,7 @@ server_listen(void) +@@ -1143,7 +1198,7 @@ server_listen(void) * from this function are in a forked subprocess. */ static void -server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) +server_accept_loop(struct ssh *ssh, int *sock_in, int *sock_out, int *newsock, int *config_s) { - struct pollfd *pfd = NULL; - int i, j, ret, npfd; -@@ -1187,6 +1242,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s) + struct pollfd *pfd = NULL; + int i, j, ret, npfd; +@@ -1204,6 +1259,7 @@ server_accept_loop(int *sock_in, int *so if (received_sigterm) { logit("Received signal %d; terminating.", (int) received_sigterm); @@ -2266,7 +2206,7 @@ index 2fb129d..13a217d 100644 close_listen_socks(); if (options.pid_file != NULL) unlink(options.pid_file); -@@ -2131,7 +2187,7 @@ main(int ac, char **av) +@@ -2098,7 +2154,7 @@ main(int ac, char **av) #endif /* Accept a connection and return in a forked child */ @@ -2275,7 +2215,7 @@ index 2fb129d..13a217d 100644 &newsock, config_s); } -@@ -2359,6 +2415,9 @@ main(int ac, char **av) +@@ -2333,6 +2389,9 @@ main(int ac, char **av) do_authenticated(ssh, authctxt); /* The connection has been terminated. */ @@ -2285,7 +2225,7 @@ index 2fb129d..13a217d 100644 ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); -@@ -2542,6 +2601,15 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2513,6 +2572,15 @@ do_ssh2_kex(struct ssh *ssh) void cleanup_exit(int i) { @@ -2301,7 +2241,7 @@ index 2fb129d..13a217d 100644 if (the_active_state != NULL && the_authctxt != NULL) { do_cleanup(the_active_state, the_authctxt); if (use_privsep && privsep_is_preauth && -@@ -2554,9 +2622,16 @@ cleanup_exit(int i) +@@ -2525,9 +2593,16 @@ cleanup_exit(int i) } } } @@ -2319,15 +2259,13 @@ index 2fb129d..13a217d 100644 audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif _exit(i); -diff --git a/sshkey.c b/sshkey.c -index 151f5af..80f131f 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -399,6 +399,38 @@ sshkey_type_is_valid_ca(int type) - } +diff -up openssh-8.6p1/sshkey.c.audit openssh-8.6p1/sshkey.c +--- openssh-8.6p1/sshkey.c.audit 2021-04-19 16:47:35.741062014 +0200 ++++ openssh-8.6p1/sshkey.c 2021-04-19 16:47:35.759062152 +0200 +@@ -371,6 +371,38 @@ sshkey_type_is_valid_ca(int type) } -+int + int +sshkey_is_private(const struct sshkey *k) +{ + switch (k->type) { @@ -2359,14 +2297,14 @@ index 151f5af..80f131f 100644 + } +} + - int ++int sshkey_is_cert(const struct sshkey *k) { -diff --git a/sshkey.h b/sshkey.h -index a51d713..bb817a6 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -189,6 +189,7 @@ int sshkey_shield_private(struct sshkey *); + if (k == NULL) +diff -up openssh-8.6p1/sshkey.h.audit openssh-8.6p1/sshkey.h +--- openssh-8.6p1/sshkey.h.audit 2021-04-19 16:47:35.741062014 +0200 ++++ openssh-8.6p1/sshkey.h 2021-04-19 16:47:35.759062152 +0200 +@@ -189,6 +189,7 @@ int sshkey_shield_private(struct sshke int sshkey_unshield_private(struct sshkey *); int sshkey_type_from_name(const char *); @@ -2374,6 +2312,3 @@ index a51d713..bb817a6 100644 int sshkey_is_cert(const struct sshkey *); int sshkey_is_sk(const struct sshkey *); int sshkey_type_is_cert(int); --- -2.27.0 - diff --git a/openssh-7.7p1-gssapi-new-unique.patch b/openssh-7.7p1-gssapi-new-unique.patch index 64e96ab236575953ac5ba5455fd8e662e52bee62..544932b79bb0943fa175b549056576c0d9ce2e87 100644 --- a/openssh-7.7p1-gssapi-new-unique.patch +++ b/openssh-7.7p1-gssapi-new-unique.patch @@ -503,13 +503,12 @@ diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_keyex == -1) -@@ -506,7 +509,8 @@ typedef enum { +@@ -506,7 +509,7 @@ typedef enum { sPort, sHostKeyFile, sLoginGraceTime, sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, - sKerberosGetAFSToken, sPasswordAuthentication, -+ sKerberosGetAFSToken, sKerberosUniqueCCache, -+ sPasswordAuthentication, ++ sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, diff --git a/openssh-7.7p1.patch b/openssh-7.7p1.patch index fcda6c6dfd00866c04b287acdfcf6174b9d1d4b9..85ebc82d9490840f15c985f57cba101a1dd56378 100644 --- a/openssh-7.7p1.patch +++ b/openssh-7.7p1.patch @@ -15,7 +15,7 @@ diff -up openssh/ssh_config.redhat openssh/ssh_config diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat --- openssh/ssh_config_redhat.redhat 2020-02-13 18:13:39.180641839 +0100 +++ openssh/ssh_config_redhat 2020-02-13 18:13:39.180641839 +0100 -@@ -0,0 +1,21 @@ +@@ -0,0 +1,15 @@ +# The options here are in the "Match final block" to be applied as the last +# options and could be potentially overwritten by the user configuration +Match final all @@ -29,12 +29,6 @@ diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat +# mode correctly we set this to yes. + ForwardX11Trusted yes + -+# Send locale-related environment variables -+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+ SendEnv XMODIFIERS -+ +# Uncomment this if you want to use .local domain +# Host *.local diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0 @@ -86,7 +80,7 @@ diff -up openssh/sshd_config.redhat openssh/sshd_config diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat --- openssh/sshd_config_redhat.redhat 2020-02-13 18:14:02.268006439 +0100 +++ openssh/sshd_config_redhat 2020-02-13 18:19:20.765035947 +0100 -@@ -0,0 +1,28 @@ +@@ -0,0 +1,22 @@ +# This system is following system-wide crypto policy. The changes to +# crypto properties (Ciphers, MACs, ...) will not have any effect in +# this or following included files. To override some configuration option, @@ -109,9 +103,3 @@ diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat +# as it is more configurable and versatile than the built-in version. +PrintMotd no + -+# Accept locale-related environment variables -+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+AcceptEnv XMODIFIERS -+ diff --git a/openssh-7.8p1-UsePAM-warning.patch b/openssh-7.8p1-UsePAM-warning.patch index 2242b98c817872339acea0bb541d2811d1e30c92..48d2b32fe3fdee503da39957a5d1fc6f097f5548 100644 --- a/openssh-7.8p1-UsePAM-warning.patch +++ b/openssh-7.8p1-UsePAM-warning.patch @@ -1,4 +1,3 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-7.8p1-UsePAM-warning.patch diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c --- openssh-8.6p1/sshd.c.log-usepam-no 2021-04-19 14:00:45.099735129 +0200 +++ openssh-8.6p1/sshd.c 2021-04-19 14:03:21.140920974 +0200 diff --git a/openssh-8.0p1-crypto-policies.patch b/openssh-8.0p1-crypto-policies.patch index 75bd3aa491f21e23f5094eceb8dd07de3cb41fe8..86c08dba42f5cb25850dc7b5be1c70cd9c9f8ccc 100644 --- a/openssh-8.0p1-crypto-policies.patch +++ b/openssh-8.0p1-crypto-policies.patch @@ -1,8 +1,7 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-8.0p1-crypto-policies.patch -diff --color -ru a/ssh_config.5 b/ssh_config.5 ---- a/ssh_config.5 2022-07-12 15:05:22.550013071 +0200 -+++ b/ssh_config.5 2022-07-12 15:17:20.016704545 +0200 -@@ -373,17 +373,13 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh_config.5 openssh-9.3p1-patched/ssh_config.5 +--- openssh-9.3p1/ssh_config.5 2023-06-07 10:26:48.284590156 +0200 ++++ openssh-9.3p1-patched/ssh_config.5 2023-06-07 10:26:00.623052194 +0200 +@@ -378,17 +378,13 @@ causes no CNAMEs to be considered for canonicalization. This is the default behaviour. .It Cm CASignatureAlgorithms @@ -25,7 +24,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set -@@ -445,20 +441,25 @@ +@@ -450,20 +446,25 @@ (the default), the check will not be executed. .It Cm Ciphers @@ -55,7 +54,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 .Pp The supported ciphers are: .Bd -literal -offset indent -@@ -474,13 +475,6 @@ +@@ -479,13 +480,6 @@ chacha20-poly1305@openssh.com .Ed .Pp @@ -69,7 +68,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClearAllForwardings -@@ -874,6 +868,11 @@ +@@ -885,6 +879,11 @@ The default is .Dq no . .It Cm GSSAPIKexAlgorithms @@ -81,7 +80,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 The list of key exchange algorithms that are offered for GSSAPI key exchange. Possible values are .Bd -literal -offset 3n -@@ -886,10 +885,8 @@ +@@ -897,10 +896,8 @@ gss-curve25519-sha256- .Ed .Pp @@ -93,7 +92,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 .It Cm HashKnownHosts Indicates that .Xr ssh 1 -@@ -913,36 +910,25 @@ +@@ -919,36 +916,25 @@ but may be manually hashed using .Xr ssh-keygen 1 . .It Cm HostbasedAcceptedAlgorithms @@ -138,7 +137,25 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 .Pp The .Fl Q -@@ -1219,30 +1216,25 @@ +@@ -1001,6 +987,17 @@ + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q HostKeyAlgorithms . ++.Pp ++The proposed ++.Cm HostKeyAlgorithms ++during KEX are limited to the set of algorithms that is defined in ++.Cm PubkeyAcceptedAlgorithms ++and therefore they are indirectly affected by system-wide ++.Xr crypto_policies 7 . ++.Xr crypto_policies 7 can not handle the list of host key algorithms directly as doing so ++would break the order given by the ++.Pa known_hosts ++file. + .It Cm HostKeyAlias + Specifies an alias that should be used instead of the + real host name when looking up or saving the host key +@@ -1232,30 +1229,25 @@ and .Cm pam . .It Cm KexAlgorithms @@ -178,7 +195,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 .Pp The list of available key exchange algorithms may also be obtained using .Qq ssh -Q kex . -@@ -1351,37 +1344,33 @@ +@@ -1365,37 +1357,33 @@ file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs @@ -225,7 +242,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm NoHostAuthenticationForLocalhost -@@ -1553,36 +1542,25 @@ +@@ -1567,39 +1555,31 @@ The default is .Cm no . .It Cm PubkeyAcceptedAlgorithms @@ -271,7 +288,13 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . -@@ -2237,7 +2207,9 @@ for those users who do not have a config ++.Pp ++This option affects also ++.Cm HostKeyAlgorithms + .It Cm PubkeyAuthentication + Specifies whether to try public key authentication. + The argument to this keyword must be +@@ -2265,7 +2245,9 @@ This file must be world-readable. .El .Sh SEE ALSO @@ -282,10 +305,10 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5 .Sh AUTHORS .An -nosplit OpenSSH is a derivative of the original and free -diff --color -ru a/sshd_config.5 b/sshd_config.5 ---- a/sshd_config.5 2022-07-12 15:05:22.535012771 +0200 -+++ b/sshd_config.5 2022-07-12 15:15:33.394809258 +0200 -@@ -373,17 +373,13 @@ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/sshd_config.5 openssh-9.3p1-patched/sshd_config.5 +--- openssh-9.3p1/sshd_config.5 2023-06-07 10:26:48.277590077 +0200 ++++ openssh-9.3p1-patched/sshd_config.5 2023-06-07 10:26:00.592051845 +0200 +@@ -379,17 +379,13 @@ then no banner is displayed. By default, no banner is displayed. .It Cm CASignatureAlgorithms @@ -308,7 +331,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set -@@ -450,20 +446,25 @@ +@@ -525,20 +521,25 @@ indicating not to .Xr chroot 2 . .It Cm Ciphers @@ -338,7 +361,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 .Pp The supported ciphers are: .Pp -@@ -490,13 +491,6 @@ +@@ -565,13 +566,6 @@ chacha20-poly1305@openssh.com .El .Pp @@ -352,7 +375,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClientAliveCountMax -@@ -685,53 +679,43 @@ +@@ -766,53 +760,43 @@ .Cm GSSAPIKeyExchange needs to be enabled in the server and also used by the client. .It Cm GSSAPIKexAlgorithms @@ -425,7 +448,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q HostbasedAcceptedAlgorithms . -@@ -799,25 +794,14 @@ +@@ -879,25 +863,14 @@ .Ev SSH_AUTH_SOCK environment variable. .It Cm HostKeyAlgorithms @@ -456,7 +479,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts -@@ -965,20 +947,25 @@ +@@ -1044,20 +1017,25 @@ The default is .Cm yes . .It Cm KexAlgorithms @@ -486,7 +509,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 The supported algorithms are: .Pp .Bl -item -compact -offset indent -@@ -1010,16 +997,6 @@ +@@ -1089,16 +1067,6 @@ sntrup761x25519-sha512@openssh.com .El .Pp @@ -503,7 +526,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 The list of available key exchange algorithms may also be obtained using .Qq ssh -Q KexAlgorithms . .It Cm ListenAddress -@@ -1104,21 +1082,26 @@ +@@ -1184,21 +1152,26 @@ file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs @@ -534,7 +557,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 .Pp The algorithms that contain .Qq -etm -@@ -1161,15 +1144,6 @@ +@@ -1241,15 +1214,6 @@ umac-128-etm@openssh.com .El .Pp @@ -550,7 +573,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm Match -@@ -1548,36 +1522,25 @@ +@@ -1633,36 +1597,25 @@ The default is .Cm yes . .It Cm PubkeyAcceptedAlgorithms @@ -596,7 +619,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5 .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . -@@ -2011,7 +1968,9 @@ This file should be writable by root onl +@@ -2131,7 +2084,9 @@ .El .Sh SEE ALSO .Xr sftp-server 8 , diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index 9db6a9f6a85b39e29f7b6ad08dc04717193959cd..f3e3f5292de2d42fc6f2dc3b3050906b0382e30b 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -1,52 +1,8 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-8.0p1-gssapi-keyex.patch - ---- - Makefile.in | 3 +- - auth.c | 94 +------- - auth2-gss.c | 56 ++++- - auth2.c | 2 + - canohost.c | 93 ++++++++ - canohost.h | 3 + - clientloop.c | 11 + - configure.ac | 24 ++ - gss-genr.c | 297 +++++++++++++++++++++++- - gss-serv-krb5.c | 97 +++++++- - gss-serv.c | 205 +++++++++++++++-- - kex.c | 66 +++++- - kex.h | 29 +++ - kexdh.c | 10 + - kexgen.c | 2 +- - kexgssc.c | 599 ++++++++++++++++++++++++++++++++++++++++++++++++ - kexgsss.c | 474 ++++++++++++++++++++++++++++++++++++++ - monitor.c | 138 ++++++++++- - monitor.h | 2 + - monitor_wrap.c | 57 ++++- - monitor_wrap.h | 4 +- - readconf.c | 70 ++++++ - readconf.h | 6 + - servconf.c | 47 ++++ - servconf.h | 3 + - session.c | 10 +- - ssh-gss.h | 54 ++++- - ssh.1 | 8 + - ssh.c | 6 +- - ssh_config | 2 + - ssh_config.5 | 58 +++++ - sshconnect2.c | 156 ++++++++++++- - sshd.c | 62 ++++- - sshd_config | 2 + - sshd_config.5 | 31 +++ - sshkey.c | 3 +- - sshkey.h | 1 + - 37 files changed, 2623 insertions(+), 162 deletions(-) - create mode 100644 kexgssc.c - create mode 100644 kexgsss.c - diff --git a/Makefile.in b/Makefile.in -index f4c7540..8229885 100644 +index e7549470..b68c1710 100644 --- a/Makefile.in +++ b/Makefile.in -@@ -112,6 +112,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ +@@ -109,6 +109,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ kexsntrup761x25519.o sntrup761.o kexgen.o \ @@ -54,7 +10,7 @@ index f4c7540..8229885 100644 sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ sshbuf-io.o -@@ -128,7 +129,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ +@@ -125,7 +126,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ monitor.o monitor_wrap.o auth-krb5.o \ @@ -63,11 +19,19 @@ index f4c7540..8229885 100644 loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ srclimit.o sftp-server.o sftp-common.o \ sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ -diff --git a/auth.c b/auth.c -index 13e8d79..a449f27 100644 ---- a/auth.c -+++ b/auth.c -@@ -358,7 +358,8 @@ auth_root_allowed(struct ssh *ssh, const char *method) +@@ -523,7 +523,7 @@ regress-prep: + ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile + + REGRESSLIBS=libssh.a $(LIBCOMPAT) +-TESTLIBS=$(LIBS) $(CHANNELLIBS) ++TESTLIBS=$(LIBS) $(CHANNELLIBS) $(GSSLIBS) + + regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ +diff -up a/auth.c.gsskex b/auth.c +--- a/auth.c.gsskex 2021-08-20 06:03:49.000000000 +0200 ++++ b/auth.c 2021-08-27 12:41:51.262788953 +0200 +@@ -402,7 +402,8 @@ auth_root_allowed(struct ssh *ssh, const case PERMIT_NO_PASSWD: if (strcmp(method, "publickey") == 0 || strcmp(method, "hostbased") == 0 || @@ -77,11 +41,10 @@ index 13e8d79..a449f27 100644 return 1; break; case PERMIT_FORCED_ONLY: -@@ -639,97 +640,6 @@ fakepw(void) - return (&fake); +@@ -730,97 +731,6 @@ fakepw(void) } --/* + /* - * Returns the remote DNS hostname as a string. The returned string must not - * be freed. NB. this will usually trigger a DNS query the first time it is - * called. @@ -172,11 +135,12 @@ index 13e8d79..a449f27 100644 - return xstrdup(name); -} - - /* +-/* * Return the canonical name of the host in the other side of the current * connection. The host name is cached, so it is efficient to call this + * several times. diff --git a/auth2-gss.c b/auth2-gss.c -index d9b192c..cd6487c 100644 +index 9351e042..d6446c0c 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,7 +1,7 @@ @@ -188,7 +152,7 @@ index d9b192c..cd6487c 100644 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -@@ -55,6 +55,48 @@ static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh); +@@ -54,6 +54,48 @@ static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh); static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh); static int input_gssapi_errtok(int, u_int32_t, struct ssh *); @@ -237,7 +201,7 @@ index d9b192c..cd6487c 100644 /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) -@@ -261,7 +303,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) +@@ -260,7 +302,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) if ((r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); @@ -247,7 +211,7 @@ index d9b192c..cd6487c 100644 if ((!use_privsep || mm_is_monitor()) && (displayname = ssh_gssapi_displayname()) != NULL) -@@ -314,7 +357,8 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) +@@ -306,7 +349,8 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) gssbuf.length = sshbuf_len(b); if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) @@ -257,7 +221,7 @@ index d9b192c..cd6487c 100644 else logit("GSSAPI MIC check failed"); -@@ -336,6 +380,12 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) +@@ -326,6 +370,12 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) return 0; } @@ -269,12 +233,12 @@ index d9b192c..cd6487c 100644 + Authmethod method_gssapi = { "gssapi-with-mic", - NULL, + NULL, diff --git a/auth2.c b/auth2.c -index 15ae306..7510c25 100644 +index 0e776224..1c217268 100644 --- a/auth2.c +++ b/auth2.c -@@ -71,6 +71,7 @@ extern Authmethod method_passwd; +@@ -73,6 +73,7 @@ extern Authmethod method_passwd; extern Authmethod method_kbdint; extern Authmethod method_hostbased; #ifdef GSSAPI @@ -282,7 +246,7 @@ index 15ae306..7510c25 100644 extern Authmethod method_gssapi; #endif -@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { +@@ -80,6 +81,7 @@ Authmethod *authmethods[] = { &method_none, &method_pubkey, #ifdef GSSAPI @@ -291,7 +255,7 @@ index 15ae306..7510c25 100644 #endif &method_passwd, diff --git a/canohost.c b/canohost.c -index a810da0..fe337d7 100644 +index abea9c6e..8e81b519 100644 --- a/canohost.c +++ b/canohost.c @@ -35,6 +35,99 @@ @@ -395,7 +359,7 @@ index a810da0..fe337d7 100644 ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) { diff --git a/canohost.h b/canohost.h -index 26d6285..0cadc9f 100644 +index 26d62855..0cadc9f1 100644 --- a/canohost.h +++ b/canohost.h @@ -15,6 +15,9 @@ @@ -409,10 +373,10 @@ index 26d6285..0cadc9f 100644 int get_peer_port(int); char *get_local_ipaddr(int); diff --git a/clientloop.c b/clientloop.c -index 0050f3e..6f6216a 100644 +index ebd0dbca..1bdac6a4 100644 --- a/clientloop.c +++ b/clientloop.c -@@ -115,6 +115,10 @@ +@@ -112,6 +112,10 @@ #include "ssherr.h" #include "hostfile.h" @@ -423,25 +387,26 @@ index 0050f3e..6f6216a 100644 /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" -@@ -1350,6 +1354,13 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, - +@@ -1379,6 +1383,14 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, /* Do channel operations. */ channel_after_poll(ssh, pfd, npfd_active); + +#ifdef GSSAPI -+ if (options.gss_renewal_rekey && -+ ssh_gssapi_credentials_updated(NULL)) { ++ if (options.gss_renewal_rekey && ++ ssh_gssapi_credentials_updated(NULL)) { + debug("credentials updated - forcing rekey"); + need_rekeying = 1; -+ } ++ } +#endif - ++ /* Buffer input from the connection. */ - if (conn_in_ready) + if (conn_in_ready) + client_process_net_input(ssh); diff --git a/configure.ac b/configure.ac -index 51545ee..bbe133e 100644 +index b689db4b..efafb6bd 100644 --- a/configure.ac +++ b/configure.ac -@@ -736,6 +736,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) +@@ -674,6 +674,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) @@ -473,7 +438,7 @@ index 51545ee..bbe133e 100644 AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) diff --git a/gss-genr.c b/gss-genr.c -index 2cd695e..9f9745b 100644 +index d56257b4..763a63ff 100644 --- a/gss-genr.c +++ b/gss-genr.c @@ -1,7 +1,7 @@ @@ -485,7 +450,7 @@ index 2cd695e..9f9745b 100644 * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -@@ -42,9 +42,33 @@ +@@ -41,9 +41,33 @@ #include "sshbuf.h" #include "log.h" #include "ssh2.h" @@ -519,7 +484,7 @@ index 2cd695e..9f9745b 100644 /* sshbuf_get for gss_buffer_desc */ int ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) -@@ -60,6 +84,159 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) +@@ -62,6 +86,159 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) return 0; } @@ -679,7 +644,7 @@ index 2cd695e..9f9745b 100644 /* Check that the OID in a data stream matches that in the context */ int ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) -@@ -216,7 +393,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, +@@ -218,7 +398,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, } ctx->major = gss_init_sec_context(&ctx->minor, @@ -688,7 +653,7 @@ index 2cd695e..9f9745b 100644 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -245,9 +422,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) +@@ -247,9 +427,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) return (ctx->major); } @@ -732,7 +697,7 @@ index 2cd695e..9f9745b 100644 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); -@@ -255,6 +466,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) +@@ -257,6 +471,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) return (ctx->major); } @@ -752,7 +717,7 @@ index 2cd695e..9f9745b 100644 void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, const char *context, const struct sshbuf *session_id) -@@ -271,11 +495,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, +@@ -273,11 +500,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, } int @@ -770,7 +735,7 @@ index 2cd695e..9f9745b 100644 /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && -@@ -285,6 +514,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +@@ -287,6 +519,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); @@ -781,7 +746,7 @@ index 2cd695e..9f9745b 100644 if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); -@@ -294,10 +527,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +@@ -296,10 +532,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) GSS_C_NO_BUFFER); } @@ -850,7 +815,7 @@ index 2cd695e..9f9745b 100644 + #endif /* GSSAPI */ diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index a151bc1..8d2b677 100644 +index a151bc1e..8d2b677f 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c @@ -1,7 +1,7 @@ @@ -990,7 +955,7 @@ index a151bc1..8d2b677 100644 #endif /* KRB5 */ diff --git a/gss-serv.c b/gss-serv.c -index b5d4bb2..4287579 100644 +index ab3a15f0..6ce56e92 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -1,7 +1,7 @@ @@ -1290,18 +1255,12 @@ index b5d4bb2..4287579 100644 /* Privileged */ diff --git a/kex.c b/kex.c -index 0bcd27d..9e58a64 100644 +index ce85f043..574c7609 100644 --- a/kex.c +++ b/kex.c -@@ -57,11 +57,16 @@ - #include "misc.h" - #include "dispatch.h" - #include "monitor.h" -+#include "xmalloc.h" - - #include "ssherr.h" - #include "sshbuf.h" +@@ -57,6 +57,10 @@ #include "digest.h" + #include "xmalloc.h" +#ifdef GSSAPI +#include "ssh-gss.h" @@ -1310,7 +1269,7 @@ index 0bcd27d..9e58a64 100644 /* prototype */ static int kex_choose_conf(struct ssh *); static int kex_input_newkeys(int, u_int32_t, struct ssh *); -@@ -117,15 +122,28 @@ static const struct kexalg kexalgs[] = { +@@ -115,15 +120,28 @@ static const struct kexalg kexalgs[] = { #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ { NULL, 0, -1, -1}, }; @@ -1342,7 +1301,7 @@ index 0bcd27d..9e58a64 100644 if (ret != NULL) ret[rlen++] = sep; nlen = strlen(k->name); -@@ -140,6 +158,18 @@ kex_alg_list(char sep) +@@ -138,6 +156,18 @@ kex_alg_list(char sep) return ret; } @@ -1361,7 +1320,7 @@ index 0bcd27d..9e58a64 100644 static const struct kexalg * kex_alg_by_name(const char *name) { -@@ -149,6 +179,10 @@ kex_alg_by_name(const char *name) +@@ -147,6 +177,10 @@ kex_alg_by_name(const char *name) if (strcmp(k->name, name) == 0) return k; } @@ -1372,7 +1331,7 @@ index 0bcd27d..9e58a64 100644 return NULL; } -@@ -317,6 +351,29 @@ kex_assemble_names(char **listp, const char *def, const char *all) +@@ -315,6 +349,29 @@ kex_assemble_names(char **listp, const char *def, const char *all) return r; } @@ -1399,21 +1358,21 @@ index 0bcd27d..9e58a64 100644 + return 1; +} + - /* put algorithm proposal into buffer */ - int - kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) -@@ -717,6 +774,9 @@ kex_free(struct kex *kex) + /* + * Fill out a proposal array with dynamically allocated values, which may + * be modified as required for compatibility reasons. +@@ -698,6 +755,9 @@ kex_free(struct kex *kex) sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); sshbuf_free(kex->session_id); +#ifdef GSSAPI + free(kex->gss_host); +#endif /* GSSAPI */ - sshbuf_free(kex->initial_sig); - sshkey_free(kex->initial_hostkey); + sshbuf_free(kex->initial_sig); + sshkey_free(kex->initial_hostkey); free(kex->failed_choice); diff --git a/kex.h b/kex.h -index c353295..240dca8 100644 +index a5ae6ac0..fe714141 100644 --- a/kex.h +++ b/kex.h @@ -102,6 +102,15 @@ enum kex_exchange { @@ -1432,7 +1391,7 @@ index c353295..240dca8 100644 KEX_MAX }; -@@ -159,6 +168,12 @@ struct kex { +@@ -153,6 +162,12 @@ struct kex { u_int flags; int hash_alg; int ec_nid; @@ -1445,7 +1404,7 @@ index c353295..240dca8 100644 char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); -@@ -180,8 +195,10 @@ struct kex { +@@ -174,8 +189,10 @@ struct kex { int kex_names_valid(const char *); char *kex_alg_list(char); @@ -1453,10 +1412,10 @@ index c353295..240dca8 100644 char *kex_names_cat(const char *, const char *); int kex_assemble_names(char **, const char *, const char *); +int kex_gss_names_valid(const char *); - - int kex_exchange_identification(struct ssh *, int, const char *); - -@@ -209,6 +226,12 @@ int kexgex_client(struct ssh *); + void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], + const char *, const char *, const char *, const char *, const char *); + void kex_proposal_free_entries(char *prop[PROPOSAL_MAX]); +@@ -202,6 +219,12 @@ int kexgex_client(struct ssh *); int kexgex_server(struct ssh *); int kex_gen_client(struct ssh *); int kex_gen_server(struct ssh *); @@ -1469,7 +1428,7 @@ index c353295..240dca8 100644 int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, -@@ -241,6 +264,12 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, +@@ -234,6 +257,12 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); @@ -1483,10 +1442,10 @@ index c353295..240dca8 100644 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); diff --git a/kexdh.c b/kexdh.c -index c1084f2..0faab21 100644 +index 67133e33..edaa4676 100644 --- a/kexdh.c +++ b/kexdh.c -@@ -49,13 +49,23 @@ kex_dh_keygen(struct kex *kex) +@@ -48,13 +48,23 @@ kex_dh_keygen(struct kex *kex) { switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: @@ -1511,7 +1470,7 @@ index c1084f2..0faab21 100644 break; case KEX_DH_GRP18_SHA512: diff --git a/kexgen.c b/kexgen.c -index 20f3c57..ca70484 100644 +index 69348b96..c0e8c2f4 100644 --- a/kexgen.c +++ b/kexgen.c @@ -44,7 +44,7 @@ @@ -1525,10 +1484,10 @@ index 20f3c57..ca70484 100644 const struct sshbuf *client_version, diff --git a/kexgssc.c b/kexgssc.c new file mode 100644 -index 0000000..1c62740 +index 00000000..f6e1405e --- /dev/null +++ b/kexgssc.c -@@ -0,0 +1,599 @@ +@@ -0,0 +1,600 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -2127,10 +2086,11 @@ index 0000000..1c62740 + sshbuf_free(server_host_key_blob); + return r; +} ++ +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --git a/kexgsss.c b/kexgsss.c new file mode 100644 -index 0000000..a2c0214 +index 00000000..60bc02de --- /dev/null +++ b/kexgsss.c @@ -0,0 +1,474 @@ @@ -2609,7 +2569,7 @@ index 0000000..a2c0214 +} +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --git a/monitor.c b/monitor.c -index 7d42b6c..983082e 100644 +index 2ce89fe9..ebf76c7f 100644 --- a/monitor.c +++ b/monitor.c @@ -148,6 +148,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); @@ -2621,7 +2581,7 @@ index 7d42b6c..983082e 100644 #endif #ifdef SSH_AUDIT_EVENTS -@@ -223,11 +225,18 @@ struct mon_table mon_dispatch_proto20[] = { +@@ -220,11 +222,18 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, @@ -2640,7 +2600,7 @@ index 7d42b6c..983082e 100644 #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, #endif -@@ -296,6 +305,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -293,6 +302,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -2651,7 +2611,24 @@ index 7d42b6c..983082e 100644 /* The first few requests do not require asynchronous access */ while (!authenticated) { -@@ -407,6 +420,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -376,8 +376,15 @@ monitor_child_preauth(struct ssh *ssh, s + if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { + auth_log(ssh, authenticated, partial, + auth_method, auth_submethod); +- if (!partial && !authenticated) ++ if (!partial && !authenticated) { ++#ifdef GSSAPI ++ /* If gssapi-with-mic failed, MONITOR_REQ_GSSCHECKMIC is disabled. ++ * We have to reenable it to try again for gssapi-keyex */ ++ if (strcmp(auth_method, "gssapi-with-mic") == 0 && options.gss_keyex) ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); ++#endif + authctxt->failures++; ++ } + if (authenticated || partial) { + auth2_update_session_info(authctxt, + auth_method, auth_submethod); +@@ -406,6 +419,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); @@ -2662,7 +2639,7 @@ index 7d42b6c..983082e 100644 if (auth_opts->permit_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); -@@ -1777,6 +1794,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1713,6 +1730,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -2680,7 +2657,7 @@ index 7d42b6c..983082e 100644 #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; -@@ -1869,8 +1897,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1806,8 +1834,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) u_char *p; int r; @@ -2691,7 +2668,7 @@ index 7d42b6c..983082e 100644 if ((r = sshbuf_get_string(m, &p, &len)) != 0) fatal_fr(r, "parse"); -@@ -1902,8 +1930,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1839,8 +1867,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) OM_uint32 flags = 0; /* GSI needs this */ int r; @@ -2702,7 +2679,7 @@ index 7d42b6c..983082e 100644 if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) fatal_fr(r, "ssh_gssapi_get_buffer_desc"); -@@ -1923,6 +1951,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1860,6 +1888,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); @@ -2710,7 +2687,7 @@ index 7d42b6c..983082e 100644 } return (0); } -@@ -1934,8 +1963,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1871,8 +1900,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) OM_uint32 ret; int r; @@ -2721,7 +2698,7 @@ index 7d42b6c..983082e 100644 if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) -@@ -1961,13 +1990,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1898,13 +1927,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) int mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -2743,7 +2720,7 @@ index 7d42b6c..983082e 100644 sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) -@@ -1976,7 +2009,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1913,7 +1946,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); @@ -2756,7 +2733,7 @@ index 7d42b6c..983082e 100644 if ((displayname = ssh_gssapi_displayname()) != NULL) auth2_record_info(authctxt, "%s", displayname); -@@ -1984,5 +2021,84 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1921,5 +1958,84 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -2842,10 +2819,10 @@ index 7d42b6c..983082e 100644 #endif /* GSSAPI */ diff --git a/monitor.h b/monitor.h -index 6174b96..2878f66 100644 +index 683e5e07..2b1a2d59 100644 --- a/monitor.h +++ b/monitor.h -@@ -67,6 +67,8 @@ enum monitor_reqtype { +@@ -63,6 +63,8 @@ enum monitor_reqtype { MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, @@ -2855,10 +2832,10 @@ index 6174b96..2878f66 100644 struct ssh; diff --git a/monitor_wrap.c b/monitor_wrap.c -index 0de136a..7fd3282 100644 +index 001a8fa1..6edb509a 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c -@@ -1020,13 +1020,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +@@ -993,13 +993,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) } int @@ -2875,7 +2852,7 @@ index 0de136a..7fd3282 100644 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, -@@ -1039,4 +1041,57 @@ mm_ssh_gssapi_userok(char *user) +@@ -1012,4 +1014,57 @@ mm_ssh_gssapi_userok(char *user) debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } @@ -2934,10 +2911,10 @@ index 0de136a..7fd3282 100644 + #endif /* GSSAPI */ diff --git a/monitor_wrap.h b/monitor_wrap.h -index 6fb5ef6..7bc2b0f 100644 +index 23ab096a..485590c1 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h -@@ -68,8 +68,10 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, +@@ -64,8 +64,10 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); @@ -2949,10 +2926,9 @@ index 6fb5ef6..7bc2b0f 100644 #endif #ifdef USE_PAM -diff --git a/readconf.c b/readconf.c -index 42be690..fde930b 100644 ---- a/readconf.c -+++ b/readconf.c +diff -up a/readconf.c.gsskex b/readconf.c +--- a/readconf.c.gsskex 2021-08-20 06:03:49.000000000 +0200 ++++ b/readconf.c 2021-08-27 12:25:42.556421509 +0200 @@ -67,6 +67,7 @@ #include "uidswap.h" #include "myproposal.h" @@ -2993,7 +2969,7 @@ index 42be690..fde930b 100644 #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, -@@ -1120,10 +1135,42 @@ parse_time: +@@ -1113,10 +1128,42 @@ parse_time: intptr = &options->gss_authentication; goto parse_flag; @@ -3036,7 +3012,7 @@ index 42be690..fde930b 100644 case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -2332,7 +2379,13 @@ initialize_options(Options * options) +@@ -2306,7 +2353,13 @@ initialize_options(Options * options) options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; options->gss_authentication = -1; @@ -3050,7 +3026,7 @@ index 42be690..fde930b 100644 options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; -@@ -2490,8 +2543,18 @@ fill_default_options(Options * options) +@@ -2463,8 +2516,18 @@ fill_default_options(Options * options) options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3069,7 +3045,7 @@ index 42be690..fde930b 100644 if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -3286,7 +3349,14 @@ dump_client_config(Options *o, const char *host) +@@ -3246,7 +3309,14 @@ dump_client_config(Options *o, const cha dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); #ifdef GSSAPI dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); @@ -3084,10 +3060,9 @@ index 42be690..fde930b 100644 #endif /* GSSAPI */ dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); -diff --git a/readconf.h b/readconf.h -index ffb5ec4..788a534 100644 ---- a/readconf.h -+++ b/readconf.h +diff -up a/readconf.h.gsskex b/readconf.h +--- a/readconf.h.gsskex 2021-08-27 12:05:29.248142431 +0200 ++++ b/readconf.h 2021-08-27 12:22:19.270679852 +0200 @@ -39,7 +39,13 @@ typedef struct { int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ @@ -3102,10 +3077,9 @@ index ffb5ec4..788a534 100644 int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff --git a/servconf.c b/servconf.c -index 423772b..eb574f5 100644 ---- a/servconf.c -+++ b/servconf.c +diff -up a/servconf.c.gsskex b/servconf.c +--- a/servconf.c.gsskex 2021-08-20 06:03:49.000000000 +0200 ++++ b/servconf.c 2021-08-27 12:28:15.887735189 +0200 @@ -70,6 +70,7 @@ #include "auth.h" #include "myproposal.h" @@ -3114,7 +3088,7 @@ index 423772b..eb574f5 100644 static void add_listen_addr(ServerOptions *, const char *, const char *, int); -@@ -136,8 +137,11 @@ initialize_server_options(ServerOptions *options) +@@ -136,8 +137,11 @@ initialize_server_options(ServerOptions options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; @@ -3126,7 +3100,7 @@ index 423772b..eb574f5 100644 options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; -@@ -357,10 +361,18 @@ fill_default_server_options(ServerOptions *options) +@@ -356,10 +360,18 @@ fill_default_server_options(ServerOption options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3145,7 +3119,7 @@ index 423772b..eb574f5 100644 if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -508,6 +520,7 @@ typedef enum { +@@ -506,6 +518,7 @@ typedef enum { sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, @@ -3153,7 +3127,7 @@ index 423772b..eb574f5 100644 sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -590,12 +603,22 @@ static struct { +@@ -587,12 +600,22 @@ static struct { #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, @@ -3176,7 +3150,7 @@ index 423772b..eb574f5 100644 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ -@@ -1578,6 +1601,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1576,6 +1599,10 @@ process_server_config_line_depth(ServerO intptr = &options->gss_authentication; goto parse_flag; @@ -3187,7 +3161,7 @@ index 423772b..eb574f5 100644 case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1586,6 +1613,22 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1584,6 +1611,22 @@ process_server_config_line_depth(ServerO intptr = &options->gss_strict_acceptor; goto parse_flag; @@ -3210,7 +3184,7 @@ index 423772b..eb574f5 100644 case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -2906,6 +2949,10 @@ dump_config(ServerOptions *o) +@@ -2892,6 +2935,10 @@ dump_config(ServerOptions *o) #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); @@ -3222,10 +3196,10 @@ index 423772b..eb574f5 100644 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, diff --git a/servconf.h b/servconf.h -index 9346155..cb7af38 100644 +index 4202a2d0..3f47ea25 100644 --- a/servconf.h +++ b/servconf.h -@@ -141,8 +141,11 @@ typedef struct { +@@ -132,8 +132,11 @@ typedef struct { int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ int gss_authentication; /* If true, permit GSSAPI authentication */ @@ -3238,10 +3212,10 @@ index 9346155..cb7af38 100644 * authentication. */ int kbd_interactive_authentication; /* If true, permit */ diff --git a/session.c b/session.c -index baf2e3f..dfe2911 100644 +index 8c0e54f7..06a33442 100644 --- a/session.c +++ b/session.c -@@ -2671,13 +2671,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +@@ -2678,13 +2678,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) #ifdef KRB5 if (options.kerberos_ticket_cleanup && @@ -3264,7 +3238,7 @@ index baf2e3f..dfe2911 100644 /* remove agent socket */ diff --git a/ssh-gss.h b/ssh-gss.h -index a8af117..58471bf 100644 +index 36180d07..70dd3665 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -1,6 +1,6 @@ @@ -3310,7 +3284,7 @@ index a8af117..58471bf 100644 void *data; } ssh_gssapi_ccache; -@@ -72,8 +96,11 @@ typedef struct { +@@ -72,8 +92,11 @@ typedef struct { gss_buffer_desc displayname; gss_buffer_desc exportedname; gss_cred_id_t creds; @@ -3322,7 +3296,7 @@ index a8af117..58471bf 100644 } ssh_gssapi_client; typedef struct ssh_gssapi_mech_struct { -@@ -84,6 +111,7 @@ typedef struct ssh_gssapi_mech_struct { +@@ -84,6 +107,7 @@ typedef struct ssh_gssapi_mech_struct { int (*userok) (ssh_gssapi_client *, char *); int (*localname) (ssh_gssapi_client *, char **); void (*storecreds) (ssh_gssapi_client *); @@ -3330,7 +3304,7 @@ index a8af117..58471bf 100644 } ssh_gssapi_mech; typedef struct { -@@ -94,10 +122,11 @@ typedef struct { +@@ -94,10 +118,11 @@ typedef struct { gss_OID oid; /* client */ gss_cred_id_t creds; /* server */ gss_name_t client; /* server */ @@ -3343,7 +3317,7 @@ index a8af117..58471bf 100644 int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -109,6 +138,7 @@ OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *); +@@ -109,6 +134,7 @@ OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *); struct sshbuf; int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *); @@ -3351,7 +3325,7 @@ index a8af117..58471bf 100644 OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, -@@ -123,17 +153,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **); +@@ -123,17 +149,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **); OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); void ssh_gssapi_buildmic(struct sshbuf *, const char *, const char *, const char *, const struct sshbuf *); @@ -3388,10 +3362,10 @@ index a8af117..58471bf 100644 #endif /* _SSH_GSS_H */ diff --git a/ssh.1 b/ssh.1 -index 9fe3d51..ba95ea6 100644 +index 60de6087..db5c65bc 100644 --- a/ssh.1 +++ b/ssh.1 -@@ -533,7 +533,13 @@ For full details of the options listed below, and their possible values, see +@@ -503,7 +503,13 @@ For full details of the options listed below, and their possible values, see .It GatewayPorts .It GlobalKnownHostsFile .It GSSAPIAuthentication @@ -3405,7 +3379,7 @@ index 9fe3d51..ba95ea6 100644 .It HashKnownHosts .It Host .It HostbasedAcceptedAlgorithms -@@ -611,6 +617,8 @@ flag), +@@ -579,6 +585,8 @@ flag), (supported message integrity codes), .Ar kex (key exchange algorithms), @@ -3415,10 +3389,10 @@ index 9fe3d51..ba95ea6 100644 (key types), .Ar key-cert diff --git a/ssh.c b/ssh.c -index 25be53d..244b7f3 100644 +index 15aee569..110cf9c1 100644 --- a/ssh.c +++ b/ssh.c -@@ -783,6 +783,8 @@ main(int ac, char **av) +@@ -747,6 +747,8 @@ main(int ac, char **av) else if (strcmp(optarg, "kex") == 0 || strcasecmp(optarg, "KexAlgorithms") == 0) cp = kex_alg_list('\n'); @@ -3427,7 +3401,7 @@ index 25be53d..244b7f3 100644 else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); else if (strcmp(optarg, "key-cert") == 0) -@@ -810,8 +812,8 @@ main(int ac, char **av) +@@ -772,8 +774,8 @@ main(int ac, char **av) } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( "cipher\ncipher-auth\ncompression\nkex\n" @@ -3439,7 +3413,7 @@ index 25be53d..244b7f3 100644 if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); diff --git a/ssh_config b/ssh_config -index 036539d..255e9e0 100644 +index 5e8ef548..1ff999b6 100644 --- a/ssh_config +++ b/ssh_config @@ -24,6 +24,8 @@ @@ -3452,10 +3426,10 @@ index 036539d..255e9e0 100644 # CheckHostIP yes # AddressFamily any diff --git a/ssh_config.5 b/ssh_config.5 -index d1ede18..0a6c4a6 100644 +index 06a32d31..3f490697 100644 --- a/ssh_config.5 +++ b/ssh_config.5 -@@ -833,10 +833,68 @@ The default is +@@ -766,10 +766,68 @@ The default is Specifies whether user authentication based on GSSAPI is allowed. The default is .Cm no . @@ -3525,10 +3499,10 @@ index d1ede18..0a6c4a6 100644 Indicates that .Xr ssh 1 diff --git a/sshconnect2.c b/sshconnect2.c -index 58fe98d..4a7931f 100644 +index af00fb30..03bc87eb 100644 --- a/sshconnect2.c +++ b/sshconnect2.c -@@ -81,8 +81,6 @@ +@@ -80,8 +80,6 @@ #endif /* import */ @@ -3537,8 +3511,8 @@ index 58fe98d..4a7931f 100644 extern Options options; /* -@@ -226,6 +224,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, - char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; +@@ -163,6 +161,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + char *s, *all_key, *hkalgs = NULL; int r, use_known_hosts_order = 0; +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3549,10 +3523,11 @@ index 58fe98d..4a7931f 100644 xxx_host = host; xxx_hostaddr = hostaddr; xxx_conn_info = cinfo; -@@ -269,6 +272,42 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, - compat_pkalg_proposal(ssh, options.hostkeyalgorithms); - } - +@@ -206,6 +209,42 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers, + options.macs, compression_alg_list(options.compression), + hkalgs ? hkalgs : options.hostkeyalgorithms); ++ +#if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { + /* Add the GSSAPI mechanisms currently supported on this @@ -3588,11 +3563,10 @@ index 58fe98d..4a7931f 100644 + } + } +#endif -+ - if (options.rekey_limit || options.rekey_interval) - ssh_packet_set_rekey_limits(ssh, options.rekey_limit, - options.rekey_interval); -@@ -287,16 +326,46 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, + + free(hkalgs); + +@@ -224,17 +256,47 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif @@ -3610,7 +3584,7 @@ index 58fe98d..4a7931f 100644 +# endif +#endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3625,6 +3599,7 @@ index 58fe98d..4a7931f 100644 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); /* remove ext-info from the KEX proposals for rekeying */ + free(myproposal[PROPOSAL_KEX_ALGS]); myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, options.kex_algorithms); +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3640,7 +3615,7 @@ index 58fe98d..4a7931f 100644 if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) fatal_r(r, "kex_prop2buf"); -@@ -394,6 +463,7 @@ static int input_gssapi_response(int type, u_int32_t, struct ssh *); +@@ -330,6 +392,7 @@ static int input_gssapi_response(int type, u_int32_t, struct ssh *); static int input_gssapi_token(int type, u_int32_t, struct ssh *); static int input_gssapi_error(int, u_int32_t, struct ssh *); static int input_gssapi_errtok(int, u_int32_t, struct ssh *); @@ -3648,7 +3623,7 @@ index 58fe98d..4a7931f 100644 #endif void userauth(struct ssh *, char *); -@@ -410,6 +480,11 @@ static char *authmethods_get(void); +@@ -346,6 +409,11 @@ static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI @@ -3660,7 +3635,7 @@ index 58fe98d..4a7931f 100644 {"gssapi-with-mic", userauth_gssapi, userauth_gssapi_cleanup, -@@ -785,12 +860,32 @@ userauth_gssapi(struct ssh *ssh) +@@ -716,12 +784,32 @@ userauth_gssapi(struct ssh *ssh) OM_uint32 min; int r, ok = 0; gss_OID mech = NULL; @@ -3694,7 +3669,7 @@ index 58fe98d..4a7931f 100644 /* Check to see whether the mechanism is usable before we offer it */ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && -@@ -799,13 +894,15 @@ userauth_gssapi(struct ssh *ssh) +@@ -730,13 +811,15 @@ userauth_gssapi(struct ssh *ssh) elements[authctxt->mech_tried]; /* My DER encoding requires length<128 */ if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, @@ -3711,7 +3686,7 @@ index 58fe98d..4a7931f 100644 if (!ok || mech == NULL) return 0; -@@ -1046,6 +1143,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) +@@ -976,6 +1059,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) free(lang); return r; } @@ -3768,10 +3743,10 @@ index 58fe98d..4a7931f 100644 static int diff --git a/sshd.c b/sshd.c -index 4662caf..c986698 100644 +index 60b2aaf7..d92f03aa 100644 --- a/sshd.c +++ b/sshd.c -@@ -810,8 +810,8 @@ notify_hostkeys(struct ssh *ssh) +@@ -817,8 +817,8 @@ notify_hostkeys(struct ssh *ssh) } debug3_f("sent %u hostkeys", nkeys); if (nkeys == 0) @@ -3782,7 +3757,7 @@ index 4662caf..c986698 100644 sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } -@@ -1943,7 +1943,8 @@ main(int ac, char **av) +@@ -1852,7 +1852,8 @@ main(int ac, char **av) free(fp); } accumulate_host_timing_secret(cfg, NULL); @@ -3792,9 +3767,9 @@ index 4662caf..c986698 100644 logit("sshd: no hostkeys available -- exiting."); exit(1); } -@@ -2429,6 +2430,48 @@ do_ssh2_kex(struct ssh *ssh) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = - compat_pkalg_proposal(ssh, list_hostkey_types()); +@@ -2347,6 +2348,48 @@ do_ssh2_kex(struct ssh *ssh) + + free(hkalgs); +#if defined(GSSAPI) && defined(WITH_OPENSSL) + { @@ -3804,9 +3779,9 @@ index 4662caf..c986698 100644 + orig = myproposal[PROPOSAL_KEX_ALGS]; + + /* -+ * If we don't have a host key, then there's no point advertising -+ * the other key exchange algorithms -+ */ ++ * If we don't have a host key, then there's no point advertising ++ * the other key exchange algorithms ++ */ + + if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) + orig = NULL; @@ -3824,10 +3799,10 @@ index 4662caf..c986698 100644 + newstr = orig; + + /* -+ * If we've got GSSAPI mechanisms, then we've got the 'null' host -+ * key alg, but we can't tell people about it unless its the only -+ * host key algorithm we support -+ */ ++ * If we've got GSSAPI mechanisms, then we've got the 'null' host ++ * key alg, but we can't tell people about it unless its the only ++ * host key algorithm we support ++ */ + if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; + @@ -3841,7 +3816,7 @@ index 4662caf..c986698 100644 /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); -@@ -2444,7 +2487,18 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2362,7 +2405,18 @@ do_ssh2_kex(struct ssh *ssh) # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -3862,10 +3837,10 @@ index 4662caf..c986698 100644 kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; kex->load_host_public_key=&get_hostkey_public_by_type; diff --git a/sshd_config b/sshd_config -index 283bd88..47b5ecb 100644 +index 19b7c91a..2c48105f 100644 --- a/sshd_config +++ b/sshd_config -@@ -77,6 +77,8 @@ AuthorizedKeysFile .ssh/authorized_keys +@@ -69,6 +69,8 @@ AuthorizedKeysFile .ssh/authorized_keys # GSSAPI options #GSSAPIAuthentication no #GSSAPICleanupCredentials yes @@ -3875,10 +3850,10 @@ index 283bd88..47b5ecb 100644 # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will diff --git a/sshd_config.5 b/sshd_config.5 -index 57363e9..861a9ec 100644 +index 70ccea44..f6b41a2f 100644 --- a/sshd_config.5 +++ b/sshd_config.5 -@@ -650,6 +650,11 @@ Specifies whether to automatically destroy the user's credentials cache +@@ -646,6 +646,11 @@ Specifies whether to automatically destroy the user's credentials cache on logout. The default is .Cm yes . @@ -3890,7 +3865,7 @@ index 57363e9..861a9ec 100644 .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. -@@ -664,6 +669,32 @@ machine's default store. +@@ -660,6 +665,32 @@ machine's default store. This facility is provided to assist with operation on multi homed machines. The default is .Cm yes . @@ -3924,31 +3899,107 @@ index 57363e9..861a9ec 100644 Specifies the signature algorithms that will be accepted for hostbased authentication as a list of comma-separated patterns. diff --git a/sshkey.c b/sshkey.c -index 7709323..f78bc15 100644 +index 57995ee6..fd5b7724 100644 --- a/sshkey.c +++ b/sshkey.c -@@ -162,6 +162,7 @@ static const struct keytype keytypes[] = { - # endif /* ENABLE_SK */ - # endif /* OPENSSL_HAS_ECC */ - #endif /* WITH_OPENSSL */ -+ { "null", "null", NULL, KEY_NULL, 0, 0, 0 }, - { NULL, NULL, NULL, -1, -1, 0, 0 } +@@ -127,6 +127,75 @@ static const struct keytype keytypes[] = { + extern const struct sshkey_impl sshkey_xmss_impl; + extern const struct sshkey_impl sshkey_xmss_cert_impl; + #endif ++ ++static int ssh_gss_equal(const struct sshkey *, const struct sshkey *) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_serialize_public(const struct sshkey *, struct sshbuf *, ++ enum sshkey_serialize_rep) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_deserialize_public(const char *, struct sshbuf *, ++ struct sshkey *) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_serialize_private(const struct sshkey *, struct sshbuf *, ++ enum sshkey_serialize_rep) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_deserialize_private(const char *, struct sshbuf *, ++ struct sshkey *) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_copy_public(const struct sshkey *, struct sshkey *) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static int ssh_gss_verify(const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, ++ struct sshkey_sig_details **) ++{ ++ return SSH_ERR_FEATURE_UNSUPPORTED; ++} ++ ++static const struct sshkey_impl_funcs sshkey_gss_funcs = { ++ /* .size = */ NULL, ++ /* .alloc = */ NULL, ++ /* .cleanup = */ NULL, ++ /* .equal = */ ssh_gss_equal, ++ /* .ssh_serialize_public = */ ssh_gss_serialize_public, ++ /* .ssh_deserialize_public = */ ssh_gss_deserialize_public, ++ /* .ssh_serialize_private = */ ssh_gss_serialize_private, ++ /* .ssh_deserialize_private = */ ssh_gss_deserialize_private, ++ /* .generate = */ NULL, ++ /* .copy_public = */ ssh_gss_copy_public, ++ /* .sign = */ NULL, ++ /* .verify = */ ssh_gss_verify, ++}; ++ ++/* The struct is intentionally dummy and has no gss calls */ ++static const struct sshkey_impl sshkey_gss_kex_impl = { ++ /* .name = */ "null", ++ /* .shortname = */ "null", ++ /* .sigalg = */ NULL, ++ /* .type = */ KEY_NULL, ++ /* .nid = */ 0, ++ /* .cert = */ 0, ++ /* .sigonly = */ 0, ++ /* .keybits = */ 0, /* FIXME */ ++ /* .funcs = */ &sshkey_gss_funcs, ++}; + + const struct sshkey_impl * const keyimpls[] = { + &sshkey_ed25519_impl, +@@ -154,6 +154,7 @@ static const struct keytype keytypes[] = { + &sshkey_xmss_impl, + &sshkey_xmss_cert_impl, + #endif ++ &sshkey_gss_kex_impl, + NULL }; -@@ -286,7 +287,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) - const struct keytype *kt; +@@ -255,7 +256,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) - for (kt = keytypes; kt->type != -1; kt++) { -- if (kt->name == NULL) -+ if (kt->name == NULL || kt->type == KEY_NULL) + for (i = 0; keyimpls[i] != NULL; i++) { + impl = keyimpls[i]; +- if (impl->name == NULL) ++ if (impl->name == NULL || impl->type == KEY_NULL) continue; - if (!include_sigonly && kt->sigonly) + if (!include_sigonly && impl->sigonly) continue; diff --git a/sshkey.h b/sshkey.h -index be254e6..0e5ef9d 100644 +index 71a3fddc..37a43a67 100644 --- a/sshkey.h +++ b/sshkey.h -@@ -71,6 +71,7 @@ enum sshkey_types { +@@ -69,6 +69,7 @@ enum sshkey_types { KEY_ECDSA_SK_CERT, KEY_ED25519_SK, KEY_ED25519_SK_CERT, @@ -3956,6 +4007,3 @@ index be254e6..0e5ef9d 100644 KEY_UNSPEC }; --- -2.27.0 - diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index 95030c50fdec49672d9edbee40e70a80d7a139e6..affdd72c22145f6236bdcfd671c0f3f4641604c4 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -1,98 +1,7 @@ -Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-8.0p1-pkcs11-uri.patch - ---- - Makefile.in | 20 +- - configure.ac | 37 ++ - regress/agent-pkcs11.sh | 2 +- - regress/pkcs11.sh | 349 +++++++++++++++ - regress/unittests/pkcs11/tests.c | 337 +++++++++++++++ - ssh-add.c | 44 +- - ssh-agent.c | 101 ++++- - ssh-keygen.c | 7 +- - ssh-pkcs11-client.c | 3 + - ssh-pkcs11-uri.c | 419 ++++++++++++++++++ - ssh-pkcs11-uri.h | 42 ++ - ssh-pkcs11.c | 715 +++++++++++++++++++++++-------- - ssh-pkcs11.h | 4 + - ssh.c | 104 +++-- - ssh_config.5 | 15 + - 15 files changed, 1961 insertions(+), 238 deletions(-) - create mode 100644 regress/pkcs11.sh - create mode 100644 regress/unittests/pkcs11/tests.c - create mode 100644 ssh-pkcs11-uri.c - create mode 100644 ssh-pkcs11-uri.h - -diff --git a/Makefile.in b/Makefile.in -index 8229885..45f7a93 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -105,7 +105,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ - ssh-ed25519-sk.o ssh-rsa.o dh.o \ - msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ -- ssh-pkcs11.o smult_curve25519_ref.o \ -+ ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ - poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ - ssh-ed25519.o digest-openssl.o digest-libc.o \ - hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ -@@ -299,6 +299,8 @@ clean: regressclean - rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) - rm -f regress/unittests/utf8/*.o - rm -f regress/unittests/utf8/test_utf8$(EXEEXT) -+ rm -f regress/unittests/pkcs11/*.o -+ rm -f regress/unittests/pkcs11/test_pkcs11$(EXEEXT) - rm -f regress/misc/sk-dummy/*.o - rm -f regress/misc/sk-dummy/*.lo - rm -f regress/misc/sk-dummy/sk-dummy.so -@@ -336,6 +338,8 @@ distclean: regressclean - rm -f regress/unittests/sshsig/test_sshsig - rm -f regress/unittests/utf8/*.o - rm -f regress/unittests/utf8/test_utf8 -+ rm -f regress/unittests/pkcs11/*.o -+ rm -f regress/unittests/pkcs11/test_pkcs11 - rm -f regress/misc/sk-dummy/*.o - rm -f regress/misc/sk-dummy/*.lo - rm -f regress/misc/sk-dummy/sk-dummy.so -@@ -513,6 +517,7 @@ regress-prep: - $(MKDIR_P) `pwd`/regress/unittests/sshkey - $(MKDIR_P) `pwd`/regress/unittests/sshsig - $(MKDIR_P) `pwd`/regress/unittests/utf8 -+ $(MKDIR_P) `pwd`/regress/unittests/pkcs11 - $(MKDIR_P) `pwd`/regress/misc/sk-dummy - [ -f `pwd`/regress/Makefile ] || \ - ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile -@@ -679,6 +684,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \ - regress/unittests/test_helper/libtest_helper.a \ - -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) - -+UNITTESTS_TEST_PKCS11_OBJS=\ -+ regress/unittests/pkcs11/tests.o -+ -+regress/unittests/pkcs11/test_pkcs11$(EXEEXT): \ -+ ${UNITTESTS_TEST_PKCS11_OBJS} \ -+ regress/unittests/test_helper/libtest_helper.a libssh.a -+ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_PKCS11_OBJS) \ -+ regress/unittests/test_helper/libtest_helper.a \ -+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) -+ - # These all need to be compiled -fPIC, so they are treated differently. - SK_DUMMY_OBJS=\ - regress/misc/sk-dummy/sk-dummy.lo \ -@@ -713,7 +728,8 @@ regress-unit-binaries: regress-prep $(REGRESSLIBS) \ - regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ - regress/unittests/sshkey/test_sshkey$(EXEEXT) \ - regress/unittests/sshsig/test_sshsig$(EXEEXT) \ -- regress/unittests/utf8/test_utf8$(EXEEXT) -+ regress/unittests/utf8/test_utf8$(EXEEXT) \ -+ regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \ - - tests: file-tests t-exec interop-tests unit - echo all tests passed -diff --git a/configure.ac b/configure.ac -index 6f7dc48..b57d0a5 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -2035,12 +2035,14 @@ AC_LINK_IFELSE( +diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac +--- openssh-8.7p1/configure.ac.pkcs11-uri 2021-08-30 13:07:43.646699953 +0200 ++++ openssh-8.7p1/configure.ac 2021-08-30 13:07:43.662700088 +0200 +@@ -1985,12 +1985,14 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) @@ -107,7 +16,7 @@ index 6f7dc48..b57d0a5 100644 fi ] ) -@@ -2064,6 +2066,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) +@@ -2019,6 +2021,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_FUNCS([dlopen]) AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) @@ -148,7 +57,7 @@ index 6f7dc48..b57d0a5 100644 # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5651,6 +5687,7 @@ echo " BSD Auth support: $BSD_AUTH_MSG" +@@ -5624,6 +5660,7 @@ echo " BSD Auth support echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" @@ -156,10 +65,74 @@ index 6f7dc48..b57d0a5 100644 echo " U2F/FIDO support: $enable_sk" echo "" -diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh -index 268a70d..72efa3b 100644 ---- a/regress/agent-pkcs11.sh -+++ b/regress/agent-pkcs11.sh +diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in +--- openssh-8.7p1/Makefile.in.pkcs11-uri 2021-08-30 13:07:43.571699324 +0200 ++++ openssh-8.7p1/Makefile.in 2021-08-30 13:07:43.663700096 +0200 +@@ -103,7 +103,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ + ssh-ed25519-sk.o ssh-rsa.o dh.o \ + msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ +- ssh-pkcs11.o smult_curve25519_ref.o \ ++ ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ + poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ + ssh-ed25519.o digest-openssl.o digest-libc.o \ + hmac.o ed25519.o hash.o \ +@@ -302,6 +302,8 @@ clean: regressclean + rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) + rm -f regress/unittests/utf8/*.o + rm -f regress/unittests/utf8/test_utf8$(EXEEXT) ++ rm -f regress/unittests/pkcs11/*.o ++ rm -f regress/unittests/pkcs11/test_pkcs11$(EXEEXT) + rm -f regress/misc/sk-dummy/*.o + rm -f regress/misc/sk-dummy/*.lo + rm -f regress/misc/sk-dummy/sk-dummy.so +@@ -339,6 +341,8 @@ distclean: regressclean + rm -f regress/unittests/sshsig/test_sshsig + rm -f regress/unittests/utf8/*.o + rm -f regress/unittests/utf8/test_utf8 ++ rm -f regress/unittests/pkcs11/*.o ++ rm -f regress/unittests/pkcs11/test_pkcs11 + rm -f regress/misc/sk-dummy/*.o + rm -f regress/misc/sk-dummy/*.lo + rm -f regress/misc/sk-dummy/sk-dummy.so +@@ -513,6 +517,7 @@ regress-prep: + $(MKDIR_P) `pwd`/regress/unittests/sshkey + $(MKDIR_P) `pwd`/regress/unittests/sshsig + $(MKDIR_P) `pwd`/regress/unittests/utf8 ++ $(MKDIR_P) `pwd`/regress/unittests/pkcs11 + $(MKDIR_P) `pwd`/regress/misc/sk-dummy + [ -f `pwd`/regress/Makefile ] || \ + ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile +@@ -677,6 +682,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT + regress/unittests/test_helper/libtest_helper.a \ + -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) + ++UNITTESTS_TEST_PKCS11_OBJS=\ ++ regress/unittests/pkcs11/tests.o ++ ++regress/unittests/pkcs11/test_pkcs11$(EXEEXT): \ ++ ${UNITTESTS_TEST_PKCS11_OBJS} \ ++ regress/unittests/test_helper/libtest_helper.a libssh.a ++ $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_PKCS11_OBJS) \ ++ regress/unittests/test_helper/libtest_helper.a \ ++ -lssh -lopenbsd-compat -lcrypto $(LIBS) ++ + # These all need to be compiled -fPIC, so they are treated differently. + SK_DUMMY_OBJS=\ + regress/misc/sk-dummy/sk-dummy.lo \ +@@ -711,7 +726,8 @@ regress-unit-binaries: regress-prep $(RE + regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ + regress/unittests/sshkey/test_sshkey$(EXEEXT) \ + regress/unittests/sshsig/test_sshsig$(EXEEXT) \ +- regress/unittests/utf8/test_utf8$(EXEEXT) ++ regress/unittests/utf8/test_utf8$(EXEEXT) \ ++ regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \ + + tests: file-tests t-exec interop-tests unit + echo all tests passed +diff -up openssh-8.7p1/regress/agent-pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/agent-pkcs11.sh +--- openssh-8.7p1/regress/agent-pkcs11.sh.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/regress/agent-pkcs11.sh 2021-08-30 13:07:43.663700096 +0200 @@ -113,7 +113,7 @@ else done @@ -169,11 +142,34 @@ index 268a70d..72efa3b 100644 r=$? if [ $r -ne 0 ]; then fail "ssh-add -e failed: exit code $r" -diff --git a/regress/pkcs11.sh b/regress/pkcs11.sh -new file mode 100644 -index 0000000..a91aee9 ---- /dev/null -+++ b/regress/pkcs11.sh +diff -up openssh-8.7p1/regress/Makefile.pkcs11-uri openssh-8.7p1/regress/Makefile +--- openssh-8.7p1/regress/Makefile.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/regress/Makefile 2021-08-30 13:07:43.663700096 +0200 +@@ -122,7 +122,8 @@ CLEANFILES= *.core actual agent-key.* au + known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ + modpipe netcat no_identity_config \ + pidfile putty.rsa2 ready regress.log remote_pid \ +- revoked-* rsa rsa-agent rsa-agent.pub rsa.pub rsa_ssh2_cr.prv \ ++ revoked-* rsa rsa-agent rsa-agent.pub rsa-agent-cert.pub \ ++ rsa.pub rsa_ssh2_cr.prv pkcs11*.crt pkcs11*.key pkcs11.info \ + rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ + scp-ssh-wrapper.scp setuid-allowed sftp-server.log \ + sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ +@@ -252,8 +253,9 @@ unit: + V="" ; \ + test "x${USE_VALGRIND}" = "x" || \ + V=${.CURDIR}/valgrind-unit.sh ; \ +- $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ +- $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ ++ $$V ${.OBJDIR}/unittests/pkcs11/test_pkcs11 ; \ ++ $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ ++ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ + -d ${.CURDIR}/unittests/sshkey/testdata ; \ + $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ + -d ${.CURDIR}/unittests/sshsig/testdata ; \ +diff -up openssh-8.7p1/regress/pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/pkcs11.sh +--- openssh-8.7p1/regress/pkcs11.sh.pkcs11-uri 2021-08-30 13:07:43.663700096 +0200 ++++ openssh-8.7p1/regress/pkcs11.sh 2021-08-30 13:07:43.663700096 +0200 @@ -0,0 +1,349 @@ +# +# Copyright (c) 2017 Red Hat @@ -524,11 +520,20 @@ index 0000000..a91aee9 + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi -diff --git a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c -new file mode 100644 -index 0000000..d726fdf ---- /dev/null -+++ b/regress/unittests/pkcs11/tests.c +diff -up openssh-8.7p1/regress/unittests/Makefile.pkcs11-uri openssh-8.7p1/regress/unittests/Makefile +--- openssh-8.7p1/regress/unittests/Makefile.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/regress/unittests/Makefile 2021-08-30 13:07:43.663700096 +0200 +@@ -2,6 +2,6 @@ + + REGRESS_FAIL_EARLY?= yes + SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion +-SUBDIR+=authopt misc sshsig ++SUBDIR+=authopt misc sshsig pkcs11 + + .include +diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1/regress/unittests/pkcs11/tests.c +--- openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri 2021-08-30 13:07:43.664700104 +0200 ++++ openssh-8.7p1/regress/unittests/pkcs11/tests.c 2021-08-30 13:07:43.664700104 +0200 @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2017 Red Hat @@ -867,11 +872,10 @@ index 0000000..d726fdf + test_parse_invalid(); + test_generate_valid(); +} -diff --git a/ssh-add.c b/ssh-add.c -index 777f21e..940e3a0 100644 ---- a/ssh-add.c -+++ b/ssh-add.c -@@ -69,6 +69,7 @@ +diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c +--- openssh-8.7p1/ssh-add.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/ssh-add.c 2021-08-30 13:07:43.664700104 +0200 +@@ -68,6 +68,7 @@ #include "ssh-sk.h" #include "sk-api.h" #include "hostfile.h" @@ -879,7 +883,7 @@ index 777f21e..940e3a0 100644 /* argv0 */ extern char *__progname; -@@ -230,6 +231,34 @@ delete_all(int agent_fd, int qflag) +@@ -229,6 +230,34 @@ delete_all(int agent_fd, int qflag) return ret; } @@ -914,7 +918,7 @@ index 777f21e..940e3a0 100644 static int add_file(int agent_fd, const char *filename, int key_only, int qflag, const char *skprovider, struct dest_constraint **dest_constraints, -@@ -445,12 +474,11 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, +@@ -445,12 +472,11 @@ add_file(int agent_fd, const char *filen static int update_card(int agent_fd, int add, const char *id, int qflag, @@ -929,7 +933,7 @@ index 777f21e..940e3a0 100644 if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; -@@ -634,6 +662,14 @@ do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, +@@ -630,6 +656,14 @@ static int const char *skprovider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { @@ -944,7 +948,7 @@ index 777f21e..940e3a0 100644 if (deleting) { if (delete_file(agent_fd, file, key_only, qflag) == -1) return -1; -@@ -960,7 +996,7 @@ main(int argc, char **argv) +@@ -813,7 +846,7 @@ main(int argc, char **argv) } if (pkcs11provider != NULL) { if (update_card(agent_fd, !deleting, pkcs11provider, @@ -953,11 +957,10 @@ index 777f21e..940e3a0 100644 ret = 1; goto done; } -diff --git a/ssh-agent.c b/ssh-agent.c -index 006ddad..50d0638 100644 ---- a/ssh-agent.c -+++ b/ssh-agent.c -@@ -1369,10 +1369,72 @@ no_identities(SocketEntry *e) +diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c +--- openssh-8.7p1/ssh-agent.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/ssh-agent.c 2021-08-30 13:07:43.664700104 +0200 +@@ -847,10 +847,72 @@ no_identities(SocketEntry *e) } #ifdef ENABLE_PKCS11 @@ -1031,7 +1034,7 @@ index 006ddad..50d0638 100644 char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds = 0; -@@ -1393,33 +1455,28 @@ process_add_smartcard_key(SocketEntry *e) +@@ -869,33 +931,28 @@ process_add_smartcard_key(SocketEntry *e error_f("failed to parse constraints"); goto send; } @@ -1073,15 +1076,15 @@ index 006ddad..50d0638 100644 } id->death = death; id->confirm = confirm; -@@ -1438,6 +1495,7 @@ process_add_smartcard_key(SocketEntry *e) +@@ -910,6 +967,7 @@ process_add_smartcard_key(SocketEntry *e send: free(pin); free(provider); + free(sane_uri); free(keys); free(comments); - free_dest_constraints(dest_constraints, ndest_constraints); -@@ -1447,7 +1505,7 @@ send: + free_dest_constraints(dest_constraints, ndest_constraints); +@@ -918,7 +976,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { @@ -1090,7 +1093,7 @@ index 006ddad..50d0638 100644 int r, success = 0; Identity *id, *nxt; -@@ -1459,30 +1517,29 @@ process_remove_smartcard_key(SocketEntry *e) +@@ -930,30 +988,29 @@ process_remove_smartcard_key(SocketEntry } free(pin); @@ -1127,522 +1130,221 @@ index 006ddad..50d0638 100644 send_status(e, success); } #endif /* ENABLE_PKCS11 */ -diff --git a/ssh-keygen.c b/ssh-keygen.c -index 9b2beda..1a7de44 100644 ---- a/ssh-keygen.c -+++ b/ssh-keygen.c -@@ -864,8 +864,11 @@ do_download(struct passwd *pw) - free(fp); - } else { - (void) sshkey_write(keys[i], stdout); /* XXX check */ -- fprintf(stdout, "%s%s\n", -- *(comments[i]) == '\0' ? "" : " ", comments[i]); -+ if (*(comments[i]) != '\0') { -+ fprintf(stdout, " %s", comments[i]); +diff -up openssh-8.7p1/ssh_config.5.pkcs11-uri openssh-8.7p1/ssh_config.5 +--- openssh-8.7p1/ssh_config.5.pkcs11-uri 2021-08-30 13:07:43.578699383 +0200 ++++ openssh-8.7p1/ssh_config.5 2021-08-30 13:07:43.664700104 +0200 +@@ -1111,6 +1111,21 @@ may also be used in conjunction with + .Cm CertificateFile + in order to provide any certificate also needed for authentication with + the identity. ++.Pp ++The authentication identity can be also specified in a form of PKCS#11 URI ++starting with a string ++.Cm pkcs11: . ++There is supported a subset of the PKCS#11 URI as defined ++in RFC 7512 (implemented path arguments ++.Cm id , ++.Cm manufacturer , ++.Cm object , ++.Cm token ++and query arguments ++.Cm module-path ++and ++.Cm pin-value ++). The URI can not be in quotes. + .It Cm IgnoreUnknown + Specifies a pattern-list of unknown options to be ignored if they are + encountered in configuration parsing. +diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c +--- openssh-8.7p1/ssh.c.pkcs11-uri 2021-08-30 13:07:43.578699383 +0200 ++++ openssh-8.7p1/ssh.c 2021-08-30 13:07:43.666700121 +0200 +@@ -826,6 +826,14 @@ main(int ac, char **av) + options.gss_deleg_creds = 1; + break; + case 'i': ++#ifdef ENABLE_PKCS11 ++ if (strlen(optarg) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(optarg, PKCS11_URI_SCHEME, ++ strlen(PKCS11_URI_SCHEME)) == 0) { ++ add_identity_file(&options, NULL, optarg, 1); ++ break; + } -+ (void) pkcs11_uri_write(keys[i], stdout); -+ fprintf(stdout, "\n"); - } - free(comments[i]); - sshkey_free(keys[i]); -diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c -index cfd833d..9e4f02b 100644 ---- a/ssh-pkcs11-client.c -+++ b/ssh-pkcs11-client.c -@@ -323,6 +323,8 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, - u_int nkeys, i; - struct sshbuf *msg; ++#endif + p = tilde_expand_filename(optarg, getuid()); + if (stat(p, &st) == -1) + fprintf(stderr, "Warning: Identity file %s " +@@ -1681,6 +1689,7 @@ main(int ac, char **av) + #ifdef ENABLE_PKCS11 + (void)pkcs11_del_provider(options.pkcs11_provider); + #endif ++ pkcs11_terminate(); -+ debug_f("called, name = %s", name); -+ - if (fd < 0 && pkcs11_start_helper() < 0) - return (-1); + skip_connect: + exit_status = ssh_session2(ssh, cinfo); +@@ -2197,6 +2206,45 @@ ssh_session2(struct ssh *ssh, const stru + options.escape_char : SSH_ESCAPECHAR_NONE, id); + } -@@ -342,6 +344,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, - *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); - if (labelsp) - *labelsp = xcalloc(nkeys, sizeof(char *)); -+ debug_f("nkeys = %u", nkeys); - for (i = 0; i < nkeys; i++) { - /* XXX clean up properly instead of fatal() */ - if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || -diff --git a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c -new file mode 100644 -index 0000000..a8a4946 ---- /dev/null -+++ b/ssh-pkcs11-uri.c -@@ -0,0 +1,419 @@ -+/* -+ * Copyright (c) 2017 Red Hat -+ * -+ * Authors: Jakub Jelen -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include "includes.h" -+ +#ifdef ENABLE_PKCS11 ++static void ++load_pkcs11_identity(char *pkcs11_uri, char *identity_files[], ++ struct sshkey *identity_keys[], int *n_ids) ++{ ++ int nkeys, i; ++ struct sshkey **keys; ++ struct pkcs11_uri *uri; + -+#include -+#include -+ -+#include "sshkey.h" -+#include "sshbuf.h" -+#include "log.h" ++ debug("identity file '%s' from pkcs#11", pkcs11_uri); ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); + -+#define CRYPTOKI_COMPAT -+#include "pkcs11.h" ++ if (pkcs11_uri_parse(pkcs11_uri, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri); + -+#include "ssh-pkcs11-uri.h" ++ /* we need to merge URI and provider together */ ++ if (options.pkcs11_provider != NULL && uri->module_path == NULL) ++ uri->module_path = strdup(options.pkcs11_provider); + -+#define PKCS11_URI_PATH_SEPARATOR ";" -+#define PKCS11_URI_QUERY_SEPARATOR "&" -+#define PKCS11_URI_VALUE_SEPARATOR "=" -+#define PKCS11_URI_ID "id" -+#define PKCS11_URI_TOKEN "token" -+#define PKCS11_URI_OBJECT "object" -+#define PKCS11_URI_LIB_MANUF "library-manufacturer" -+#define PKCS11_URI_MANUF "manufacturer" -+#define PKCS11_URI_MODULE_PATH "module-path" -+#define PKCS11_URI_PIN_VALUE "pin-value" ++ if (options.num_identity_files < SSH_MAX_IDENTITY_FILES && ++ (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys, NULL)) > 0) { ++ for (i = 0; i < nkeys; i++) { ++ if (*n_ids >= SSH_MAX_IDENTITY_FILES) { ++ sshkey_free(keys[i]); ++ continue; ++ } ++ identity_keys[*n_ids] = keys[i]; ++ identity_files[*n_ids] = pkcs11_uri_get(uri); ++ (*n_ids)++; ++ } ++ free(keys); ++ } + -+/* Keyword tokens. */ -+typedef enum { -+ pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pModulePath, -+ pPinValue, pBadOption -+} pkcs11uriOpCodes; ++ pkcs11_uri_cleanup(uri); ++} ++#endif /* ENABLE_PKCS11 */ + -+/* Textual representation of the tokens. */ -+static struct { -+ const char *name; -+ pkcs11uriOpCodes opcode; -+} keywords[] = { -+ { PKCS11_URI_ID, pId }, -+ { PKCS11_URI_TOKEN, pToken }, -+ { PKCS11_URI_OBJECT, pObject }, -+ { PKCS11_URI_LIB_MANUF, pLibraryManufacturer }, -+ { PKCS11_URI_MANUF, pManufacturer }, -+ { PKCS11_URI_MODULE_PATH, pModulePath }, -+ { PKCS11_URI_PIN_VALUE, pPinValue }, -+ { NULL, pBadOption } -+}; -+ -+static pkcs11uriOpCodes -+parse_token(const char *cp) -+{ -+ u_int i; -+ -+ for (i = 0; keywords[i].name; i++) -+ if (strncasecmp(cp, keywords[i].name, -+ strlen(keywords[i].name)) == 0) -+ return keywords[i].opcode; -+ -+ return pBadOption; -+} -+ -+int -+percent_decode(char *data, char **outp) -+{ -+ char tmp[3]; -+ char *out, *tmp_end; -+ char *p = data; -+ long value; -+ size_t outlen = 0; -+ -+ out = malloc(strlen(data)+1); /* upper bound */ -+ if (out == NULL) -+ return -1; -+ while (*p != '\0') { -+ switch (*p) { -+ case '%': -+ p++; -+ if (*p == '\0') -+ goto fail; -+ tmp[0] = *p++; -+ if (*p == '\0') -+ goto fail; -+ tmp[1] = *p++; -+ tmp[2] = '\0'; -+ tmp_end = NULL; -+ value = strtol(tmp, &tmp_end, 16); -+ if (tmp_end != tmp+2) -+ goto fail; -+ else -+ out[outlen++] = (char) value; -+ break; -+ default: -+ out[outlen++] = *p++; -+ break; -+ } -+ } -+ -+ /* zero terminate */ -+ out[outlen] = '\0'; -+ *outp = out; -+ return outlen; -+fail: -+ free(out); -+ return -1; -+} -+ -+struct sshbuf * -+percent_encode(const char *data, size_t length, const char *allow_list) -+{ -+ struct sshbuf *b = NULL; -+ char tmp[4], *cp; -+ size_t i; -+ -+ if ((b = sshbuf_new()) == NULL) -+ return NULL; -+ for (i = 0; i < length; i++) { -+ cp = strchr(allow_list, data[i]); -+ /* if c is specified as '\0' pointer to terminator is returned !! */ -+ if (cp != NULL && *cp != '\0') { -+ if (sshbuf_put(b, &data[i], 1) != 0) -+ goto err; -+ } else -+ if (snprintf(tmp, 4, "%%%02X", (unsigned char) data[i]) < 3 -+ || sshbuf_put(b, tmp, 3) != 0) -+ goto err; -+ } -+ if (sshbuf_put(b, "\0", 1) == 0) -+ return b; -+err: -+ sshbuf_free(b); -+ return NULL; -+} -+ -+char * -+pkcs11_uri_append(char *part, const char *separator, const char *key, -+ struct sshbuf *value) -+{ -+ char *new_part; -+ size_t size = 0; -+ -+ if (value == NULL) -+ return NULL; -+ -+ size = asprintf(&new_part, -+ "%s%s%s" PKCS11_URI_VALUE_SEPARATOR "%s", -+ (part != NULL ? part : ""), -+ (part != NULL ? separator : ""), -+ key, sshbuf_ptr(value)); -+ sshbuf_free(value); -+ free(part); -+ -+ if (size <= 0) -+ return NULL; -+ return new_part; -+} -+ -+char * -+pkcs11_uri_get(struct pkcs11_uri *uri) -+{ -+ size_t size = 0; -+ char *p = NULL, *path = NULL, *query = NULL; -+ -+ /* compose a percent-encoded ID */ -+ if (uri->id_len > 0) { -+ struct sshbuf *key_id = percent_encode(uri->id, uri->id_len, ""); -+ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, -+ PKCS11_URI_ID, key_id); -+ if (path == NULL) -+ goto err; -+ } -+ -+ /* Write object label */ -+ if (uri->object) { -+ struct sshbuf *label = percent_encode(uri->object, strlen(uri->object), -+ PKCS11_URI_WHITELIST); -+ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, -+ PKCS11_URI_OBJECT, label); -+ if (path == NULL) -+ goto err; -+ } -+ -+ /* Write token label */ -+ if (uri->token) { -+ struct sshbuf *label = percent_encode(uri->token, strlen(uri->token), -+ PKCS11_URI_WHITELIST); -+ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, -+ PKCS11_URI_TOKEN, label); -+ if (path == NULL) -+ goto err; -+ } -+ -+ /* Write manufacturer */ -+ if (uri->manuf) { -+ struct sshbuf *manuf = percent_encode(uri->manuf, -+ strlen(uri->manuf), PKCS11_URI_WHITELIST); -+ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, -+ PKCS11_URI_MANUF, manuf); -+ if (path == NULL) -+ goto err; -+ } -+ -+ /* Write module_path */ -+ if (uri->module_path) { -+ struct sshbuf *module = percent_encode(uri->module_path, -+ strlen(uri->module_path), PKCS11_URI_WHITELIST "/"); -+ query = pkcs11_uri_append(query, PKCS11_URI_QUERY_SEPARATOR, -+ PKCS11_URI_MODULE_PATH, module); -+ if (query == NULL) -+ goto err; -+ } -+ -+ size = asprintf(&p, PKCS11_URI_SCHEME "%s%s%s", -+ path != NULL ? path : "", -+ query != NULL ? "?" : "", -+ query != NULL ? query : ""); -+err: -+ free(query); -+ free(path); -+ if (size <= 0) -+ return NULL; -+ return p; -+} -+ -+struct pkcs11_uri * -+pkcs11_uri_init() -+{ -+ struct pkcs11_uri *d = calloc(1, sizeof(struct pkcs11_uri)); -+ return d; -+} -+ -+void -+pkcs11_uri_cleanup(struct pkcs11_uri *pkcs11) -+{ -+ if (pkcs11 == NULL) { -+ return; -+ } -+ -+ free(pkcs11->id); -+ free(pkcs11->module_path); -+ free(pkcs11->token); -+ free(pkcs11->object); -+ free(pkcs11->lib_manuf); -+ free(pkcs11->manuf); -+ if (pkcs11->pin) -+ freezero(pkcs11->pin, strlen(pkcs11->pin)); -+ free(pkcs11); -+} -+ -+int -+pkcs11_uri_parse(const char *uri, struct pkcs11_uri *pkcs11) -+{ -+ char *saveptr1, *saveptr2, *str1, *str2, *tok; -+ int rv = 0, len; -+ char *p = NULL; -+ -+ size_t scheme_len = strlen(PKCS11_URI_SCHEME); -+ if (strlen(uri) < scheme_len || /* empty URI matches everything */ -+ strncmp(uri, PKCS11_URI_SCHEME, scheme_len) != 0) { -+ error_f("The '%s' does not look like PKCS#11 URI", uri); -+ return -1; -+ } -+ -+ if (pkcs11 == NULL) { -+ error_f("Bad arguments. The pkcs11 can't be null"); -+ return -1; -+ } -+ -+ /* skip URI schema name */ -+ p = strdup(uri); -+ str1 = p; -+ -+ /* everything before ? */ -+ tok = strtok_r(str1, "?", &saveptr1); -+ if (tok == NULL) { -+ error_f("pk11-path expected, got EOF"); -+ rv = -1; -+ goto out; -+ } -+ -+ /* skip URI schema name: -+ * the scheme ensures that there is at least something before "?" -+ * allowing empty pk11-path. Resulting token at worst pointing to -+ * \0 byte */ -+ tok = tok + scheme_len; -+ -+ /* parse pk11-path */ -+ for (str2 = tok; ; str2 = NULL) { -+ char **charptr, *arg = NULL; -+ pkcs11uriOpCodes opcode; -+ tok = strtok_r(str2, PKCS11_URI_PATH_SEPARATOR, &saveptr2); -+ if (tok == NULL) -+ break; -+ opcode = parse_token(tok); -+ if (opcode != pBadOption) -+ arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */ -+ -+ switch (opcode) { -+ case pId: -+ /* CKA_ID */ -+ if (pkcs11->id != NULL) { -+ verbose_f("The id already set in the PKCS#11 URI"); -+ rv = -1; -+ goto out; -+ } -+ len = percent_decode(arg, &pkcs11->id); -+ if (len <= 0) { -+ verbose_f("Failed to percent-decode CKA_ID: %s", arg); -+ rv = -1; -+ goto out; -+ } else -+ pkcs11->id_len = len; -+ debug3_f("Setting CKA_ID = %s from PKCS#11 URI", arg); -+ break; -+ case pToken: -+ /* CK_TOKEN_INFO -> label */ -+ charptr = &pkcs11->token; -+ parse_string: -+ if (*charptr != NULL) { -+ verbose_f("The %s already set in the PKCS#11 URI", -+ keywords[opcode].name); -+ rv = -1; -+ goto out; -+ } -+ percent_decode(arg, charptr); -+ debug3_f("Setting %s = %s from PKCS#11 URI", -+ keywords[opcode].name, *charptr); -+ break; -+ -+ case pObject: -+ /* CK_TOKEN_INFO -> manufacturerID */ -+ charptr = &pkcs11->object; -+ goto parse_string; -+ -+ case pManufacturer: -+ /* CK_TOKEN_INFO -> manufacturerID */ -+ charptr = &pkcs11->manuf; -+ goto parse_string; -+ -+ case pLibraryManufacturer: -+ /* CK_INFO -> manufacturerID */ -+ charptr = &pkcs11->lib_manuf; -+ goto parse_string; + /* Loads all IdentityFile and CertificateFile keys */ + static void + load_public_identity_files(const struct ssh_conn_info *cinfo) +@@ -2211,11 +2259,6 @@ load_public_identity_files(const struct + char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; + struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; + int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; +-#ifdef ENABLE_PKCS11 +- struct sshkey **keys = NULL; +- char **comments = NULL; +- int nkeys; +-#endif /* PKCS11 */ + + n_ids = n_certs = 0; + memset(identity_files, 0, sizeof(identity_files)); +@@ -2228,33 +2271,46 @@ load_public_identity_files(const struct + sizeof(certificate_file_userprovided)); + + #ifdef ENABLE_PKCS11 +- if (options.pkcs11_provider != NULL && +- options.num_identity_files < SSH_MAX_IDENTITY_FILES && +- (pkcs11_init(!options.batch_mode) == 0) && +- (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, +- &keys, &comments)) > 0) { +- for (i = 0; i < nkeys; i++) { +- if (n_ids >= SSH_MAX_IDENTITY_FILES) { +- sshkey_free(keys[i]); +- free(comments[i]); +- continue; +- } +- identity_keys[n_ids] = keys[i]; +- identity_files[n_ids] = comments[i]; /* transferred */ +- n_ids++; +- } +- free(keys); +- free(comments); ++ /* handle fallback from PKCS11Provider option */ ++ pkcs11_init(!options.batch_mode); + -+ default: -+ /* Unrecognized attribute in the URI path SHOULD be error */ -+ verbose_f("Unknown part of path in PKCS#11 URI: %s", tok); -+ } -+ } ++ if (options.pkcs11_provider != NULL) { ++ struct pkcs11_uri *uri; + -+ tok = strtok_r(NULL, "?", &saveptr1); -+ if (tok == NULL) { -+ goto out; -+ } -+ /* parse pk11-query (optional) */ -+ for (str2 = tok; ; str2 = NULL) { -+ char *arg; -+ pkcs11uriOpCodes opcode; -+ tok = strtok_r(str2, PKCS11_URI_QUERY_SEPARATOR, &saveptr2); -+ if (tok == NULL) -+ break; -+ opcode = parse_token(tok); -+ if (opcode != pBadOption) -+ arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); + -+ switch (opcode) { -+ case pModulePath: -+ /* module-path is PKCS11Provider */ -+ if (pkcs11->module_path != NULL) { -+ verbose_f("Multiple module-path attributes are" -+ "not supported the PKCS#11 URI"); -+ rv = -1; -+ goto out; -+ } -+ percent_decode(arg, &pkcs11->module_path); -+ debug3_f("Setting PKCS11Provider = %s from PKCS#11 URI", -+ pkcs11->module_path); -+ break; ++ /* Construct simple PKCS#11 URI to simplify access */ ++ uri->module_path = strdup(options.pkcs11_provider); + -+ case pPinValue: -+ /* pin-value */ -+ if (pkcs11->pin != NULL) { -+ verbose_f("Multiple pin-value attributes are" -+ "not supported the PKCS#11 URI"); -+ rv = -1; -+ goto out; -+ } -+ percent_decode(arg, &pkcs11->pin); -+ debug3_f("Setting PIN from PKCS#11 URI"); -+ break; ++ /* Add it as any other IdentityFile */ ++ cp = pkcs11_uri_get(uri); ++ add_identity_file(&options, NULL, cp, 1); ++ free(cp); + -+ default: -+ /* Unrecognized attribute in the URI query SHOULD be ignored */ -+ verbose_f("Unknown part of query in PKCS#11 URI: %s", tok); ++ pkcs11_uri_cleanup(uri); + } + #endif /* ENABLE_PKCS11 */ + for (i = 0; i < options.num_identity_files; i++) { ++ char *name = options.identity_files[i]; + if (n_ids >= SSH_MAX_IDENTITY_FILES || +- strcasecmp(options.identity_files[i], "none") == 0) { ++ strcasecmp(name, "none") == 0) { + free(options.identity_files[i]); + options.identity_files[i] = NULL; + continue; + } +- cp = tilde_expand_filename(options.identity_files[i], getuid()); ++#ifdef ENABLE_PKCS11 ++ if (strlen(name) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(name, PKCS11_URI_SCHEME, ++ strlen(PKCS11_URI_SCHEME)) == 0) { ++ load_pkcs11_identity(name, identity_files, ++ identity_keys, &n_ids); ++ free(options.identity_files[i]); ++ continue; + } -+ } -+out: -+ free(p); -+ return rv; -+} -+ +#endif /* ENABLE_PKCS11 */ -diff --git a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h -new file mode 100644 -index 0000000..942a5a5 ---- /dev/null -+++ b/ssh-pkcs11-uri.h -@@ -0,0 +1,42 @@ -+/* -+ * Copyright (c) 2017 Red Hat -+ * -+ * Authors: Jakub Jelen -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#define PKCS11_URI_SCHEME "pkcs11:" -+#define PKCS11_URI_WHITELIST "abcdefghijklmnopqrstuvwxyz" \ -+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ -+ "0123456789_-.()" -+ -+struct pkcs11_uri { -+ /* path */ -+ char *id; -+ size_t id_len; -+ char *token; -+ char *object; -+ char *lib_manuf; -+ char *manuf; -+ /* query */ -+ char *module_path; -+ char *pin; /* Only parsed, but not printed */ -+}; -+ -+struct pkcs11_uri *pkcs11_uri_init(); -+void pkcs11_uri_cleanup(struct pkcs11_uri *); -+int pkcs11_uri_parse(const char *, struct pkcs11_uri *); -+struct pkcs11_uri *pkcs11_uri_init(); -+char *pkcs11_uri_get(struct pkcs11_uri *uri); ++ cp = tilde_expand_filename(name, getuid()); + filename = default_client_percent_dollar_expand(cp, cinfo); + free(cp); + check_load(sshkey_load_public(filename, &public, NULL), +diff -up openssh-8.7p1/ssh-keygen.c.pkcs11-uri openssh-8.7p1/ssh-keygen.c +--- openssh-8.7p1/ssh-keygen.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/ssh-keygen.c 2021-08-30 13:07:43.666700121 +0200 +@@ -860,8 +860,11 @@ do_download(struct passwd *pw) + free(fp); + } else { + (void) sshkey_write(keys[i], stdout); /* XXX check */ +- fprintf(stdout, "%s%s\n", +- *(comments[i]) == '\0' ? "" : " ", comments[i]); ++ if (*(comments[i]) != '\0') { ++ fprintf(stdout, " %s", comments[i]); ++ } ++ (void) pkcs11_uri_write(keys[i], stdout); ++ fprintf(stdout, "\n"); + } + free(comments[i]); + sshkey_free(keys[i]); +diff -up openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-client.c +--- openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/ssh-pkcs11-client.c 2021-08-30 13:07:43.666700121 +0200 +@@ -323,6 +323,8 @@ pkcs11_add_provider(char *name, char *pi + u_int nkeys, i; + struct sshbuf *msg; + ++ debug_f("called, name = %s", name); + -diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c -index b2e2b32..720ae2a 100644 ---- a/ssh-pkcs11.c -+++ b/ssh-pkcs11.c + if (fd < 0 && pkcs11_start_helper() < 0) + return (-1); + +@@ -342,6 +344,7 @@ pkcs11_add_provider(char *name, char *pi + *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); + if (labelsp) + *labelsp = xcalloc(nkeys, sizeof(char *)); ++ debug_f("nkeys = %u", nkeys); + for (i = 0; i < nkeys; i++) { + /* XXX clean up properly instead of fatal() */ + if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || +diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c +--- openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/ssh-pkcs11.c 2021-08-30 13:12:27.709084157 +0200 @@ -55,8 +55,8 @@ struct pkcs11_slotinfo { int logged_in; }; @@ -1749,7 +1451,7 @@ index b2e2b32..720ae2a 100644 } /* -@@ -137,11 +180,9 @@ pkcs11_provider_unref(struct pkcs11_provider *p) +@@ -137,11 +180,9 @@ pkcs11_provider_unref(struct pkcs11_prov { debug_f("provider \"%s\" refcount %d", p->name, p->refcount); if (--p->refcount <= 0) { @@ -1784,7 +1486,7 @@ index b2e2b32..720ae2a 100644 /* lookup provider by name */ static struct pkcs11_provider * pkcs11_provider_lookup(char *provider_id) -@@ -173,19 +228,55 @@ pkcs11_provider_lookup(char *provider_id) +@@ -173,19 +228,55 @@ pkcs11_provider_lookup(char *provider_id return (NULL); } @@ -1793,7 +1495,7 @@ index b2e2b32..720ae2a 100644 /* unregister provider by name */ int pkcs11_del_provider(char *provider_id) -+{ + { + int rv; + struct pkcs11_uri *uri; + @@ -1822,7 +1524,7 @@ index b2e2b32..720ae2a 100644 +/* unregister provider by PKCS#11 URI */ +int +pkcs11_del_provider_by_uri(struct pkcs11_uri *uri) - { ++{ struct pkcs11_provider *p; + int rv = -1; + char *provider_uri = pkcs11_uri_get(uri); @@ -1899,7 +1601,7 @@ index b2e2b32..720ae2a 100644 /* release a wrapped object */ static void pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, -@@ -208,6 +348,7 @@ pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, +@@ -208,6 +348,7 @@ pkcs11_k11_free(void *parent, void *ptr, if (k11->provider) pkcs11_provider_unref(k11->provider); free(k11->keyid); @@ -1907,7 +1609,7 @@ index b2e2b32..720ae2a 100644 free(k11); } -@@ -222,8 +363,8 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, +@@ -222,8 +363,8 @@ pkcs11_find(struct pkcs11_provider *p, C CK_RV rv; int ret = -1; @@ -1918,7 +1620,7 @@ index b2e2b32..720ae2a 100644 if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); return (-1); -@@ -262,12 +403,12 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, +@@ -262,12 +403,12 @@ pkcs11_login_slot(struct pkcs11_provider else { snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", si->token.label); @@ -1933,7 +1635,7 @@ index b2e2b32..720ae2a 100644 (pin != NULL) ? strlen(pin) : 0); if (pin != NULL) freezero(pin, strlen(pin)); -@@ -297,13 +438,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, +@@ -297,13 +438,14 @@ pkcs11_login_slot(struct pkcs11_provider static int pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) { @@ -1950,7 +1652,7 @@ index b2e2b32..720ae2a 100644 } -@@ -319,13 +461,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, +@@ -319,13 +461,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs *val = 0; @@ -1968,7 +1670,7 @@ index b2e2b32..720ae2a 100644 attr.type = type; attr.pValue = &flag; -@@ -356,13 +499,14 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) +@@ -356,13 +499,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C int always_auth = 0; int did_login = 0; @@ -1986,7 +1688,7 @@ index b2e2b32..720ae2a 100644 if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { if (pkcs11_login(k11, CKU_USER) < 0) { -@@ -439,8 +583,8 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, +@@ -439,8 +583,8 @@ pkcs11_rsa_private_encrypt(int flen, con return (-1); } @@ -2006,7 +1708,7 @@ index b2e2b32..720ae2a 100644 { struct pkcs11_key *k11; -@@ -502,6 +646,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, +@@ -502,6 +646,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } @@ -2019,7 +1721,7 @@ index b2e2b32..720ae2a 100644 RSA_set_method(rsa, rsa_method); RSA_set_ex_data(rsa, rsa_idx, k11); return (0); -@@ -532,8 +682,8 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, +@@ -532,8 +682,8 @@ ecdsa_do_sign(const unsigned char *dgst, return (NULL); } @@ -2039,10 +1741,10 @@ index b2e2b32..720ae2a 100644 { struct pkcs11_key *k11; -@@ -615,6 +765,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, +@@ -614,6 +764,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider k11->keyid = xmalloc(k11->keyid_len); memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); - } + } + if (label_attrib->ulValueLen > 0 ) { + k11->label = xmalloc(label_attrib->ulValueLen+1); + memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); @@ -2052,7 +1754,7 @@ index b2e2b32..720ae2a 100644 EC_KEY_set_method(ec, ec_key_method); EC_KEY_set_ex_data(ec, ec_key_idx, k11); -@@ -651,8 +807,8 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, +@@ -650,8 +806,8 @@ pkcs11_open_session(struct pkcs11_provid CK_SESSION_HANDLE session; int login_required, ret; @@ -2063,7 +1765,7 @@ index b2e2b32..720ae2a 100644 login_required = si->token.flags & CKF_LOGIN_REQUIRED; -@@ -662,9 +818,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, +@@ -661,9 +817,9 @@ pkcs11_open_session(struct pkcs11_provid error("pin required"); return (-SSH_PKCS11_ERR_PIN_REQUIRED); } @@ -2075,7 +1777,7 @@ index b2e2b32..720ae2a 100644 return (-1); } if (login_required && pin != NULL && strlen(pin) != 0) { -@@ -700,7 +856,8 @@ static struct sshkey * +@@ -699,7 +855,8 @@ static struct sshkey * pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -2085,7 +1787,7 @@ index b2e2b32..720ae2a 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -714,14 +871,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -713,14 +870,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -2106,7 +1808,7 @@ index b2e2b32..720ae2a 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -732,19 +890,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -731,19 +889,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -2130,7 +1832,7 @@ index b2e2b32..720ae2a 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -756,8 +914,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -755,8 +913,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -2141,7 +1843,7 @@ index b2e2b32..720ae2a 100644 if (group == NULL) { ossl_error("d2i_ECPKParameters failed"); goto fail; -@@ -768,13 +926,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -767,13 +925,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -2158,7 +1860,7 @@ index b2e2b32..720ae2a 100644 if (octet == NULL) { ossl_error("d2i_ASN1_OCTET_STRING failed"); goto fail; -@@ -791,7 +949,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -790,7 +948,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -2167,7 +1869,7 @@ index b2e2b32..720ae2a 100644 goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -807,7 +965,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -806,7 +964,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ ec = NULL; /* now owned by key */ fail: @@ -2176,7 +1878,7 @@ index b2e2b32..720ae2a 100644 free(key_attr[i].pValue); if (ec) EC_KEY_free(ec); -@@ -824,7 +982,8 @@ static struct sshkey * +@@ -823,7 +981,8 @@ static struct sshkey * pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -2186,7 +1888,7 @@ index b2e2b32..720ae2a 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -835,14 +994,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -834,14 +993,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -2207,7 +1909,7 @@ index b2e2b32..720ae2a 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -853,19 +1013,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -852,19 +1012,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -2231,7 +1933,7 @@ index b2e2b32..720ae2a 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -877,8 +1037,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -876,8 +1036,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr goto fail; } @@ -2242,7 +1944,7 @@ index b2e2b32..720ae2a 100644 if (rsa_n == NULL || rsa_e == NULL) { error("BN_bin2bn failed"); goto fail; -@@ -887,7 +1047,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -886,7 +1046,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr fatal_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ @@ -2251,7 +1953,7 @@ index b2e2b32..720ae2a 100644 goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -902,7 +1062,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -901,7 +1061,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr rsa = NULL; /* now owned by key */ fail: @@ -2260,7 +1962,7 @@ index b2e2b32..720ae2a 100644 free(key_attr[i].pValue); RSA_free(rsa); -@@ -913,7 +1073,8 @@ static int +@@ -912,7 +1072,8 @@ static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { @@ -2270,7 +1972,7 @@ index b2e2b32..720ae2a 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -937,14 +1098,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -936,14 +1097,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p memset(&cert_attr, 0, sizeof(cert_attr)); cert_attr[0].type = CKA_ID; @@ -2291,7 +1993,7 @@ index b2e2b32..720ae2a 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return -1; -@@ -956,18 +1118,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -955,18 +1117,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p * XXX assumes CKA_ID is always first. */ if (cert_attr[1].ulValueLen == 0 || @@ -2314,7 +2016,7 @@ index b2e2b32..720ae2a 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto out; -@@ -981,8 +1144,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -980,8 +1143,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p subject = xstrdup("invalid subject"); X509_NAME_free(x509_name); @@ -2325,7 +2027,7 @@ index b2e2b32..720ae2a 100644 error("d2i_x509 failed"); goto out; } -@@ -1002,7 +1165,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1001,7 +1164,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2334,7 +2036,7 @@ index b2e2b32..720ae2a 100644 goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1032,7 +1195,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1031,7 +1194,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2343,7 +2045,7 @@ index b2e2b32..720ae2a 100644 goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1052,7 +1215,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1051,7 +1214,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } out: @@ -2352,7 +2054,7 @@ index b2e2b32..720ae2a 100644 free(cert_attr[i].pValue); X509_free(x509); RSA_free(rsa); -@@ -1103,11 +1266,12 @@ note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, +@@ -1102,11 +1265,12 @@ note_key(struct pkcs11_provider *p, CK_U */ static int pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2367,7 +2069,7 @@ index b2e2b32..720ae2a 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1124,10 +1288,23 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1123,10 +1287,23 @@ pkcs11_fetch_certs(struct pkcs11_provide key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2385,16 +2087,16 @@ index b2e2b32..720ae2a 100644 + key_attr[nattr].ulValueLen = strlen(uri->object); + nattr++; + } - -- rv = f->C_FindObjectsInit(session, key_attr, 1); ++ + session = p->module->slotinfo[slotidx].session; + f = p->module->function_list; -+ + +- rv = f->C_FindObjectsInit(session, key_attr, 1); + rv = f->C_FindObjectsInit(session, key_attr, nattr); if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1208,11 +1385,12 @@ fail: +@@ -1207,11 +1384,12 @@ fail: */ static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2409,7 +2111,7 @@ index b2e2b32..720ae2a 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1228,10 +1406,23 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1227,10 +1405,23 @@ pkcs11_fetch_keys(struct pkcs11_provider key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2436,7 +2138,7 @@ index b2e2b32..720ae2a 100644 if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1500,16 +1691,10 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1499,16 +1690,10 @@ pkcs11_ecdsa_generate_private_key(struct } #endif /* WITH_PKCS11_KEYGEN */ @@ -2455,15 +2157,14 @@ index b2e2b32..720ae2a 100644 int ret = -1; struct pkcs11_provider *p = NULL; void *handle = NULL; -@@ -1518,164 +1703,298 @@ pkcs11_register_provider(char *provider_id, char *pin, +@@ -1517,164 +1702,298 @@ pkcs11_register_provider(char *provider_ CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; -- -- if (providerp == NULL) + char *provider_module = NULL; + struct pkcs11_module *m = NULL; -+ + +- if (providerp == NULL) + /* if no provider specified, fallback to p11-kit */ + if (uri->module_path == NULL) { +#ifdef PKCS11_DEFAULT_PROVIDER @@ -2472,22 +2173,21 @@ index b2e2b32..720ae2a 100644 + error_f("No module path provided"); goto fail; - *providerp = NULL; -- -- if (keyp != NULL) -- *keyp = NULL; -- if (labelsp != NULL) -- *labelsp = NULL; +#endif + } else { + provider_module = strdup(uri->module_path); + } +- if (keyp != NULL) +- *keyp = NULL; +- if (labelsp != NULL) +- *labelsp = NULL; ++ p = xcalloc(1, sizeof(*p)); ++ p->name = pkcs11_uri_get(uri); + - if (pkcs11_provider_lookup(provider_id) != NULL) { - debug_f("provider already registered: %s", provider_id); - goto fail; -+ p = xcalloc(1, sizeof(*p)); -+ p->name = pkcs11_uri_get(uri); -+ + if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL + && m->valid) { + debug_f("provider module already initialized: %s", provider_module); @@ -2790,282 +2490,570 @@ index b2e2b32..720ae2a 100644 +pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, + char ***labelsp, struct pkcs11_provider **providerp, CK_ULONG user) +{ -+ struct pkcs11_uri *uri = NULL; -+ int r; ++ struct pkcs11_uri *uri = NULL; ++ int r; ++ ++ debug_f("called, provider_id = %s", provider_id); ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("failed to init PKCS#11 URI"); ++ ++ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { ++ if (pkcs11_uri_parse(provider_id, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI"); ++ } else { ++ uri->module_path = strdup(provider_id); ++ } ++ ++ r = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, providerp, user); ++ pkcs11_uri_cleanup(uri); ++ ++ return r; ++} ++ + int +-pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, +- char ***labelsp) ++pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin, ++ struct sshkey ***keyp, char ***labelsp) + { + struct pkcs11_provider *p = NULL; + int nkeys; ++ char *provider_uri = pkcs11_uri_get(uri); ++ ++ debug_f("called, provider_uri = %s", provider_uri); + +- nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp, +- &p, CKU_USER); ++ nkeys = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, &p, CKU_USER); + + /* no keys found or some other error, de-register provider */ + if (nkeys <= 0 && p != NULL) { +@@ -1683,7 +2002,37 @@ pkcs11_add_provider(char *provider_id, c + pkcs11_provider_unref(p); + } + if (nkeys == 0) +- debug_f("provider %s returned no keys", provider_id); ++ debug_f("provider %s returned no keys", provider_uri); ++ ++ free(provider_uri); ++ return nkeys; ++} ++ ++/* ++ * register a new provider and get number of keys hold by the token, ++ * fails if provider already exists ++ */ ++int ++pkcs11_add_provider(char *provider_id, char *pin, ++ struct sshkey ***keyp, char ***labelsp) ++{ ++ struct pkcs11_uri *uri; ++ int nkeys; ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); ++ ++ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { ++ if (pkcs11_uri_parse(provider_id, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI"); ++ } else { ++ uri->module_path = strdup(provider_id); ++ } ++ ++ nkeys = pkcs11_add_provider_by_uri(uri, pin, keyp, labelsp); ++ pkcs11_uri_cleanup(uri); + + return (nkeys); + } +diff -up openssh-8.7p1/ssh-pkcs11.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11.h +--- openssh-8.7p1/ssh-pkcs11.h.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/ssh-pkcs11.h 2021-08-30 13:07:43.666700121 +0200 +@@ -22,10 +22,14 @@ + #define SSH_PKCS11_ERR_PIN_REQUIRED 4 + #define SSH_PKCS11_ERR_PIN_LOCKED 5 + ++#include "ssh-pkcs11-uri.h" ++ + int pkcs11_init(int); + void pkcs11_terminate(void); + int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); ++int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***, char ***); + int pkcs11_del_provider(char *); ++int pkcs11_uri_write(const struct sshkey *, FILE *); + #ifdef WITH_PKCS11_KEYGEN + struct sshkey * + pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, +diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri.c +--- openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri 2021-08-30 13:07:43.667700130 +0200 ++++ openssh-8.7p1/ssh-pkcs11-uri.c 2021-08-30 13:07:43.667700130 +0200 +@@ -0,0 +1,419 @@ ++/* ++ * Copyright (c) 2017 Red Hat ++ * ++ * Authors: Jakub Jelen ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#include "includes.h" ++ ++#ifdef ENABLE_PKCS11 ++ ++#include ++#include ++ ++#include "sshkey.h" ++#include "sshbuf.h" ++#include "log.h" ++ ++#define CRYPTOKI_COMPAT ++#include "pkcs11.h" ++ ++#include "ssh-pkcs11-uri.h" ++ ++#define PKCS11_URI_PATH_SEPARATOR ";" ++#define PKCS11_URI_QUERY_SEPARATOR "&" ++#define PKCS11_URI_VALUE_SEPARATOR "=" ++#define PKCS11_URI_ID "id" ++#define PKCS11_URI_TOKEN "token" ++#define PKCS11_URI_OBJECT "object" ++#define PKCS11_URI_LIB_MANUF "library-manufacturer" ++#define PKCS11_URI_MANUF "manufacturer" ++#define PKCS11_URI_MODULE_PATH "module-path" ++#define PKCS11_URI_PIN_VALUE "pin-value" ++ ++/* Keyword tokens. */ ++typedef enum { ++ pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pModulePath, ++ pPinValue, pBadOption ++} pkcs11uriOpCodes; ++ ++/* Textual representation of the tokens. */ ++static struct { ++ const char *name; ++ pkcs11uriOpCodes opcode; ++} keywords[] = { ++ { PKCS11_URI_ID, pId }, ++ { PKCS11_URI_TOKEN, pToken }, ++ { PKCS11_URI_OBJECT, pObject }, ++ { PKCS11_URI_LIB_MANUF, pLibraryManufacturer }, ++ { PKCS11_URI_MANUF, pManufacturer }, ++ { PKCS11_URI_MODULE_PATH, pModulePath }, ++ { PKCS11_URI_PIN_VALUE, pPinValue }, ++ { NULL, pBadOption } ++}; ++ ++static pkcs11uriOpCodes ++parse_token(const char *cp) ++{ ++ u_int i; ++ ++ for (i = 0; keywords[i].name; i++) ++ if (strncasecmp(cp, keywords[i].name, ++ strlen(keywords[i].name)) == 0) ++ return keywords[i].opcode; ++ ++ return pBadOption; ++} ++ ++int ++percent_decode(char *data, char **outp) ++{ ++ char tmp[3]; ++ char *out, *tmp_end; ++ char *p = data; ++ long value; ++ size_t outlen = 0; ++ ++ out = malloc(strlen(data)+1); /* upper bound */ ++ if (out == NULL) ++ return -1; ++ while (*p != '\0') { ++ switch (*p) { ++ case '%': ++ p++; ++ if (*p == '\0') ++ goto fail; ++ tmp[0] = *p++; ++ if (*p == '\0') ++ goto fail; ++ tmp[1] = *p++; ++ tmp[2] = '\0'; ++ tmp_end = NULL; ++ value = strtol(tmp, &tmp_end, 16); ++ if (tmp_end != tmp+2) ++ goto fail; ++ else ++ out[outlen++] = (char) value; ++ break; ++ default: ++ out[outlen++] = *p++; ++ break; ++ } ++ } ++ ++ /* zero terminate */ ++ out[outlen] = '\0'; ++ *outp = out; ++ return outlen; ++fail: ++ free(out); ++ return -1; ++} ++ ++struct sshbuf * ++percent_encode(const char *data, size_t length, const char *allow_list) ++{ ++ struct sshbuf *b = NULL; ++ char tmp[4], *cp; ++ size_t i; ++ ++ if ((b = sshbuf_new()) == NULL) ++ return NULL; ++ for (i = 0; i < length; i++) { ++ cp = strchr(allow_list, data[i]); ++ /* if c is specified as '\0' pointer to terminator is returned !! */ ++ if (cp != NULL && *cp != '\0') { ++ if (sshbuf_put(b, &data[i], 1) != 0) ++ goto err; ++ } else ++ if (snprintf(tmp, 4, "%%%02X", (unsigned char) data[i]) < 3 ++ || sshbuf_put(b, tmp, 3) != 0) ++ goto err; ++ } ++ if (sshbuf_put(b, "\0", 1) == 0) ++ return b; ++err: ++ sshbuf_free(b); ++ return NULL; ++} ++ ++char * ++pkcs11_uri_append(char *part, const char *separator, const char *key, ++ struct sshbuf *value) ++{ ++ char *new_part; ++ size_t size = 0; + -+ debug_f("called, provider_id = %s", provider_id); ++ if (value == NULL) ++ return NULL; + -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("failed to init PKCS#11 URI"); ++ size = asprintf(&new_part, ++ "%s%s%s" PKCS11_URI_VALUE_SEPARATOR "%s", ++ (part != NULL ? part : ""), ++ (part != NULL ? separator : ""), ++ key, sshbuf_ptr(value)); ++ sshbuf_free(value); ++ free(part); + -+ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { -+ if (pkcs11_uri_parse(provider_id, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI"); -+ } else { -+ uri->module_path = strdup(provider_id); ++ if (size <= 0) ++ return NULL; ++ return new_part; ++} ++ ++char * ++pkcs11_uri_get(struct pkcs11_uri *uri) ++{ ++ size_t size = 0; ++ char *p = NULL, *path = NULL, *query = NULL; ++ ++ /* compose a percent-encoded ID */ ++ if (uri->id_len > 0) { ++ struct sshbuf *key_id = percent_encode(uri->id, uri->id_len, ""); ++ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, ++ PKCS11_URI_ID, key_id); ++ if (path == NULL) ++ goto err; + } + -+ r = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, providerp, user); -+ pkcs11_uri_cleanup(uri); ++ /* Write object label */ ++ if (uri->object) { ++ struct sshbuf *label = percent_encode(uri->object, strlen(uri->object), ++ PKCS11_URI_WHITELIST); ++ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, ++ PKCS11_URI_OBJECT, label); ++ if (path == NULL) ++ goto err; ++ } + -+ return r; ++ /* Write token label */ ++ if (uri->token) { ++ struct sshbuf *label = percent_encode(uri->token, strlen(uri->token), ++ PKCS11_URI_WHITELIST); ++ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, ++ PKCS11_URI_TOKEN, label); ++ if (path == NULL) ++ goto err; ++ } ++ ++ /* Write manufacturer */ ++ if (uri->manuf) { ++ struct sshbuf *manuf = percent_encode(uri->manuf, ++ strlen(uri->manuf), PKCS11_URI_WHITELIST); ++ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, ++ PKCS11_URI_MANUF, manuf); ++ if (path == NULL) ++ goto err; ++ } ++ ++ /* Write module_path */ ++ if (uri->module_path) { ++ struct sshbuf *module = percent_encode(uri->module_path, ++ strlen(uri->module_path), PKCS11_URI_WHITELIST "/"); ++ query = pkcs11_uri_append(query, PKCS11_URI_QUERY_SEPARATOR, ++ PKCS11_URI_MODULE_PATH, module); ++ if (query == NULL) ++ goto err; ++ } ++ ++ size = asprintf(&p, PKCS11_URI_SCHEME "%s%s%s", ++ path != NULL ? path : "", ++ query != NULL ? "?" : "", ++ query != NULL ? query : ""); ++err: ++ free(query); ++ free(path); ++ if (size <= 0) ++ return NULL; ++ return p; +} + - int --pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, -- char ***labelsp) -+pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin, -+ struct sshkey ***keyp, char ***labelsp) - { - struct pkcs11_provider *p = NULL; - int nkeys; -+ char *provider_uri = pkcs11_uri_get(uri); - -- nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp, -- &p, CKU_USER); -+ debug_f("called, provider_uri = %s", provider_uri); ++struct pkcs11_uri * ++pkcs11_uri_init() ++{ ++ struct pkcs11_uri *d = calloc(1, sizeof(struct pkcs11_uri)); ++ return d; ++} + -+ nkeys = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, &p, CKU_USER); - - /* no keys found or some other error, de-register provider */ - if (nkeys <= 0 && p != NULL) { -@@ -1684,7 +2003,37 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, - pkcs11_provider_unref(p); - } - if (nkeys == 0) -- debug_f("provider %s returned no keys", provider_id); -+ debug_f("provider %s returned no keys", provider_uri); ++void ++pkcs11_uri_cleanup(struct pkcs11_uri *pkcs11) ++{ ++ if (pkcs11 == NULL) { ++ return; ++ } + -+ free(provider_uri); -+ return nkeys; ++ free(pkcs11->id); ++ free(pkcs11->module_path); ++ free(pkcs11->token); ++ free(pkcs11->object); ++ free(pkcs11->lib_manuf); ++ free(pkcs11->manuf); ++ if (pkcs11->pin) ++ freezero(pkcs11->pin, strlen(pkcs11->pin)); ++ free(pkcs11); +} + -+/* -+ * register a new provider and get number of keys hold by the token, -+ * fails if provider already exists -+ */ +int -+pkcs11_add_provider(char *provider_id, char *pin, -+ struct sshkey ***keyp, char ***labelsp) ++pkcs11_uri_parse(const char *uri, struct pkcs11_uri *pkcs11) +{ -+ struct pkcs11_uri *uri; -+ int nkeys; ++ char *saveptr1, *saveptr2, *str1, *str2, *tok; ++ int rv = 0, len; ++ char *p = NULL; + -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PKCS#11 URI"); ++ size_t scheme_len = strlen(PKCS11_URI_SCHEME); ++ if (strlen(uri) < scheme_len || /* empty URI matches everything */ ++ strncmp(uri, PKCS11_URI_SCHEME, scheme_len) != 0) { ++ error_f("The '%s' does not look like PKCS#11 URI", uri); ++ return -1; ++ } + -+ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { -+ if (pkcs11_uri_parse(provider_id, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI"); -+ } else { -+ uri->module_path = strdup(provider_id); ++ if (pkcs11 == NULL) { ++ error_f("Bad arguments. The pkcs11 can't be null"); ++ return -1; + } + -+ nkeys = pkcs11_add_provider_by_uri(uri, pin, keyp, labelsp); -+ pkcs11_uri_cleanup(uri); - - return (nkeys); - } -diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h -index 81f1d7c..feaf74d 100644 ---- a/ssh-pkcs11.h -+++ b/ssh-pkcs11.h -@@ -22,10 +22,14 @@ - #define SSH_PKCS11_ERR_PIN_REQUIRED 4 - #define SSH_PKCS11_ERR_PIN_LOCKED 5 - -+#include "ssh-pkcs11-uri.h" ++ /* skip URI schema name */ ++ p = strdup(uri); ++ str1 = p; + - int pkcs11_init(int); - void pkcs11_terminate(void); - int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); -+int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***, char ***); - int pkcs11_del_provider(char *); -+int pkcs11_uri_write(const struct sshkey *, FILE *); - #ifdef WITH_PKCS11_KEYGEN - struct sshkey * - pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, -diff --git a/ssh.c b/ssh.c -index 244b7f3..fff421a 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -835,6 +835,14 @@ main(int ac, char **av) - options.gss_deleg_creds = 1; - break; - case 'i': -+#ifdef ENABLE_PKCS11 -+ if (strlen(optarg) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(optarg, PKCS11_URI_SCHEME, -+ strlen(PKCS11_URI_SCHEME)) == 0) { -+ add_identity_file(&options, NULL, optarg, 1); -+ break; ++ /* everything before ? */ ++ tok = strtok_r(str1, "?", &saveptr1); ++ if (tok == NULL) { ++ error_f("pk11-path expected, got EOF"); ++ rv = -1; ++ goto out; ++ } ++ ++ /* skip URI schema name: ++ * the scheme ensures that there is at least something before "?" ++ * allowing empty pk11-path. Resulting token at worst pointing to ++ * \0 byte */ ++ tok = tok + scheme_len; ++ ++ /* parse pk11-path */ ++ for (str2 = tok; ; str2 = NULL) { ++ char **charptr, *arg = NULL; ++ pkcs11uriOpCodes opcode; ++ tok = strtok_r(str2, PKCS11_URI_PATH_SEPARATOR, &saveptr2); ++ if (tok == NULL) ++ break; ++ opcode = parse_token(tok); ++ if (opcode != pBadOption) ++ arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */ ++ ++ switch (opcode) { ++ case pId: ++ /* CKA_ID */ ++ if (pkcs11->id != NULL) { ++ verbose_f("The id already set in the PKCS#11 URI"); ++ rv = -1; ++ goto out; ++ } ++ len = percent_decode(arg, &pkcs11->id); ++ if (len <= 0) { ++ verbose_f("Failed to percent-decode CKA_ID: %s", arg); ++ rv = -1; ++ goto out; ++ } else ++ pkcs11->id_len = len; ++ debug3_f("Setting CKA_ID = %s from PKCS#11 URI", arg); ++ break; ++ case pToken: ++ /* CK_TOKEN_INFO -> label */ ++ charptr = &pkcs11->token; ++ parse_string: ++ if (*charptr != NULL) { ++ verbose_f("The %s already set in the PKCS#11 URI", ++ keywords[opcode].name); ++ rv = -1; ++ goto out; + } -+#endif - p = tilde_expand_filename(optarg, getuid()); - if (stat(p, &st) == -1) - fprintf(stderr, "Warning: Identity file %s " -@@ -1699,6 +1707,7 @@ main(int ac, char **av) - #ifdef ENABLE_PKCS11 - (void)pkcs11_del_provider(options.pkcs11_provider); - #endif -+ pkcs11_terminate(); - - skip_connect: - exit_status = ssh_session2(ssh, cinfo); -@@ -2215,6 +2224,45 @@ ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) - options.escape_char : SSH_ESCAPECHAR_NONE, id); - } - -+#ifdef ENABLE_PKCS11 -+static void -+load_pkcs11_identity(char *pkcs11_uri, char *identity_files[], -+ struct sshkey *identity_keys[], int *n_ids) -+{ -+ int nkeys, i; -+ struct sshkey **keys; -+ struct pkcs11_uri *uri; ++ percent_decode(arg, charptr); ++ debug3_f("Setting %s = %s from PKCS#11 URI", ++ keywords[opcode].name, *charptr); ++ break; + -+ debug("identity file '%s' from pkcs#11", pkcs11_uri); -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PKCS#11 URI"); ++ case pObject: ++ /* CK_TOKEN_INFO -> manufacturerID */ ++ charptr = &pkcs11->object; ++ goto parse_string; + -+ if (pkcs11_uri_parse(pkcs11_uri, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri); ++ case pManufacturer: ++ /* CK_TOKEN_INFO -> manufacturerID */ ++ charptr = &pkcs11->manuf; ++ goto parse_string; + -+ /* we need to merge URI and provider together */ -+ if (options.pkcs11_provider != NULL && uri->module_path == NULL) -+ uri->module_path = strdup(options.pkcs11_provider); ++ case pLibraryManufacturer: ++ /* CK_INFO -> manufacturerID */ ++ charptr = &pkcs11->lib_manuf; ++ goto parse_string; + -+ if (options.num_identity_files < SSH_MAX_IDENTITY_FILES && -+ (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys, NULL)) > 0) { -+ for (i = 0; i < nkeys; i++) { -+ if (*n_ids >= SSH_MAX_IDENTITY_FILES) { -+ sshkey_free(keys[i]); -+ continue; -+ } -+ identity_keys[*n_ids] = keys[i]; -+ identity_files[*n_ids] = pkcs11_uri_get(uri); -+ (*n_ids)++; ++ default: ++ /* Unrecognized attribute in the URI path SHOULD be error */ ++ verbose_f("Unknown part of path in PKCS#11 URI: %s", tok); + } -+ free(keys); + } + -+ pkcs11_uri_cleanup(uri); -+} -+#endif /* ENABLE_PKCS11 */ ++ tok = strtok_r(NULL, "?", &saveptr1); ++ if (tok == NULL) { ++ goto out; ++ } ++ /* parse pk11-query (optional) */ ++ for (str2 = tok; ; str2 = NULL) { ++ char *arg; ++ pkcs11uriOpCodes opcode; ++ tok = strtok_r(str2, PKCS11_URI_QUERY_SEPARATOR, &saveptr2); ++ if (tok == NULL) ++ break; ++ opcode = parse_token(tok); ++ if (opcode != pBadOption) ++ arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */ + - /* Loads all IdentityFile and CertificateFile keys */ - static void - load_public_identity_files(const struct ssh_conn_info *cinfo) -@@ -2229,11 +2277,6 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) - char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; - struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; - int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; --#ifdef ENABLE_PKCS11 -- struct sshkey **keys = NULL; -- char **comments = NULL; -- int nkeys; --#endif /* PKCS11 */ - - n_ids = n_certs = 0; - memset(identity_files, 0, sizeof(identity_files)); -@@ -2246,33 +2289,46 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) - sizeof(certificate_file_userprovided)); - - #ifdef ENABLE_PKCS11 -- if (options.pkcs11_provider != NULL && -- options.num_identity_files < SSH_MAX_IDENTITY_FILES && -- (pkcs11_init(!options.batch_mode) == 0) && -- (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, -- &keys, &comments)) > 0) { -- for (i = 0; i < nkeys; i++) { -- if (n_ids >= SSH_MAX_IDENTITY_FILES) { -- sshkey_free(keys[i]); -- free(comments[i]); -- continue; -- } -- identity_keys[n_ids] = keys[i]; -- identity_files[n_ids] = comments[i]; /* transferred */ -- n_ids++; -- } -- free(keys); -- free(comments); -+ /* handle fallback from PKCS11Provider option */ -+ pkcs11_init(!options.batch_mode); ++ switch (opcode) { ++ case pModulePath: ++ /* module-path is PKCS11Provider */ ++ if (pkcs11->module_path != NULL) { ++ verbose_f("Multiple module-path attributes are" ++ "not supported the PKCS#11 URI"); ++ rv = -1; ++ goto out; ++ } ++ percent_decode(arg, &pkcs11->module_path); ++ debug3_f("Setting PKCS11Provider = %s from PKCS#11 URI", ++ pkcs11->module_path); ++ break; + -+ if (options.pkcs11_provider != NULL) { -+ struct pkcs11_uri *uri; ++ case pPinValue: ++ /* pin-value */ ++ if (pkcs11->pin != NULL) { ++ verbose_f("Multiple pin-value attributes are" ++ "not supported the PKCS#11 URI"); ++ rv = -1; ++ goto out; ++ } ++ percent_decode(arg, &pkcs11->pin); ++ debug3_f("Setting PIN from PKCS#11 URI"); ++ break; + -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PKCS#11 URI"); ++ default: ++ /* Unrecognized attribute in the URI query SHOULD be ignored */ ++ verbose_f("Unknown part of query in PKCS#11 URI: %s", tok); ++ } ++ } ++out: ++ free(p); ++ return rv; ++} + -+ /* Construct simple PKCS#11 URI to simplify access */ -+ uri->module_path = strdup(options.pkcs11_provider); ++#endif /* ENABLE_PKCS11 */ +diff -up openssh-8.7p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri.h +--- openssh-8.7p1/ssh-pkcs11-uri.h.pkcs11-uri 2021-08-30 13:07:43.667700130 +0200 ++++ openssh-8.7p1/ssh-pkcs11-uri.h 2021-08-30 13:07:43.667700130 +0200 +@@ -0,0 +1,42 @@ ++/* ++ * Copyright (c) 2017 Red Hat ++ * ++ * Authors: Jakub Jelen ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ + -+ /* Add it as any other IdentityFile */ -+ cp = pkcs11_uri_get(uri); -+ add_identity_file(&options, NULL, cp, 1); -+ free(cp); ++#define PKCS11_URI_SCHEME "pkcs11:" ++#define PKCS11_URI_WHITELIST "abcdefghijklmnopqrstuvwxyz" \ ++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ ++ "0123456789_-.()" ++ ++struct pkcs11_uri { ++ /* path */ ++ char *id; ++ size_t id_len; ++ char *token; ++ char *object; ++ char *lib_manuf; ++ char *manuf; ++ /* query */ ++ char *module_path; ++ char *pin; /* Only parsed, but not printed */ ++}; ++ ++struct pkcs11_uri *pkcs11_uri_init(); ++void pkcs11_uri_cleanup(struct pkcs11_uri *); ++int pkcs11_uri_parse(const char *, struct pkcs11_uri *); ++struct pkcs11_uri *pkcs11_uri_init(); ++char *pkcs11_uri_get(struct pkcs11_uri *uri); + -+ pkcs11_uri_cleanup(uri); - } - #endif /* ENABLE_PKCS11 */ - for (i = 0; i < options.num_identity_files; i++) { -+ char *name = options.identity_files[i]; - if (n_ids >= SSH_MAX_IDENTITY_FILES || -- strcasecmp(options.identity_files[i], "none") == 0) { -+ strcasecmp(name, "none") == 0) { - free(options.identity_files[i]); - options.identity_files[i] = NULL; - continue; - } -- cp = tilde_expand_filename(options.identity_files[i], getuid()); -+#ifdef ENABLE_PKCS11 -+ if (strlen(name) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(name, PKCS11_URI_SCHEME, -+ strlen(PKCS11_URI_SCHEME)) == 0) { -+ load_pkcs11_identity(name, identity_files, -+ identity_keys, &n_ids); -+ free(options.identity_files[i]); -+ continue; -+ } -+#endif /* ENABLE_PKCS11 */ -+ cp = tilde_expand_filename(name, getuid()); - filename = default_client_percent_dollar_expand(cp, cinfo); - free(cp); - check_load(sshkey_load_public(filename, &public, NULL), -diff --git a/ssh_config.5 b/ssh_config.5 -index 0a6c4a6..4bacaf9 100644 ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -1114,6 +1114,21 @@ may also be used in conjunction with - .Cm CertificateFile - in order to provide any certificate also needed for authentication with - the identity. -+.Pp -+The authentication identity can be also specified in a form of PKCS#11 URI -+starting with a string -+.Cm pkcs11: . -+There is supported a subset of the PKCS#11 URI as defined -+in RFC 7512 (implemented path arguments -+.Cm id , -+.Cm manufacturer , -+.Cm object , -+.Cm token -+and query arguments -+.Cm module-path -+and -+.Cm pin-value -+). The URI can not be in quotes. - .It Cm IgnoreUnknown - Specifies a pattern-list of unknown options to be ignored if they are - encountered in configuration parsing. --- -2.27.0 - diff --git a/openssh-8.7p1-ibmca.patch b/openssh-8.7p1-ibmca.patch new file mode 100644 index 0000000000000000000000000000000000000000..2f2556e0ac9b21a6c0534be8ebccab043409b756 --- /dev/null +++ b/openssh-8.7p1-ibmca.patch @@ -0,0 +1,12 @@ +Reference:https://src.fedoraproject.org/rpms/openssh/blob/rawhide/f/openssh-8.7p1-ibmca.patch +--- openssh-8.7p1/openbsd-compat/bsd-closefrom.c.orig 2022-04-12 15:47:03.815044607 +0200 ++++ openssh-8.7p1/openbsd-compat/bsd-closefrom.c 2022-04-12 15:48:12.464963511 +0200 +@@ -16,7 +16,7 @@ + + #include "includes.h" + +-#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) ++#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) || (defined __s390__) + + #include + #include diff --git a/openssh-8.7p1-minrsabits.patch b/openssh-8.7p1-minrsabits.patch new file mode 100644 index 0000000000000000000000000000000000000000..2ed59a3e099b7db9599382b6875622862541db0c --- /dev/null +++ b/openssh-8.7p1-minrsabits.patch @@ -0,0 +1,24 @@ +diff --git a/readconf.c b/readconf.c +index 7f26c680..42be690b 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -320,6 +320,7 @@ static struct { + { "securitykeyprovider", oSecurityKeyProvider }, + { "knownhostscommand", oKnownHostsCommand }, + { "requiredrsasize", oRequiredRSASize }, ++ { "rsaminsize", oRequiredRSASize }, /* alias */ + { "enableescapecommandline", oEnableEscapeCommandline }, + + { NULL, oBadOption } +diff --git a/servconf.c b/servconf.c +index 29df0463..423772b1 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -676,6 +680,7 @@ static struct { + { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, + { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, + { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, ++ { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */ + { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, + { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, + { NULL, sBadOption, 0 } diff --git a/openssh-8.7p1-negotiate-supported-algs.patch b/openssh-8.7p1-negotiate-supported-algs.patch new file mode 100644 index 0000000000000000000000000000000000000000..ee3637fa37cb1860486800adc670d7fad4abc1ed --- /dev/null +++ b/openssh-8.7p1-negotiate-supported-algs.patch @@ -0,0 +1,117 @@ +diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostkey-agent.sh +--- openssh-9.3p1/regress/hostkey-agent.sh.xxx 2023-05-29 18:15:56.311236887 +0200 ++++ openssh-9.3p1/regress/hostkey-agent.sh 2023-05-29 18:16:07.598503551 +0200 +@@ -17,8 +17,21 @@ trace "make CA key" + + ${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA" + ++PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \ ++ grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"` ++SSH_ACCEPTED_KEYTYPES=`echo "$SSH_KEYTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"` ++echo $PUBKEY_ACCEPTED_ALGOS | grep "rsa" ++r=$? ++if [ $r == 0 ]; then ++echo $SSH_ACCEPTED_KEYTYPES | grep "rsa" ++r=$? ++if [ $r -ne 0 ]; then ++SSH_ACCEPTED_KEYTYPES="$SSH_ACCEPTED_KEYTYPES ssh-rsa" ++fi ++fi ++ + trace "load hostkeys" +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; do + ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k" + ${SSHKEYGEN} -s $OBJ/agent-ca -qh -n localhost-with-alias \ + -I localhost-with-alias $OBJ/agent-key.$k.pub || \ +@@ -32,12 +48,16 @@ rm $OBJ/agent-ca # Don't need CA private + + unset SSH_AUTH_SOCK + +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; do + verbose "key type $k" ++ hka=$k ++ if [ $k = "ssh-rsa" ]; then ++ hka="rsa-sha2-512" ++ fi + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy +- echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy ++ echo "HostKeyAlgorithms $hka" >> $OBJ/sshd_proxy + echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy +- opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" ++ opts="-oHostKeyAlgorithms=$hka -F $OBJ/ssh_proxy" + ( printf 'localhost-with-alias,127.0.0.1,::1 ' ; + cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts + SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` +@@ -50,15 +70,16 @@ for k in $SSH_KEYTYPES ; do + done + + SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com'` ++SSH_ACCEPTED_CERTTYPES=`echo "$SSH_CERTTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"` + + # Prepare sshd_proxy for certificates. + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + HOSTKEYALGS="" +-for k in $SSH_CERTTYPES ; do ++for k in $SSH_ACCEPTED_CERTTYPES ; do + test -z "$HOSTKEYALGS" || HOSTKEYALGS="${HOSTKEYALGS}," + HOSTKEYALGS="${HOSTKEYALGS}${k}" + done +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; do + echo "Hostkey $OBJ/agent-key.${k}.pub" >> $OBJ/sshd_proxy + echo "HostCertificate $OBJ/agent-key.${k}-cert.pub" >> $OBJ/sshd_proxy + test -f $OBJ/agent-key.${k}.pub || fatal "no $k key" +@@ -70,7 +93,7 @@ echo "HostKeyAlgorithms $HOSTKEYALGS" >> + ( printf '@cert-authority localhost-with-alias ' ; + cat $OBJ/agent-ca.pub) > $OBJ/known_hosts + +-for k in $SSH_CERTTYPES ; do ++for k in $SSH_ACCEPTED_CERTTYPES ; do + verbose "cert type $k" + opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" + SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` +diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c +--- openssh-9.3p1/sshconnect2.c.xxx 2023-04-26 17:37:35.100827792 +0200 ++++ openssh-9.3p1/sshconnect2.c 2023-04-26 17:50:31.860748877 +0200 +@@ -221,7 +221,7 @@ ssh_kex2(struct ssh *ssh, char *host, st + const struct ssh_conn_info *cinfo) + { + char *myproposal[PROPOSAL_MAX]; +- char *s, *all_key, *hkalgs = NULL; ++ char *s, *all_key, *hkalgs = NULL, *filtered_algs = NULL; + int r, use_known_hosts_order = 0; + + #if defined(GSSAPI) && defined(WITH_OPENSSL) +@@ -260,9 +260,21 @@ ssh_kex2(struct ssh *ssh, char *host, st + if (use_known_hosts_order) + hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo); + ++ filtered_algs = hkalgs ? match_filter_allowlist(hkalgs, options.pubkey_accepted_algos) ++ : match_filter_allowlist(options.hostkeyalgorithms, ++ options.pubkey_accepted_algos); ++ if (filtered_algs == NULL) { ++ if (hkalgs) ++ fatal_f("No match between algorithms for %s (host %s) and pubkey accepted algorithms %s", ++ hkalgs, host, options.pubkey_accepted_algos); ++ else ++ fatal_f("No match between host key algorithms %s and pubkey accepted algorithms %s", ++ options.hostkeyalgorithms, options.pubkey_accepted_algos); ++ } ++ + kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers, + options.macs, compression_alg_list(options.compression), +- hkalgs ? hkalgs : options.hostkeyalgorithms); ++ filtered_algs); + + #if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { +@@ -303,6 +315,7 @@ ssh_kex2(struct ssh *ssh, char *host, st + #endif + + free(hkalgs); ++ free(filtered_algs); + + /* start key exchange */ + if ((r = kex_setup(ssh, myproposal)) != 0) diff --git a/openssh-8.7p1-recursive-scp.patch b/openssh-8.7p1-recursive-scp.patch new file mode 100644 index 0000000000000000000000000000000000000000..f0d9b0fed4898e8536615edeffe6a122aace88fc --- /dev/null +++ b/openssh-8.7p1-recursive-scp.patch @@ -0,0 +1,181 @@ +diff -up openssh-8.7p1/scp.c.scp-sftpdirs openssh-8.7p1/scp.c +--- openssh-8.7p1/scp.c.scp-sftpdirs 2022-02-07 12:31:07.407740407 +0100 ++++ openssh-8.7p1/scp.c 2022-02-07 12:31:07.409740424 +0100 +@@ -1324,7 +1324,7 @@ source_sftp(int argc, char *src, char *t + + if (src_is_dir && iamrecursive) { + if (upload_dir(conn, src, abs_dst, pflag, +- SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { ++ SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) { + error("failed to upload directory %s to %s", src, targ); + errs = 1; + } +diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c +--- openssh-8.7p1/sftp-client.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/sftp-client.c 2022-02-07 12:47:59.117516131 +0100 +@@ -971,7 +971,7 @@ do_fsetstat(struct sftp_conn *conn, cons + + /* Implements both the realpath and expand-path operations */ + static char * +-do_realpath_expand(struct sftp_conn *conn, const char *path, int expand) ++do_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir) + { + struct sshbuf *msg; + u_int expected_id, count, id; +@@ -1033,11 +1033,43 @@ do_realpath_expand(struct sftp_conn *con + if ((r = sshbuf_get_u32(msg, &status)) != 0 || + (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) + fatal_fr(r, "parse status"); +- error("%s %s: %s", expand ? "expand" : "realpath", +- path, *errmsg == '\0' ? fx2txt(status) : errmsg); +- free(errmsg); +- sshbuf_free(msg); +- return NULL; ++ if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) { ++ memset(&a, '\0', sizeof(a)); ++ if ((r = do_mkdir(conn, path, &a, 0)) != 0) { ++ sshbuf_free(msg); ++ return NULL; ++ } ++ debug2("Sending SSH2_FXP_REALPATH \"%s\" - create dir", path); ++ send_string_request(conn, id, SSH2_FXP_REALPATH, ++ path, strlen(path)); ++ ++ get_msg(conn, msg); ++ if ((r = sshbuf_get_u8(msg, &type)) != 0 || ++ (r = sshbuf_get_u32(msg, &id)) != 0) ++ fatal_fr(r, "parse"); ++ ++ if (id != expected_id) ++ fatal("ID mismatch (%u != %u)", id, expected_id); ++ ++ if (type == SSH2_FXP_STATUS) { ++ free(errmsg); ++ ++ if ((r = sshbuf_get_u32(msg, &status)) != 0 || ++ (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) ++ fatal_fr(r, "parse status"); ++ error("%s %s: %s", expand ? "expand" : "realpath", ++ path, *errmsg == '\0' ? fx2txt(status) : errmsg); ++ free(errmsg); ++ sshbuf_free(msg); ++ return NULL; ++ } ++ } else { ++ error("%s %s: %s", expand ? "expand" : "realpath", ++ path, *errmsg == '\0' ? fx2txt(status) : errmsg); ++ free(errmsg); ++ sshbuf_free(msg); ++ return NULL; ++ } + } else if (type != SSH2_FXP_NAME) + fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", + SSH2_FXP_NAME, type); +@@ -1039,9 +1067,9 @@ do_realpath_expand(struct sftp_conn *con + } + + char * +-do_realpath(struct sftp_conn *conn, const char *path) ++do_realpath(struct sftp_conn *conn, const char *path, int create_dir) + { +- return do_realpath_expand(conn, path, 0); ++ return do_realpath_expand(conn, path, 0, create_dir); + } + + int +@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c + { + if (!can_expand_path(conn)) { + debug3_f("no server support, fallback to realpath"); +- return do_realpath_expand(conn, path, 0); ++ return do_realpath_expand(conn, path, 0, 0); + } +- return do_realpath_expand(conn, path, 1); ++ return do_realpath_expand(conn, path, 1, 0); + } + + int +@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con + char *src_canon; + int ret; + +- if ((src_canon = do_realpath(conn, src)) == NULL) { ++ if ((src_canon = do_realpath(conn, src, 0)) == NULL) { + error("download \"%s\": path canonicalization failed", src); + return -1; + } +@@ -2115,12 +2143,12 @@ upload_dir_internal(struct sftp_conn *co + int + upload_dir(struct sftp_conn *conn, const char *src, const char *dst, + int preserve_flag, int print_flag, int resume, int fsync_flag, +- int follow_link_flag, int inplace_flag) ++ int follow_link_flag, int inplace_flag, int create_dir) + { + char *dst_canon; + int ret; + +- if ((dst_canon = do_realpath(conn, dst)) == NULL) { ++ if ((dst_canon = do_realpath(conn, dst, create_dir)) == NULL) { + error("upload \"%s\": path canonicalization failed", dst); + return -1; + } +@@ -2557,7 +2585,7 @@ crossload_dir(struct sftp_conn *from, st + char *from_path_canon; + int ret; + +- if ((from_path_canon = do_realpath(from, from_path)) == NULL) { ++ if ((from_path_canon = do_realpath(from, from_path, 0)) == NULL) { + error("crossload \"%s\": path canonicalization failed", + from_path); + return -1; +diff -up openssh-8.7p1/sftp-client.h.scp-sftpdirs openssh-8.7p1/sftp-client.h +--- openssh-8.7p1/sftp-client.h.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/sftp-client.h 2022-02-07 12:31:07.410740433 +0100 +@@ -111,7 +111,7 @@ int do_fsetstat(struct sftp_conn *, cons + int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); + + /* Canonicalise 'path' - caller must free result */ +-char *do_realpath(struct sftp_conn *, const char *); ++char *do_realpath(struct sftp_conn *, const char *, int); + + /* Canonicalisation with tilde expansion (requires server extension) */ + char *do_expand_path(struct sftp_conn *, const char *); +@@ -159,7 +159,7 @@ int do_upload(struct sftp_conn *, const + * times if 'pflag' is set + */ + int upload_dir(struct sftp_conn *, const char *, const char *, +- int, int, int, int, int, int); ++ int, int, int, int, int, int, int); + + /* + * Download a 'from_path' from the 'from' connection and upload it to +diff -up openssh-8.7p1/sftp.c.scp-sftpdirs openssh-8.7p1/sftp.c +--- openssh-8.7p1/sftp.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200 ++++ openssh-8.7p1/sftp.c 2022-02-07 12:31:07.411740442 +0100 +@@ -760,7 +760,7 @@ process_put(struct sftp_conn *conn, cons + if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { + if (upload_dir(conn, g.gl_pathv[i], abs_dst, + pflag || global_pflag, 1, resume, +- fflag || global_fflag, 0, 0) == -1) ++ fflag || global_fflag, 0, 0, 0) == -1) + err = -1; + } else { + if (do_upload(conn, g.gl_pathv[i], abs_dst, +@@ -1577,7 +1577,7 @@ parse_dispatch_command(struct sftp_conn + if (path1 == NULL || *path1 == '\0') + path1 = xstrdup(startdir); + path1 = make_absolute(path1, *pwd); +- if ((tmp = do_realpath(conn, path1)) == NULL) { ++ if ((tmp = do_realpath(conn, path1, 0)) == NULL) { + err = 1; + break; + } +@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn, + } + #endif /* USE_LIBEDIT */ + +- remote_path = do_realpath(conn, "."); ++ remote_path = do_realpath(conn, ".", 0); + if (remote_path == NULL) + fatal("Need cwd"); + startdir = xstrdup(remote_path); diff --git a/openssh-8.7p1-scp-kill-switch.patch b/openssh-8.7p1-scp-kill-switch.patch index 6710304c1dc676ef2e5d13a327fb6fdad52ea93e..161ab2d92842f82809c398d560937d6f4e516358 100644 --- a/openssh-8.7p1-scp-kill-switch.patch +++ b/openssh-8.7p1-scp-kill-switch.patch @@ -13,8 +13,8 @@ diff -up openssh-8.7p1/scp.1.kill-scp openssh-8.7p1/scp.1 --- openssh-8.7p1/scp.1.kill-scp 2021-09-16 12:09:02.646714578 +0200 +++ openssh-8.7p1/scp.1 2021-09-16 12:26:49.978628226 +0200 @@ -278,6 +278,13 @@ to print debugging messages about their - This is helpful in - debugging connection, authentication, and configuration problems. + By default a 32KB buffer is used. + .El .El +.Pp +Usage of SCP protocol can be blocked by creating a world-readable diff --git a/openssh-8.7p1-ssh-manpage.patch b/openssh-8.7p1-ssh-manpage.patch new file mode 100644 index 0000000000000000000000000000000000000000..c7f6f1e659a00bcba4a91c9e63dc2f5e0e8f2632 --- /dev/null +++ b/openssh-8.7p1-ssh-manpage.patch @@ -0,0 +1,53 @@ +diff --color -ru a/ssh.1 b/ssh.1 +--- a/ssh.1 2022-07-12 11:47:51.307295880 +0200 ++++ b/ssh.1 2022-07-12 11:50:28.793363263 +0200 +@@ -493,6 +493,7 @@ + .It AddressFamily + .It BatchMode + .It BindAddress ++.It BindInterface + .It CanonicalDomains + .It CanonicalizeFallbackLocal + .It CanonicalizeHostname +@@ -510,6 +511,7 @@ + .It ControlPath + .It ControlPersist + .It DynamicForward ++.It EnableSSHKeysign + .It EnableEscapeCommandline + .It EscapeChar + .It ExitOnForwardFailure +@@ -538,6 +540,8 @@ + .It IdentitiesOnly + .It IdentityAgent + .It IdentityFile ++.It IgnoreUnknown ++.It Include + .It IPQoS + .It KbdInteractiveAuthentication + .It KbdInteractiveDevices +@@ -546,6 +550,7 @@ + .It LocalCommand + .It LocalForward + .It LogLevel ++.It LogVerbose + .It MACs + .It Match + .It NoHostAuthenticationForLocalhost +@@ -566,6 +571,8 @@ + .It RemoteCommand + .It RemoteForward + .It RequestTTY ++.It RevokedHostKeys ++.It SecurityKeyProvider + .It RequiredRSASize + .It SendEnv + .It ServerAliveInterval +@@ -575,6 +582,7 @@ + .It StreamLocalBindMask + .It StreamLocalBindUnlink + .It StrictHostKeyChecking ++.It SyslogFacility + .It TCPKeepAlive + .It Tunnel + .It TunnelDevice diff --git a/openssh-9.1p1.tar.gz b/openssh-9.1p1.tar.gz deleted file mode 100644 index a8c5b89bb1a721a0563ae7379490d3f40010390f..0000000000000000000000000000000000000000 Binary files a/openssh-9.1p1.tar.gz and /dev/null differ diff --git a/openssh-9.1p1.tar.gz.asc b/openssh-9.1p1.tar.gz.asc deleted file mode 100644 index 0237718e410b6eb49e3dba898b89e13fd9093894..0000000000000000000000000000000000000000 --- a/openssh-9.1p1.tar.gz.asc +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmM6+qUACgkQKj9BTnNg -YLqLSxAAi+hmachTcy9O2GNbCq4uPFlFqQ8hjZ697nhNvkIJtrtc2WSIg17ImN4E -3ucWQLEqbytwsj67J1UFC4NyOmGo2mfsZ3BEDsgkkd0Tp2YO7UhkrVzTD0l0Wl7/ -qe0biPaYOLFptL+88wC3OdamNkWgHAtSYBizgHK4k2uEtLYsEXuC+0nnfqykL2vq -UEB3MZ7C00JYmBVHFfMjtmGmt+Z3ahv5LSzFsj//c6hwkhdJHtv/V4UlCIVrrMdG -XyTumREl+y5zuP5oGxsRU/LZNo7ncXYDUg2qE/FpR4o8giF9d1fm/aHuAmr+g03E -Ev3uUcrgA+Kq95bbv7ubtO2JxFnuzUmJkUy6SNIcE1o4naxGejxlEw7nvtvf7auV -BPqomw1yOWyQzbhXtD18OiSi1IJMXyDCei9HcsO+oM3aq8YQc9Bsed7UPhA36e6b -GjuAIOPtee+JqxDj3psN39G+y4YUcxSPqC4gKL8cKfImbP2DlSoHPmZ1fDf/pKPj -hWdNiA+a+KzsXR2fjBWMeUIkSvx2BYZC9NKFS/zN4X86jEdyOJtQJ4WQcIvekLIA -Z/yP6UrzM+2jYYqix4PBocP1utEakFDYfLPJu0G2pK9meU4dz6EzNUT7J3daF2h7 -eaibQUZ0+wg+sI+MPys3INcqcKwv/5OVDl6wi7g2iNOdOII49VM= -=xfW+ ------END PGP SIGNATURE----- diff --git a/openssh-8.0p1-openssl-evp.patch b/openssh-9.3p1-merged-openssl-evp.patch similarity index 40% rename from openssh-8.0p1-openssl-evp.patch rename to openssh-9.3p1-merged-openssl-evp.patch index ade0bbb2118460071a8b8347c81363cbacd21bb3..d8c2ca359fa4592e5f2ab362099dd6170d3a564b 100644 --- a/openssh-8.0p1-openssl-evp.patch +++ b/openssh-9.3p1-merged-openssl-evp.patch @@ -1,23 +1,23 @@ -From ed7ec0cdf577ffbb0b15145340cf51596ca3eb89 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 14 May 2019 10:45:45 +0200 -Subject: [PATCH] Use high-level OpenSSL API for signatures - ---- - digest-openssl.c | 16 ++++ - digest.h | 6 ++ - ssh-dss.c | 65 ++++++++++------ - ssh-ecdsa.c | 69 ++++++++++------- - ssh-rsa.c | 193 +++++++++-------------------------------------- - sshkey.c | 77 +++++++++++++++++++ - sshkey.h | 4 + - 7 files changed, 221 insertions(+), 209 deletions(-) - -diff --git a/digest-openssl.c b/digest-openssl.c -index da7ed72bc..6a21d8adb 100644 ---- a/digest-openssl.c -+++ b/digest-openssl.c -@@ -63,6 +63,22 @@ const struct ssh_digest digests[] = { +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/digest.h openssh-9.3p1-patched/digest.h +--- openssh-9.3p1/digest.h 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/digest.h 2023-06-06 15:52:25.602551466 +0200 +@@ -32,6 +32,12 @@ + struct sshbuf; + struct ssh_digest_ctx; + ++#ifdef WITH_OPENSSL ++#include ++/* Converts internal digest representation to the OpenSSL one */ ++const EVP_MD *ssh_digest_to_md(int digest_type); ++#endif ++ + /* Looks up a digest algorithm by name */ + int ssh_digest_alg_by_name(const char *name); + +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/digest-openssl.c openssh-9.3p1-patched/digest-openssl.c +--- openssh-9.3p1/digest-openssl.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/digest-openssl.c 2023-06-06 15:52:25.601551454 +0200 +@@ -64,6 +64,22 @@ { -1, NULL, 0, NULL }, }; @@ -40,30 +40,21 @@ index da7ed72bc..6a21d8adb 100644 static const struct ssh_digest * ssh_digest_by_alg(int alg) { -diff --git a/digest.h b/digest.h -index 274574d0e..c7ceeb36f 100644 ---- a/digest.h -+++ b/digest.h -@@ -32,6 +32,12 @@ - struct sshbuf; - struct ssh_digest_ctx; +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-dss.c openssh-9.3p1-patched/ssh-dss.c +--- openssh-9.3p1/ssh-dss.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/ssh-dss.c 2023-06-06 15:52:25.624551743 +0200 +@@ -32,6 +32,8 @@ + #include + #include + #include ++#include ++#include -+#ifdef WITH_OPENSSL -+#include -+/* Converts internal digest representation to the OpenSSL one */ -+const EVP_MD *ssh_digest_to_md(int digest_type); -+#endif -+ - /* Looks up a digest algorithm by name */ - int ssh_digest_alg_by_name(const char *name); - -diff --git a/ssh-dss.c b/ssh-dss.c -index a23c383dc..ea45e7275 100644 ---- a/ssh-dss.c -+++ b/ssh-dss.c -@@ -52,11 +52,15 @@ int - ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat) + #include + #include +@@ -261,11 +263,15 @@ + const u_char *data, size_t datalen, + const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { + EVP_PKEY *pkey = NULL; DSA_SIG *sig = NULL; @@ -79,7 +70,7 @@ index a23c383dc..ea45e7275 100644 int ret = SSH_ERR_INVALID_ARGUMENT; if (lenp != NULL) -@@ -67,17 +71,24 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +@@ -276,17 +282,23 @@ if (key == NULL || key->dsa == NULL || sshkey_type_plain(key->type) != KEY_DSA) return SSH_ERR_INVALID_ARGUMENT; @@ -88,9 +79,8 @@ index a23c383dc..ea45e7275 100644 - if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, - digest, sizeof(digest))) != 0) -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; ++ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0) ++ return ret; + ret = sshkey_calculate_signature(pkey, SSH_DIGEST_SHA1, &sigb, &len, + data, datalen); + EVP_PKEY_free(pkey); @@ -109,7 +99,7 @@ index a23c383dc..ea45e7275 100644 DSA_SIG_get0(sig, &sig_r, &sig_s); rlen = BN_num_bytes(sig_r); -@@ -110,7 +121,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +@@ -319,7 +331,7 @@ *lenp = len; ret = 0; out: @@ -118,15 +108,15 @@ index a23c383dc..ea45e7275 100644 DSA_SIG_free(sig); sshbuf_free(b); return ret; -@@ -121,20 +132,20 @@ ssh_dss_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat) +@@ -331,20 +343,20 @@ + const u_char *data, size_t dlen, const char *alg, u_int compat, + struct sshkey_sig_details **detailsp) { + EVP_PKEY *pkey = NULL; - DSA_SIG *sig = NULL; + DSA_SIG *dsig = NULL; BIGNUM *sig_r = NULL, *sig_s = NULL; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; -- size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); +- size_t len, hlen = ssh_digest_bytes(SSH_DIGEST_SHA1); + u_char *sigblob = NULL; + size_t len, slen; int ret = SSH_ERR_INTERNAL_ERROR; @@ -136,25 +126,25 @@ index a23c383dc..ea45e7275 100644 if (key == NULL || key->dsa == NULL || sshkey_type_plain(key->type) != KEY_DSA || - signature == NULL || signaturelen == 0) + sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; -- if (dlen == 0) +- if (hlen == 0) - return SSH_ERR_INTERNAL_ERROR; /* fetch signature */ - if ((b = sshbuf_from(signature, signaturelen)) == NULL) -@@ -176,25 +187,31 @@ ssh_dss_verify(const struct sshkey *key, + if ((b = sshbuf_from(sig, siglen)) == NULL) +@@ -386,25 +398,28 @@ } sig_r = sig_s = NULL; /* transferred */ - /* sha1 the data */ -- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, +- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, dlen, - digest, sizeof(digest))) != 0) -+ if ((slen = i2d_DSA_SIG(sig, NULL)) == 0) { ++ if ((slen = i2d_DSA_SIG(dsig, NULL)) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; - -- switch (DSA_do_verify(digest, dlen, sig, key->dsa)) { +- switch (DSA_do_verify(digest, hlen, dsig, key->dsa)) { - case 1: - ret = 0; - break; @@ -167,70 +157,187 @@ index a23c383dc..ea45e7275 100644 - default: + } + psig = sigb; -+ if ((slen = i2d_DSA_SIG(sig, &psig)) == 0) { ++ if ((slen = i2d_DSA_SIG(dsig, &psig)) == 0) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; ++ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0) + goto out; -+ } -+ ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, datalen, ++ ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, dlen, + sigb, slen); + EVP_PKEY_free(pkey); + out: - explicit_bzero(digest, sizeof(digest)); + free(sigb); - DSA_SIG_free(sig); + DSA_SIG_free(dsig); BN_clear_free(sig_r); BN_clear_free(sig_s); -diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c -index 599c7199d..b036796e8 100644 ---- a/ssh-ecdsa.c -+++ b/ssh-ecdsa.c -@@ -50,11 +50,13 @@ int - ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat) +@@ -415,6 +430,65 @@ + return ret; + } + ++int ++ssh_create_evp_dss(const struct sshkey *k, EVP_PKEY **pkey) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ const BIGNUM *p = NULL, *q = NULL, *g = NULL, *pub = NULL, *priv = NULL; ++ int ret = 0; ++ ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DSA", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ DSA_get0_pqg(k->dsa, &p, &q, &g); ++ DSA_get0_key(k->dsa, &pub, &priv); ++ ++ if (p != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (q != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (g != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (pub != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, ++ pub) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (priv != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, ++ priv) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ return ret; ++} ++ + static const struct sshkey_impl_funcs sshkey_dss_funcs = { + /* .size = */ ssh_dss_size, + /* .alloc = */ ssh_dss_alloc, +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-ecdsa.c openssh-9.3p1-patched/ssh-ecdsa.c +--- openssh-9.3p1/ssh-ecdsa.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/ssh-ecdsa.c 2023-06-06 15:52:25.626551768 +0200 +@@ -34,6 +34,8 @@ + #include + #include + #include ++#include ++#include + + #include + +@@ -126,19 +128,29 @@ + static int + ssh_ecdsa_generate(struct sshkey *k, int bits) + { +- EC_KEY *private; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *res = NULL; + + if ((k->ecdsa_nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) + return SSH_ERR_KEY_LENGTH; +- if ((private = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL) ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL) + return SSH_ERR_ALLOC_FAIL; +- if (EC_KEY_generate_key(private) != 1) { +- EC_KEY_free(private); ++ ++ if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_CTX_set_group_name(ctx, OBJ_nid2sn(k->ecdsa_nid)) <= 0 ++ || EVP_PKEY_keygen(ctx, &res) <= 0) { ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(res); + return SSH_ERR_LIBCRYPTO_ERROR; + } +- EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); +- k->ecdsa = private; +- return 0; ++ /* This function is deprecated in OpenSSL 3.0 but OpenSSH doesn't worry about it*/ ++ k->ecdsa = EVP_PKEY_get1_EC_KEY(res); ++ if (k->ecdsa) ++ EC_KEY_set_asn1_flag(k->ecdsa, OPENSSL_EC_NAMED_CURVE); ++ ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(res); ++ return (k->ecdsa) ? 0 : SSH_ERR_LIBCRYPTO_ERROR; + } + + static int +@@ -228,11 +240,13 @@ + const u_char *data, size_t dlen, + const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { + EVP_PKEY *pkey = NULL; - ECDSA_SIG *sig = NULL; + ECDSA_SIG *esig = NULL; + unsigned char *sigb = NULL; + const unsigned char *psig; const BIGNUM *sig_r, *sig_s; int hash_alg; - u_char digest[SSH_DIGEST_MAX_LENGTH]; -- size_t len, dlen; +- size_t len, hlen; + int len; struct sshbuf *b = NULL, *bb = NULL; int ret = SSH_ERR_INTERNAL_ERROR; -@@ -67,18 +69,24 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +@@ -245,18 +259,33 @@ sshkey_type_plain(key->type) != KEY_ECDSA) return SSH_ERR_INVALID_ARGUMENT; - if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || -- (dlen = ssh_digest_bytes(hash_alg)) == 0) +- (hlen = ssh_digest_bytes(hash_alg)) == 0) + if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) return SSH_ERR_INTERNAL_ERROR; -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, +- if ((ret = ssh_digest_memory(hash_alg, data, dlen, - digest, sizeof(digest))) != 0) + -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; ++#ifdef ENABLE_PKCS11 ++ if (is_ecdsa_pkcs11(key->ecdsa)) { ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ } else { ++#endif ++ if ((ret = ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey)) != 0) ++ return ret; ++#ifdef ENABLE_PKCS11 ++ } ++#endif + ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data, -+ datalen); ++ dlen); + EVP_PKEY_free(pkey); + if (ret < 0) { goto out; + } -- if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) { +- if ((esig = ECDSA_do_sign(digest, hlen, key->ecdsa)) == NULL) { + psig = sigb; -+ if ((sig = d2i_ECDSA_SIG(NULL, &psig, len)) == NULL) { ++ if (d2i_ECDSA_SIG(&esig, &psig, len) == NULL) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } @@ -238,7 +345,7 @@ index 599c7199d..b036796e8 100644 if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; goto out; -@@ -102,7 +110,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +@@ -280,7 +309,7 @@ *lenp = len; ret = 0; out: @@ -246,17 +353,17 @@ index 599c7199d..b036796e8 100644 + free(sigb); sshbuf_free(b); sshbuf_free(bb); - ECDSA_SIG_free(sig); -@@ -115,22 +123,21 @@ ssh_ecdsa_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat) + ECDSA_SIG_free(esig); +@@ -293,22 +322,21 @@ + const u_char *data, size_t dlen, const char *alg, u_int compat, + struct sshkey_sig_details **detailsp) { + EVP_PKEY *pkey = NULL; - ECDSA_SIG *sig = NULL; + ECDSA_SIG *esig = NULL; BIGNUM *sig_r = NULL, *sig_s = NULL; - int hash_alg; - u_char digest[SSH_DIGEST_MAX_LENGTH]; -- size_t dlen; +- size_t hlen; + int hash_alg, len; int ret = SSH_ERR_INTERNAL_ERROR; struct sshbuf *b = NULL, *sigbuf = NULL; @@ -265,79 +372,491 @@ index 599c7199d..b036796e8 100644 if (key == NULL || key->ecdsa == NULL || sshkey_type_plain(key->type) != KEY_ECDSA || - signature == NULL || signaturelen == 0) + sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; - if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || -- (dlen = ssh_digest_bytes(hash_alg)) == 0) +- (hlen = ssh_digest_bytes(hash_alg)) == 0) + if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) return SSH_ERR_INTERNAL_ERROR; /* fetch signature */ -@@ -166,28 +173,36 @@ ssh_ecdsa_verify(const struct sshkey *key, +@@ -344,28 +372,33 @@ } sig_r = sig_s = NULL; /* transferred */ - if (sshbuf_len(sigbuf) != 0) { - ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + /* Figure out the length */ -+ if ((len = i2d_ECDSA_SIG(sig, NULL)) == 0) { ++ if ((len = i2d_ECDSA_SIG(esig, NULL)) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ if ((sigb = malloc(len)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; goto out; } -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, +- if ((ret = ssh_digest_memory(hash_alg, data, dlen, - digest, sizeof(digest))) != 0) -+ psig = sigb; -+ if ((len = i2d_ECDSA_SIG(sig, &psig)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; -+ } - -- switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) { +- goto out; +- +- switch (ECDSA_do_verify(digest, hlen, esig, key->ecdsa)) { - case 1: - ret = 0; - break; - case 0: - ret = SSH_ERR_SIGNATURE_INVALID; -+ if (sshbuf_len(sigbuf) != 0) { -+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; ++ if ((sigb = malloc(len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; goto out; - default: -- ret = SSH_ERR_LIBCRYPTO_ERROR; + } -+ -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; ++ psig = sigb; ++ if ((len = i2d_ECDSA_SIG(esig, &psig)) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } -+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, sigb, len); -+ EVP_PKEY_free(pkey); ++ if (sshbuf_len(sigbuf) != 0) { ++ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; ++ goto out; ++ } ++ ++ if (ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey) != 0) ++ goto out; ++ ret = sshkey_verify_signature(pkey, hash_alg, data, dlen, sigb, len); ++ EVP_PKEY_free(pkey); ++ out: - explicit_bzero(digest, sizeof(digest)); + free(sigb); sshbuf_free(sigbuf); sshbuf_free(b); - ECDSA_SIG_free(sig); -diff --git a/ssh-rsa.c b/ssh-rsa.c -index 9b14f9a9a..8ef3a6aca 100644 ---- a/ssh-rsa.c -+++ b/ssh-rsa.c -@@ -37,7 +37,7 @@ + ECDSA_SIG_free(esig); +@@ -375,6 +408,79 @@ + return ret; + } + ++int ++ssh_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ BN_CTX *bn_ctx = NULL; ++ uint8_t *pub_ser = NULL; ++ const char *group_name; ++ const EC_POINT *pub = NULL; ++ const BIGNUM *priv = NULL; ++ int ret = 0; ++ ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL || ++ (bn_ctx = BN_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if ((group_name = OSSL_EC_curve_nid2name(ecdsa_nid)) == NULL || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, ++ group_name, ++ strlen(group_name)) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((pub = EC_KEY_get0_public_key(k)) != NULL) { ++ const EC_GROUP *group; ++ size_t len; ++ ++ group = EC_KEY_get0_group(k); ++ len = EC_POINT_point2oct(group, pub, ++ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL); ++ if ((pub_ser = malloc(len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ EC_POINT_point2oct(group, ++ pub, ++ POINT_CONVERSION_UNCOMPRESSED, ++ pub_ser, ++ len, ++ bn_ctx); ++ if (OSSL_PARAM_BLD_push_octet_string(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, ++ pub_ser, ++ len) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ } ++ if ((priv = EC_KEY_get0_private_key(k)) != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ BN_CTX_free(bn_ctx); ++ free(pub_ser); ++ return ret; ++} ++ + /* NB. not static; used by ECDSA-SK */ + const struct sshkey_impl_funcs sshkey_ecdsa_funcs = { + /* .size = */ ssh_ecdsa_size, +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/sshkey.c openssh-9.3p1-patched/sshkey.c +--- openssh-9.3p1/sshkey.c 2023-06-06 15:53:36.608444190 +0200 ++++ openssh-9.3p1-patched/sshkey.c 2023-06-06 15:52:25.625551756 +0200 +@@ -34,6 +34,8 @@ + #include + #include + #include ++#include ++#include + #endif + + #include "crypto_api.h" +@@ -57,6 +59,7 @@ + #define SSHKEY_INTERNAL + #include "sshkey.h" + #include "match.h" ++#include "log.h" + #include "ssh-sk.h" + + #ifdef WITH_XMSS +@@ -575,6 +577,86 @@ + } + + #ifdef WITH_OPENSSL ++int ++sshkey_calculate_signature(EVP_PKEY *pkey, int hash_alg, u_char **sigp, ++ int *lenp, const u_char *data, size_t datalen) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ u_char *sig = NULL; ++ int ret, slen; ++ size_t len; ++ ++ if (sigp == NULL || lenp == NULL) { ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ ++ slen = EVP_PKEY_get_size(pkey); ++ if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) ++ return SSH_ERR_INVALID_ARGUMENT; ++ ++ len = slen; ++ if ((sig = malloc(slen)) == NULL) { ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ if ((ctx = EVP_MD_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto error; ++ } ++ if (EVP_DigestSignInit(ctx, NULL, ssh_digest_to_md(hash_alg), ++ NULL, pkey) != 1 || ++ EVP_DigestSignUpdate(ctx, data, datalen) != 1 || ++ EVP_DigestSignFinal(ctx, sig, &len) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto error; ++ } ++ ++ *sigp = sig; ++ *lenp = len; ++ /* Now owned by the caller */ ++ sig = NULL; ++ ret = 0; ++ ++error: ++ EVP_MD_CTX_free(ctx); ++ free(sig); ++ return ret; ++} ++ ++int ++sshkey_verify_signature(EVP_PKEY *pkey, int hash_alg, const u_char *data, ++ size_t datalen, u_char *sigbuf, int siglen) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ int ret; ++ ++ if ((ctx = EVP_MD_CTX_new()) == NULL) { ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ if (EVP_DigestVerifyInit(ctx, NULL, ssh_digest_to_md(hash_alg), ++ NULL, pkey) != 1 || ++ EVP_DigestVerifyUpdate(ctx, data, datalen) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto done; ++ } ++ ret = EVP_DigestVerifyFinal(ctx, sigbuf, siglen); ++ switch (ret) { ++ case 1: ++ ret = 0; ++ break; ++ case 0: ++ ret = SSH_ERR_SIGNATURE_INVALID; ++ break; ++ default: ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ break; ++ } ++ ++done: ++ EVP_MD_CTX_free(ctx); ++ return ret; ++} ++ + /* XXX: these are really begging for a table-driven approach */ + int + sshkey_curve_name_to_nid(const char *name) +@@ -3763,3 +3845,27 @@ + return 0; + } + #endif /* WITH_XMSS */ ++ ++#ifdef WITH_OPENSSL ++EVP_PKEY * ++sshkey_create_evp(OSSL_PARAM_BLD *param_bld, EVP_PKEY_CTX *ctx) ++{ ++ EVP_PKEY *ret = NULL; ++ OSSL_PARAM *params = NULL; ++ if (param_bld == NULL || ctx == NULL) { ++ debug2_f("param_bld or ctx is NULL"); ++ return NULL; ++ } ++ if ((params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ debug2_f("Could not build param list"); ++ return NULL; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1 || ++ EVP_PKEY_fromdata(ctx, &ret, EVP_PKEY_KEYPAIR, params) != 1) { ++ debug2_f("EVP_PKEY_fromdata failed"); ++ OSSL_PARAM_free(params); ++ return NULL; ++ } ++ return ret; ++} ++#endif /* WITH_OPENSSL */ +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/sshkey.h openssh-9.3p1-patched/sshkey.h +--- openssh-9.3p1/sshkey.h 2023-06-06 15:53:36.608444190 +0200 ++++ openssh-9.3p1-patched/sshkey.h 2023-06-06 15:52:25.626551768 +0200 +@@ -31,6 +31,9 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include ++#include ++#include + # ifdef OPENSSL_HAS_ECC + # include + # include +@@ -268,6 +271,10 @@ + const char *sshkey_ssh_name_plain(const struct sshkey *); + int sshkey_names_valid2(const char *, int); + char *sshkey_alg_list(int, int, int, char); ++int sshkey_calculate_signature(EVP_PKEY*, int, u_char **, ++ int *, const u_char *, size_t); ++int sshkey_verify_signature(EVP_PKEY *, int, const u_char *, ++ size_t, u_char *, int); + + int sshkey_from_blob(const u_char *, size_t, struct sshkey **); + int sshkey_fromb(struct sshbuf *, struct sshkey **); +@@ -324,6 +331,13 @@ + + void sshkey_sig_details_free(struct sshkey_sig_details *); + ++#ifdef WITH_OPENSSL ++EVP_PKEY *sshkey_create_evp(OSSL_PARAM_BLD *, EVP_PKEY_CTX *); ++int ssh_create_evp_dss(const struct sshkey *, EVP_PKEY **); ++int ssh_create_evp_rsa(const struct sshkey *, EVP_PKEY **); ++int ssh_create_evp_ec(EC_KEY *, int, EVP_PKEY **); ++#endif /* WITH_OPENSSL */ ++ + #ifdef SSHKEY_INTERNAL + int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b); + void sshkey_sk_cleanup(struct sshkey *k); +@@ -338,6 +352,10 @@ + #endif + #endif + ++#ifdef ENABLE_PKCS11 ++int pkcs11_get_ecdsa_idx(void); ++#endif ++ + #if !defined(WITH_OPENSSL) + # undef RSA + # undef DSA +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-pkcs11.c openssh-9.3p1-patched/ssh-pkcs11.c +--- openssh-9.3p1/ssh-pkcs11.c 2023-06-06 15:53:36.592443989 +0200 ++++ openssh-9.3p1-patched/ssh-pkcs11.c 2023-06-06 15:52:25.626551768 +0200 +@@ -777,8 +777,24 @@ + + return (0); + } ++ ++int ++is_ecdsa_pkcs11(EC_KEY *ecdsa) ++{ ++ if (EC_KEY_get_ex_data(ecdsa, ec_key_idx) != NULL) ++ return 1; ++ return 0; ++} + #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + ++int ++is_rsa_pkcs11(RSA *rsa) ++{ ++ if (RSA_get_ex_data(rsa, rsa_idx) != NULL) ++ return 1; ++ return 0; ++} ++ + /* remove trailing spaces */ + static void + rmspace(u_char *buf, size_t len) +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-pkcs11-client.c openssh-9.3p1-patched/ssh-pkcs11-client.c +--- openssh-9.3p1/ssh-pkcs11-client.c 2023-06-06 15:53:36.591443976 +0200 ++++ openssh-9.3p1-patched/ssh-pkcs11-client.c 2023-06-06 15:52:25.626551768 +0200 +@@ -225,8 +225,36 @@ + static RSA_METHOD *helper_rsa; + #if defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) + static EC_KEY_METHOD *helper_ecdsa; ++ ++int ++is_ecdsa_pkcs11(EC_KEY *ecdsa) ++{ ++ const EC_KEY_METHOD *meth; ++ ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgstlen, ++ const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey) = NULL; ++ ++ meth = EC_KEY_get_method(ecdsa); ++ EC_KEY_METHOD_get_sign(meth, NULL, NULL, &sign_sig); ++ if (sign_sig == ecdsa_do_sign) ++ return 1; ++ return 0; ++} + #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + ++int ++is_rsa_pkcs11(RSA *rsa) ++{ ++ const RSA_METHOD *meth; ++ int (*priv_enc)(int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa, int padding) = NULL; ++ ++ meth = RSA_get_method(rsa); ++ priv_enc = RSA_meth_get_priv_enc(meth); ++ if (priv_enc == rsa_encrypt) ++ return 1; ++ return 0; ++} ++ + /* redirect private key crypto operations to the ssh-pkcs11-helper */ + static void + wrap_key(struct sshkey *k) +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-pkcs11.h openssh-9.3p1-patched/ssh-pkcs11.h +--- openssh-9.3p1/ssh-pkcs11.h 2023-06-06 15:53:36.592443989 +0200 ++++ openssh-9.3p1-patched/ssh-pkcs11.h 2023-06-06 15:52:25.626551768 +0200 +@@ -39,6 +39,11 @@ + u_int32_t *); + #endif + ++#ifdef HAVE_EC_KEY_METHOD_NEW ++int is_ecdsa_pkcs11(EC_KEY *ecdsa); ++#endif ++int is_rsa_pkcs11(RSA *rsa); ++ + #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) + #undef ENABLE_PKCS11 + #endif +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-rsa.c openssh-9.3p1-patched/ssh-rsa.c +--- openssh-9.3p1/ssh-rsa.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/ssh-rsa.c 2023-06-06 15:52:25.627551781 +0200 +@@ -23,6 +23,8 @@ + + #include + #include ++#include ++#include + + #include + #include +@@ -36,7 +38,7 @@ #include "openbsd-compat/openssl-compat.h" -static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); +static int openssh_RSA_verify(int, const u_char *, size_t, u_char *, size_t, EVP_PKEY *); - static const char * - rsa_hash_alg_ident(int hash_alg) -@@ -90,21 +90,6 @@ rsa_hash_id_from_keyname(const char *alg) + static u_int + ssh_rsa_size(const struct sshkey *key) +@@ -131,27 +133,50 @@ + static int + ssh_rsa_generate(struct sshkey *k, int bits) + { +- RSA *private = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *res = NULL; + BIGNUM *f4 = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + + if (bits < SSH_RSA_MINIMUM_MODULUS_SIZE || + bits > SSHBUF_MAX_BIGNUM * 8) + return SSH_ERR_KEY_LENGTH; +- if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) { ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL ++ || (f4 = BN_new()) == NULL || !BN_set_word(f4, RSA_F4)) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (!BN_set_word(f4, RSA_F4) || +- !RSA_generate_key_ex(private, bits, f4, NULL)) { ++ ++ if (EVP_PKEY_keygen_init(ctx) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) <= 0) { ++ ret = SSH_ERR_KEY_LENGTH; ++ goto out; ++ } ++ ++ if (EVP_PKEY_CTX_set1_rsa_keygen_pubexp(ctx, f4) <= 0) ++ goto out; ++ ++ if (EVP_PKEY_keygen(ctx, &res) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* This function is deprecated in OpenSSL 3.0 but OpenSSH doesn't worry about it*/ ++ k->rsa = EVP_PKEY_get1_RSA(res); ++ if (k->rsa) { ++ ret = 0; ++ } else { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- k->rsa = private; +- private = NULL; +- ret = 0; + out: +- RSA_free(private); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(res); + BN_free(f4); + return ret; + } +@@ -317,21 +342,6 @@ return -1; } @@ -359,14 +878,14 @@ index 9b14f9a9a..8ef3a6aca 100644 int ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp) { -@@ -164,11 +149,10 @@ int - ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, const char *alg_ident) +@@ -393,11 +403,10 @@ + const u_char *data, size_t datalen, + const char *alg, const char *sk_provider, const char *sk_pin, u_int compat) { - const BIGNUM *rsa_n; - u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; - size_t slen = 0; -- u_int dlen, len; +- u_int hlen, len; - int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; + EVP_PKEY *pkey = NULL; + u_char *sig = NULL; @@ -375,10 +894,10 @@ index 9b14f9a9a..8ef3a6aca 100644 struct sshbuf *b = NULL; if (lenp != NULL) -@@ -180,33 +164,24 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +@@ -409,33 +418,33 @@ hash_alg = SSH_DIGEST_SHA1; else - hash_alg = rsa_hash_id_from_keyname(alg_ident); + hash_alg = rsa_hash_id_from_keyname(alg); + if (key == NULL || key->rsa == NULL || hash_alg == -1 || sshkey_type_plain(key->type) != KEY_RSA) @@ -392,7 +911,7 @@ index 9b14f9a9a..8ef3a6aca 100644 - - /* hash the data */ - nid = rsa_hash_alg_nid(hash_alg); -- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) +- if ((hlen = ssh_digest_bytes(hash_alg)) == 0) - return SSH_ERR_INTERNAL_ERROR; - if ((ret = ssh_digest_memory(hash_alg, data, datalen, - digest, sizeof(digest))) != 0) @@ -402,24 +921,33 @@ index 9b14f9a9a..8ef3a6aca 100644 - if ((sig = malloc(slen)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; +- goto out; ++#ifdef ENABLE_PKCS11 ++ if (is_rsa_pkcs11(key->rsa)) { ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ } else { ++#endif ++ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) ++ return ret; ++#ifdef ENABLE_PKCS11 + } +- +- if (RSA_sign(nid, digest, hlen, sig, &len, key->rsa) != 1) { +- ret = SSH_ERR_LIBCRYPTO_ERROR; ++#endif + ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data, + datalen); + EVP_PKEY_free(pkey); + if (ret < 0) { goto out; } - -- if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { -- ret = SSH_ERR_LIBCRYPTO_ERROR; -- goto out; -- } ++ if (len < slen) { size_t diff = slen - len; memmove(sig + diff, sig, len); -@@ -215,6 +190,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +@@ -444,6 +453,7 @@ ret = SSH_ERR_INTERNAL_ERROR; goto out; } @@ -427,7 +955,7 @@ index 9b14f9a9a..8ef3a6aca 100644 /* encode signature */ if ((b = sshbuf_new()) == NULL) { ret = SSH_ERR_ALLOC_FAIL; -@@ -235,7 +211,6 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, +@@ -464,7 +474,6 @@ *lenp = len; ret = 0; out: @@ -435,20 +963,20 @@ index 9b14f9a9a..8ef3a6aca 100644 freezero(sig, slen); sshbuf_free(b); return ret; -@@ -246,10 +221,10 @@ ssh_rsa_verify(const struct sshkey *key, - const u_char *sig, size_t siglen, const u_char *data, size_t datalen, - const char *alg) +@@ -476,10 +485,10 @@ + const u_char *data, size_t dlen, const char *alg, u_int compat, + struct sshkey_sig_details **detailsp) { - const BIGNUM *rsa_n; + EVP_PKEY *pkey = NULL; char *sigtype = NULL; int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; -- size_t len = 0, diff, modlen, dlen; +- size_t len = 0, diff, modlen, hlen; + size_t len = 0, diff, modlen; struct sshbuf *b = NULL; u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; -@@ -257,8 +232,7 @@ ssh_rsa_verify(const struct sshkey *key, +@@ -487,8 +496,7 @@ sshkey_type_plain(key->type) != KEY_RSA || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; @@ -458,30 +986,29 @@ index 9b14f9a9a..8ef3a6aca 100644 return SSH_ERR_KEY_LENGTH; if ((b = sshbuf_from(sig, siglen)) == NULL) -@@ -310,16 +284,15 @@ ssh_rsa_verify(const struct sshkey *key, +@@ -540,16 +548,13 @@ explicit_bzero(sigblob, diff); len = modlen; } -- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { +- if ((hlen = ssh_digest_bytes(hash_alg)) == 0) { - ret = SSH_ERR_INTERNAL_ERROR; +- goto out; +- } +- if ((ret = ssh_digest_memory(hash_alg, data, dlen, +- digest, sizeof(digest))) != 0) + -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; ++ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) goto out; - } -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, -- digest, sizeof(digest))) != 0) -- goto out; -+ ret = openssh_RSA_verify(hash_alg, data, datalen, sigblob, len, pkey); -+ EVP_PKEY_free(pkey); -- ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, +- ret = openssh_RSA_verify(hash_alg, digest, hlen, sigblob, len, - key->rsa); ++ ret = openssh_RSA_verify(hash_alg, data, dlen, sigblob, len, pkey); ++ EVP_PKEY_free(pkey); ++ out: freezero(sigblob, len); free(sigtype); -@@ -328,122 +301,26 @@ ssh_rsa_verify(const struct sshkey *key, +@@ -558,125 +563,110 @@ return ret; } @@ -558,7 +1085,6 @@ index 9b14f9a9a..8ef3a6aca 100644 - return 0; -} + size_t rsasize = 0; -+ const RSA *rsa; + int ret; -static int @@ -578,8 +1104,8 @@ index 9b14f9a9a..8ef3a6aca 100644 - ret = SSH_ERR_INVALID_ARGUMENT; - goto done; - } -+ rsa = EVP_PKEY_get0_RSA(pkey); - rsasize = RSA_size(rsa); +- rsasize = RSA_size(rsa); ++ rsasize = EVP_PKEY_get_size(pkey); if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || siglen == 0 || siglen > rsasize) { ret = SSH_ERR_INVALID_ARGUMENT; @@ -613,108 +1139,90 @@ index 9b14f9a9a..8ef3a6aca 100644 - freezero(decrypted, rsasize); return ret; } - #endif /* WITH_OPENSSL */ -diff --git a/sshkey.c b/sshkey.c -index ad1957762..b95ed0b10 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -358,6 +358,83 @@ sshkey_type_plain(int type) - } - #ifdef WITH_OPENSSL +int -+sshkey_calculate_signature(EVP_PKEY *pkey, int hash_alg, u_char **sigp, -+ int *lenp, const u_char *data, size_t datalen) ++ssh_create_evp_rsa(const struct sshkey *k, EVP_PKEY **pkey) +{ -+ EVP_MD_CTX *ctx = NULL; -+ u_char *sig = NULL; -+ int ret, slen, len; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ int ret = 0; ++ const BIGNUM *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL; ++ const BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; + -+ if (sigp == NULL || lenp == NULL) { -+ return SSH_ERR_INVALID_ARGUMENT; -+ } ++ if (k == NULL) ++ return SSH_ERR_INVALID_ARGUMENT; ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "RSA", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + -+ slen = EVP_PKEY_size(pkey); -+ if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) -+ return SSH_ERR_INVALID_ARGUMENT; ++ RSA_get0_key(k->rsa, &n, &e, &d); ++ RSA_get0_factors(k->rsa, &p, &q); ++ RSA_get0_crt_params(k->rsa, &dmp1, &dmq1, &iqmp); + -+ len = slen; -+ if ((sig = malloc(slen)) == NULL) { -+ return SSH_ERR_ALLOC_FAIL; -+ } -+ -+ if ((ctx = EVP_MD_CTX_new()) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto error; -+ } -+ if (EVP_SignInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || -+ EVP_SignUpdate(ctx, data, datalen) <= 0 || -+ EVP_SignFinal(ctx, sig, &len, pkey) <= 0) { ++ if (n != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_N, n) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (e != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_E, e) != 1) { + ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto error; -+ } -+ -+ *sigp = sig; -+ *lenp = len; -+ /* Now owned by the caller */ -+ sig = NULL; -+ ret = 0; -+ -+error: -+ EVP_MD_CTX_free(ctx); -+ free(sig); -+ return ret; -+} ++ goto out; ++ } ++ if (d != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_RSA_D, d) != 1) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + -+int -+sshkey_verify_signature(EVP_PKEY *pkey, int hash_alg, const u_char *data, -+ size_t datalen, u_char *sigbuf, int siglen) -+{ -+ EVP_MD_CTX *ctx = NULL; -+ int ret; ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + -+ if ((ctx = EVP_MD_CTX_new()) == NULL) { -+ return SSH_ERR_ALLOC_FAIL; -+ } -+ if (EVP_VerifyInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || -+ EVP_VerifyUpdate(ctx, data, datalen) <= 0) { ++ /* setting this to param_build makes the creation process fail */ ++ if (p != NULL && ++ EVP_PKEY_set_bn_param(*pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, p) != 1) { ++ debug2_f("failed to add 'p' param"); + ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto done; -+ } -+ ret = EVP_VerifyFinal(ctx, sigbuf, siglen, pkey); -+ switch (ret) { -+ case 1: -+ ret = 0; -+ break; -+ case 0: -+ ret = SSH_ERR_SIGNATURE_INVALID; -+ break; -+ default: ++ goto out; ++ } ++ if (q != NULL && ++ EVP_PKEY_set_bn_param(*pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, q) != 1) { ++ debug2_f("failed to add 'q' param"); + ret = SSH_ERR_LIBCRYPTO_ERROR; -+ break; -+ } ++ goto out; ++ } ++ if (dmp1 != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_EXPONENT1, dmp1) != 1) { ++ debug2_f("failed to add 'dmp1' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (dmq1 != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_EXPONENT2, dmq1) != 1) { ++ debug2_f("failed to add 'dmq1' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (iqmp != NULL && ++ EVP_PKEY_set_bn_param(*pkey, ++ OSSL_PKEY_PARAM_RSA_COEFFICIENT1, iqmp) != 1) { ++ debug2_f("failed to add 'iqmp' param"); ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + -+done: -+ EVP_MD_CTX_free(ctx); -+ return ret; ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ return ret; +} + - /* XXX: these are really begging for a table-driven approach */ - int - sshkey_curve_name_to_nid(const char *name) -diff --git a/sshkey.h b/sshkey.h -index a91e60436..270901a87 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -179,6 +179,10 @@ const char *sshkey_ssh_name(const struct sshkey *); - const char *sshkey_ssh_name_plain(const struct sshkey *); - int sshkey_names_valid2(const char *, int); - char *sshkey_alg_list(int, int, int, char); -+int sshkey_calculate_signature(EVP_PKEY*, int, u_char **, -+ int *, const u_char *, size_t); -+int sshkey_verify_signature(EVP_PKEY *, int, const u_char *, -+ size_t, u_char *, int); - - int sshkey_from_blob(const u_char *, size_t, struct sshkey **); - int sshkey_fromb(struct sshbuf *, struct sshkey **); - + static const struct sshkey_impl_funcs sshkey_rsa_funcs = { + /* .size = */ ssh_rsa_size, + /* .alloc = */ ssh_rsa_alloc, diff --git a/openssh-9.3p1-upstream-cve-2023-38408.patch b/openssh-9.3p1-upstream-cve-2023-38408.patch new file mode 100644 index 0000000000000000000000000000000000000000..e9ac2aea17bd498a51dc685c74d82c0e2bcf0e6e --- /dev/null +++ b/openssh-9.3p1-upstream-cve-2023-38408.patch @@ -0,0 +1,130 @@ +diff --git a/ssh-agent.c b/ssh-agent.c +index 618bb198..8ea831f4 100644 +diff -up openssh-9.3p1/ssh-agent.c.cve openssh-9.3p1/ssh-agent.c +--- openssh-9.3p1/ssh-agent.c.cve 2023-07-21 15:38:13.237276580 +0200 ++++ openssh-9.3p1/ssh-agent.c 2023-07-21 15:41:30.269943569 +0200 +@@ -169,6 +169,12 @@ char socket_dir[PATH_MAX]; + /* Pattern-list of allowed PKCS#11/Security key paths */ + static char *allowed_providers; + ++/* ++ * Allows PKCS11 providers or SK keys that use non-internal providers to ++ * be added over a remote connection (identified by session-bind@openssh.com). ++ */ ++static int remote_add_provider; ++ + /* locking */ + #define LOCK_SIZE 32 + #define LOCK_SALT_SIZE 16 +@@ -1228,6 +1234,12 @@ process_add_identity(SocketEntry *e) + if (strcasecmp(sk_provider, "internal") == 0) { + debug_f("internal provider"); + } else { ++ if (e->nsession_ids != 0 && !remote_add_provider) { ++ verbose("failed add of SK provider \"%.100s\": " ++ "remote addition of providers is disabled", ++ sk_provider); ++ goto out; ++ } + if (realpath(sk_provider, canonical_provider) == NULL) { + verbose("failed provider \"%.100s\": " + "realpath: %s", sk_provider, +@@ -1368,7 +1380,7 @@ no_identities(SocketEntry *e) + + #ifdef ENABLE_PKCS11 + static char * +-sanitize_pkcs11_provider(const char *provider) ++sanitize_pkcs11_provider(SocketEntry *e, const char *provider) + { + struct pkcs11_uri *uri = NULL; + char *sane_uri, *module_path = NULL; /* default path */ +@@ -1399,6 +1411,11 @@ sanitize_pkcs11_provider(const char *pro + module_path = strdup(provider); /* simple path */ + + if (module_path != NULL) { /* do not validate default NULL path in URI */ ++ if (e->nsession_ids != 0 && !remote_add_provider) { ++ verbose("failed PKCS#11 add of \"%.100s\": remote addition of " ++ "providers is disabled", provider); ++ return NULL; ++ } + if (realpath(module_path, canonical_provider) == NULL) { + verbose("failed PKCS#11 provider \"%.100s\": realpath: %s", + module_path, strerror(errno)); +@@ -1455,7 +1472,7 @@ process_add_smartcard_key(SocketEntry *e + goto send; + } + +- sane_uri = sanitize_pkcs11_provider(provider); ++ sane_uri = sanitize_pkcs11_provider(e, provider); + if (sane_uri == NULL) + goto send; + +@@ -1516,7 +1533,7 @@ process_remove_smartcard_key(SocketEntry + } + free(pin); + +- sane_uri = sanitize_pkcs11_provider(provider); ++ sane_uri = sanitize_pkcs11_provider(e, provider); + if (sane_uri == NULL) + goto send; + +@@ -2108,7 +2125,9 @@ main(int ac, char **av) + break; + case 'O': + if (strcmp(optarg, "no-restrict-websafe") == 0) +- restrict_websafe = 0; ++ restrict_websafe = 0; ++ else if (strcmp(optarg, "allow-remote-pkcs11") == 0) ++ remote_add_provider = 1; + else + fatal("Unknown -O option"); + break; +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +index 6be647ec..ebddf6c3 100644 +--- a/ssh-pkcs11.c ++++ b/ssh-pkcs11.c +@@ -1537,10 +1537,8 @@ pkcs11_register_provider(char *provider_id, char *pin, + error("dlopen %s failed: %s", provider_module, dlerror()); + goto fail; + } +- if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) { +- error("dlsym(C_GetFunctionList) failed: %s", dlerror()); +- goto fail; +- } ++ if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) ++ fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); + + p->module->handle = handle; + /* setup the pkcs11 callbacks */ +--- a/ssh-agent.1 2023-03-15 22:28:19.000000000 +0100 ++++ b/ssh-agent.1 2023-07-19 21:39:17.981406432 +0200 +@@ -107,9 +107,27 @@ + .It Fl O Ar option + Specify an option when starting + .Nm . +-Currently only one option is supported: ++Currently two options are supported: ++.Cm allow-remote-pkcs11 ++and + .Cm no-restrict-websafe . +-This instructs ++.Pp ++The ++.Cm allow-remote-pkcs11 ++option allows clients of a forwarded ++.Nm ++to load PKCS#11 or FIDO provider libraries. ++By default only local clients may perform this operation. ++Note that signalling that a ++.Nm ++client remote is performed by ++.Xr ssh 1 , ++and use of other tools to forward access to the agent socket may circumvent ++this restriction. ++.Pp ++The ++.Cm no-restrict-websafe , ++instructs + .Nm + to permit signatures using FIDO keys that might be web authentication + requests. diff --git a/openssh-9.3p1.tar.gz b/openssh-9.3p1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..94dfcebe6519cadd06318a10bbfc503284b16677 Binary files /dev/null and b/openssh-9.3p1.tar.gz differ diff --git a/openssh-9.3p1.tar.gz.asc b/openssh-9.3p1.tar.gz.asc new file mode 100644 index 0000000000000000000000000000000000000000..13b4da91dcc32aebaea1325d7bfb6348e00f5f0c --- /dev/null +++ b/openssh-9.3p1.tar.gz.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP SIGNATURE----- + +iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmQSOZYACgkQKj9BTnNg +YLrKJg//fSKjNlnb3l75ZwLoWhwpEZQp7poEq5qCCRNvu4dleuU1sMxNPl9/Ow1i +iZVW67OGNjIsJ7FJmHNF3UOgkH50c6OHivmDaTywDtyCLZvUVmaSfOe0own8s8KB +OV7czHqd9giHQlGWWTxg9eVAfOaqpzXugkzo7UoTVqEqJ3Ru/FQ4RGSIjTGzuM/0 +EC+JkKyO+0pP3mr4XfZdxsbYc9WVEG9ZIlT153y9I5MfiWM1SC/0gg4NLz025Xaa +ment5c+BdhIwYjC2f5F/9s0J6+lFHiFBHLQVGx4qq/Tx3XGfP0xBcS1V9Mkhyjzf +ZXj6acQ+T50H8p3OWZyrWn11YNtGjzkwuQWrj8Ue4NPFGqgPbANeH32yOiIWpIh0 +CtpGnRGQP1zF14hEAR5gKangTNCp/IVMBhIs4UL3zI6uS2yRLTGOWcgrnjJv26vg +jb2WmL0AeqYLZw41pbq+zmVizhhg8qk7KPQQsFxnalSFHz35tnHN8oQD5TCDxqtu +f/roTbZhW/nnlaMlEAnB09LO6e1nyDIcJ6hj0CK9cSgIn8pb1q9GdjYx5PNKwsoa +NuD+bqlzF5krjiOHJh+vDw0GKFusflL46Dmry5a4K0vLUGBn6uAUPtuwMdBsLofU +k3a4zBMlOCm6o3WqgAug4fSwCfYkJ9Dc+FaedGC1X4fys4lV/6k= +=deVJ +-----END PGP SIGNATURE----- diff --git a/openssh.spec b/openssh.spec index af49a6c25d5a365588bc16e1185a93d764c047ef..3e1c4ca9b40cd7fe26412d6b5a18372dceea01cd 100644 --- a/openssh.spec +++ b/openssh.spec @@ -6,10 +6,10 @@ %{?no_gtk2:%global gtk2 0} %global sshd_uid 74 -%global openssh_release 6 +%global openssh_release 1 Name: openssh -Version: 9.1p1 +Version: 9.3p1 Release: %{openssh_release} URL: http://www.openssh.com/portable.html License: BSD @@ -30,7 +30,8 @@ Source11: sshd-keygen Source12: sshd.tmpfiles Source13: sshd-keygen.target Source14: ssh-agent.service -Source15: ssh-keygen-bash-completion.sh +Source15: ssh-agent.socket +Source16: ssh-keygen-bash-completion.sh Patch0: openssh-6.7p1-coverity.patch Patch1: openssh-7.6p1-audit.patch Patch2: openssh-7.1p2-audit-race-condition.patch @@ -40,77 +41,63 @@ Patch5: pam_ssh_agent_auth-0.9.2-visibility.patch Patch6: pam_ssh_agent_auth-0.9.3-agent_structure.patch Patch7: pam_ssh_agent_auth-0.10.2-compat.patch Patch8: pam_ssh_agent_auth-0.10.2-dereference.patch -Patch9: openssh-7.8p1-role-mls.patch -Patch10: openssh-6.6p1-privsep-selinux.patch -Patch12: openssh-6.6p1-keycat.patch -Patch13: openssh-6.6p1-allow-ip-opts.patch -Patch15: openssh-5.9p1-ipv6man.patch -Patch16: openssh-5.8p2-sigpipe.patch -Patch17: openssh-7.2p2-x11.patch -Patch19: openssh-5.1p1-askpass-progress.patch -Patch20: openssh-4.3p2-askpass-grab-info.patch -Patch21: openssh-7.7p1.patch -Patch22: openssh-7.8p1-UsePAM-warning.patch -Patch26: openssh-8.0p1-gssapi-keyex.patch -Patch27: openssh-6.6p1-force_krb.patch -Patch28: openssh-6.6p1-GSSAPIEnablek5users.patch -Patch29: openssh-7.7p1-gssapi-new-unique.patch -Patch30: openssh-7.2p2-k5login_directory.patch -Patch31: openssh-6.6p1-kuserok.patch -Patch32: openssh-6.4p1-fromto-remote.patch -Patch33: openssh-6.6.1p1-selinux-contexts.patch -Patch34: openssh-6.6.1p1-log-in-chroot.patch -Patch35: openssh-6.6.1p1-scp-non-existing-directory.patch -Patch36: openssh-6.8p1-sshdT-output.patch -Patch37: openssh-6.7p1-sftp-force-permission.patch -Patch38: openssh-7.2p2-s390-closefrom.patch -Patch39: openssh-7.3p1-x11-max-displays.patch -Patch40: openssh-7.4p1-systemd.patch -Patch41: openssh-7.6p1-cleanup-selinux.patch -Patch42: openssh-7.5p1-sandbox.patch -Patch43: openssh-8.0p1-pkcs11-uri.patch -Patch44: openssh-7.8p1-scp-ipv6.patch -Patch46: openssh-8.0p1-crypto-policies.patch -Patch47: openssh-8.0p1-openssl-evp.patch -Patch48: openssh-8.0p1-openssl-kdf.patch -Patch49: openssh-8.2p1-visibility.patch -Patch50: openssh-8.2p1-x11-without-ipv6.patch -Patch51: openssh-8.0p1-keygen-strip-doseol.patch -Patch52: openssh-8.0p1-preserve-pam-errors.patch -Patch53: openssh-8.7p1-scp-kill-switch.patch -Patch54: bugfix-sftp-when-parse_user_host_path-empty-path-should-be-allowed.patch -Patch56: bugfix-openssh-add-option-check-username-splash.patch -Patch57: feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch -Patch58: bugfix-openssh-fix-sftpserver.patch -Patch59: set-sshd-config.patch -Patch60: feature-add-SMx-support.patch -Patch63: add-loongarch.patch -Patch65: openssh-Add-sw64-architecture.patch +Patch9: pam_ssh_agent_auth-0.10.4-rsasha2.patch +Patch10: pam_ssh_agent-configure-c99.patch +Patch11: openssh-7.8p1-role-mls.patch +Patch12: openssh-6.6p1-privsep-selinux.patch +Patch14: openssh-6.6p1-keycat.patch +Patch15: openssh-6.6p1-allow-ip-opts.patch +Patch17: openssh-5.9p1-ipv6man.patch +Patch18: openssh-5.8p2-sigpipe.patch +Patch19: openssh-7.2p2-x11.patch +Patch21: openssh-5.1p1-askpass-progress.patch +Patch22: openssh-4.3p2-askpass-grab-info.patch +Patch23: openssh-7.7p1.patch +Patch24: openssh-7.8p1-UsePAM-warning.patch +Patch28: openssh-8.0p1-gssapi-keyex.patch +Patch29: openssh-6.6p1-force_krb.patch +Patch30: openssh-6.6p1-GSSAPIEnablek5users.patch +Patch31: openssh-7.7p1-gssapi-new-unique.patch +Patch32: openssh-7.2p2-k5login_directory.patch +Patch33: openssh-6.6p1-kuserok.patch +Patch34: openssh-6.4p1-fromto-remote.patch +Patch35: openssh-6.6.1p1-selinux-contexts.patch +Patch36: openssh-6.6.1p1-log-in-chroot.patch +Patch37: openssh-6.6.1p1-scp-non-existing-directory.patch +Patch38: openssh-6.8p1-sshdT-output.patch +Patch39: openssh-6.7p1-sftp-force-permission.patch +Patch40: openssh-7.2p2-s390-closefrom.patch +Patch41: openssh-7.3p1-x11-max-displays.patch +Patch42: openssh-7.4p1-systemd.patch +Patch43: openssh-7.6p1-cleanup-selinux.patch +Patch44: openssh-7.5p1-sandbox.patch +Patch45: openssh-8.0p1-pkcs11-uri.patch +Patch46: openssh-7.8p1-scp-ipv6.patch +Patch48: openssh-8.0p1-crypto-policies.patch +Patch49: openssh-9.3p1-merged-openssl-evp.patch +Patch50: openssh-8.0p1-openssl-kdf.patch +Patch51: openssh-8.2p1-visibility.patch +Patch52: openssh-8.2p1-x11-without-ipv6.patch +Patch53: openssh-8.0p1-keygen-strip-doseol.patch +Patch54: openssh-8.0p1-preserve-pam-errors.patch +Patch55: openssh-8.7p1-scp-kill-switch.patch +Patch56: openssh-8.7p1-recursive-scp.patch +Patch57: openssh-8.7p1-minrsabits.patch +Patch58: openssh-8.7p1-ibmca.patch +Patch60: openssh-8.7p1-ssh-manpage.patch +Patch61: openssh-8.7p1-negotiate-supported-algs.patch +Patch65: openssh-9.3p1-upstream-cve-2023-38408.patch +Patch66: bugfix-sftp-when-parse_user_host_path-empty-path-should-be-allowed.patch +Patch67: bugfix-openssh-add-option-check-username-splash.patch +Patch68: feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch +Patch69: bugfix-openssh-fix-sftpserver.patch +Patch70: set-sshd-config.patch +Patch71: feature-add-SMx-support.patch +Patch72: add-loongarch.patch +Patch73: openssh-Add-sw64-architecture.patch Patch74: add-strict-scp-check-for-CVE-2020-15778.patch -Patch77: skip-scp-test-if-there-is-no-scp-on-remote-path-as-s.patch -Patch78: backport-upstream-CVE-2023-25136-fix-double-free-caused.patch -Patch79: set-ssh-config.patch -Patch80: backport-upstream-honour-user-s-umask-if-it-is-more-restricti.patch -Patch81: backport-upstream-use-correct-type-with-sizeof-ok-djm.patch -Patch82: backport-Defer-seed_rng-until-after-closefrom-call.patch -Patch83: backport-upstream-Handle-dynamic-remote-port-forwarding-in-es.patch -Patch84: backport-upstream-The-idiomatic-way-of-coping-with-signed-cha.patch -Patch85: backport-upstream-Clear-signal-mask-early-in-main-sshd-may-ha.patch -Patch86: backport-upstream-fix-bug-in-PermitRemoteOpen-which-caused-it.patch -Patch87: backport-upstream-regression-test-for-PermitRemoteOpen.patch -Patch88: backport-upstream-Copy-bytes-from-the_banana-rather-than-bana.patch -Patch89: backport-upstream-When-OpenSSL-is-not-available-skip-parts-of.patch -Patch90: backport-don-t-test-IPv6-addresses-if-platform-lacks-support.patch -Patch91: backport-upstream-avoid-printf-s-NULL-if-using-ssh.patch -Patch92: backport-upstream-Add-scp-s-path-to-test-sshd-s-PATH.patch -Patch93: backport-upstream-Instead-of-skipping-the-all-tokens-test-if-.patch -Patch94: backport-upstream-Shell-syntax-fix.-From-ren-mingshuai-vi-git.patch -Patch95: backport-Allow-writev-is-seccomp-sandbox.patch -Patch96: backport-upstream-Ensure-that-there-is-a-terminating-newline-.patch -Patch97: backport-upstream-when-restoring-non-blocking-mode-to-stdio-f.patch -Patch98: backport-upstream-test-compat_kex_proposal-by-dtucker.patch -Patch99: backport-adapt-compat_kex_proposal-test-to-portable.patch -Patch100: backport-upstream-Move-scp-path-setting-to-a-helper-function.patch +Patch75: skip-scp-test-if-there-is-no-scp-on-remote-path-as-s.patch +Patch77: set-ssh-config.patch Requires: /sbin/nologin Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 @@ -193,84 +180,71 @@ pushd pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4 %patch7 -p2 -b .psaa-compat %patch6 -p2 -b .psaa-agent %patch8 -p2 -b .psaa-deref +%patch9 -p2 -b .rsasha2 +%patch10 -p1 -b .psaa-configure-c99 # Remove duplicate headers and library files rm -f $(cat %{SOURCE4}) popd -%patch9 -p1 -b .role-mls -%patch10 -p1 -b .privsep-selinux -%patch12 -p1 -b .keycat -%patch13 -p1 -b .ip-opts -%patch15 -p1 -b .ipv6man -%patch16 -p1 -b .sigpipe -%patch17 -p1 -b .x11 -%patch19 -p1 -b .progress -%patch20 -p1 -b .grab-info -%patch21 -p1 -%patch22 -p1 -b .log-usepam-no -%patch26 -p1 -b .gsskex -%patch27 -p1 -b .force_krb -%patch29 -p1 -b .ccache_name -%patch30 -p1 -b .k5login -%patch31 -p1 -b .kuserok -%patch32 -p1 -b .fromto-remote -%patch33 -p1 -b .contexts -%patch34 -p1 -b .log-in-chroot -%patch35 -p1 -b .scp -%patch28 -p1 -b .GSSAPIEnablek5users -%patch36 -p1 -b .sshdt -%patch37 -p1 -b .sftp-force-mode -%patch38 -p1 -b .s390-dev -%patch39 -p1 -b .x11max -%patch40 -p1 -b .systemd -%patch41 -p1 -b .refactor -%patch42 -p1 -b .sandbox -%patch43 -p1 -b .pkcs11-uri -%patch44 -p1 -b .scp-ipv6 -%patch46 -p1 -b .crypto-policies -%patch47 -p1 -b .openssl-evp -%patch48 -p1 -b .openssl-kdf -%patch49 -p1 -b .visibility -%patch50 -p1 -b .x11-ipv6 -%patch51 -p1 -b .keygen-strip-doseol -%patch52 -p1 -b .preserve-pam-errors -%patch53 -p1 -b .kill-scp +%patch11 -p1 -b .role-mls +%patch12 -p1 -b .privsep-selinux +%patch14 -p1 -b .keycat +%patch15 -p1 -b .ip-opts +%patch17 -p1 -b .ipv6man +%patch18 -p1 -b .sigpipe +%patch19 -p1 -b .x11 +%patch21 -p1 -b .progress +%patch22 -p1 -b .grab-info +%patch23 -p1 +%patch24 -p1 -b .log-usepam-no +%patch28 -p1 -b .gsskex +%patch29 -p1 -b .force_krb +%patch31 -p1 -b .ccache_name +%patch32 -p1 -b .k5login +%patch33 -p1 -b .kuserok +%patch34 -p1 -b .fromto-remote +%patch35 -p1 -b .contexts +%patch36 -p1 -b .log-in-chroot +%patch37 -p1 -b .scp +%patch30 -p1 -b .GSSAPIEnablek5users +%patch38 -p1 -b .sshdt +%patch39 -p1 -b .sftp-force-mode +%patch40 -p1 -b .s390-dev +%patch41 -p1 -b .x11max +%patch42 -p1 -b .systemd +%patch43 -p1 -b .refactor +%patch44 -p1 -b .sandbox +%patch45 -p1 -b .pkcs11-uri +%patch46 -p1 -b .scp-ipv6 +%patch48 -p1 -b .crypto-policies +%patch49 -p1 -b .openssl-evp +%patch50 -p1 -b .openssl-kdf +%patch51 -p1 -b .visibility +%patch52 -p1 -b .x11-ipv6 +%patch53 -p1 -b .keygen-strip-doseol +%patch54 -p1 -b .preserve-pam-errors +%patch55 -p1 -b .kill-scp +%patch56 -p1 -b .scp-sftpdirs +%patch57 -p1 -b .minrsabits +%patch58 -p1 -b .ibmca +%patch60 -p1 -b .ssh-manpage +%patch61 -p1 -b .negotiate-supported-algs +%patch65 -p1 -b .cve-2023-38408 %patch1 -p1 -b .audit %patch2 -p1 -b .audit-race %patch0 -p1 -b .coverity -%patch54 -p1 -%patch56 -p1 -%patch57 -p1 -%patch58 -p1 -%patch59 -p1 -%patch60 -p1 -%patch63 -p1 -%patch65 -p1 + +%patch66 -p1 +%patch67 -p1 +%patch68 -p1 +%patch69 -p1 +%patch70 -p1 +%patch71 -p1 +%patch72 -p1 +%patch73 -p1 %patch74 -p1 +%patch75 -p1 %patch77 -p1 -%patch78 -p1 -%patch79 -p1 -%patch80 -p1 -%patch81 -p1 -%patch82 -p1 -%patch83 -p1 -%patch84 -p1 -%patch85 -p1 -%patch86 -p1 -%patch87 -p1 -%patch88 -p1 -%patch89 -p1 -%patch90 -p1 -%patch91 -p1 -%patch92 -p1 -%patch93 -p1 -%patch94 -p1 -%patch95 -p1 -%patch96 -p1 -%patch97 -p1 -%patch98 -p1 -%patch99 -p1 -%patch100 -p1 autoreconf pushd pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4 @@ -367,12 +341,13 @@ install -m644 %{SOURCE10} $RPM_BUILD_ROOT/%{_unitdir}/sshd-keygen@.service install -m644 %{SOURCE13} $RPM_BUILD_ROOT/%{_unitdir}/sshd-keygen.target install -d -m755 $RPM_BUILD_ROOT/%{_userunitdir} install -m644 %{SOURCE14} $RPM_BUILD_ROOT/%{_userunitdir}/ssh-agent.service +install -m644 %{SOURCE15} $RPM_BUILD_ROOT/%{_userunitdir}/ssh-agent.socket install -m744 %{SOURCE11} $RPM_BUILD_ROOT/%{_libexecdir}/openssh/sshd-keygen install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT%{_bindir}/ install contrib/ssh-copy-id.1 $RPM_BUILD_ROOT%{_mandir}/man1/ install -m644 -D %{SOURCE12} $RPM_BUILD_ROOT%{_tmpfilesdir}/%{name}.conf install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass -install -m644 %{SOURCE15} $RPM_BUILD_ROOT/etc/bash_completion.d/ssh-keygen-bash-completion.sh +install -m644 %{SOURCE16} $RPM_BUILD_ROOT/etc/bash_completion.d/ssh-keygen-bash-completion.sh ln -s gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/ssh-askpass install -m 755 -d $RPM_BUILD_ROOT%{_sysconfdir}/profile.d/ @@ -403,6 +378,14 @@ getent passwd sshd >/dev/null || \ %postun server %systemd_postun_with_restart sshd.service +%post clients +%systemd_user_post ssh-agent.service +%systemd_user_post ssh-agent.target + +%preun clients +%systemd_user_preun ssh-agent.service +%systemd_user_preun ssh-agent.target + %files %license LICENCE %doc CREDITS README.platform @@ -424,7 +407,8 @@ getent passwd sshd >/dev/null || \ %attr(0755,root,root) %{_bindir}/ssh-copy-id %attr(0755,root,root) %{_libexecdir}/openssh/ssh-pkcs11-helper %attr(0755,root,root) %{_libexecdir}/openssh/ssh-sk-helper -%attr(0755,root,root) %{_userunitdir}/ssh-agent.service +%attr(0644,root,root) %{_userunitdir}/ssh-agent.service +%attr(0644,root,root) %{_userunitdir}/ssh-agent.socket %files server %dir %attr(0711,root,root) %{_var}/empty/sshd @@ -467,6 +451,12 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog +* Thu Jul 27 2023 renmingshuai - 9.3p1-1 +- Type:requirement +- CVE:NA +- SUG:NA +- DESC:update to 9.3p1 + * Tue Jun 13 2023 renmingshuai - 9.1p1-6 - Type:bugfix - CVE:NA diff --git a/pam_ssh_agent-configure-c99.patch b/pam_ssh_agent-configure-c99.patch new file mode 100644 index 0000000000000000000000000000000000000000..bc40434968e8cce4d22acfd0735039bc9b06f782 --- /dev/null +++ b/pam_ssh_agent-configure-c99.patch @@ -0,0 +1,249 @@ +configure.ac: Improve C99 compatibility + +Future compilers will not support implicit declarations and implicit +ints by default. This means that configure probes which rely on them +will fail unconditionally, without actually testing anything. + +The changes mostly mirror what has been implemented in the openssh +repository, but had to be adapted somewhat because of drift between +the two versions of configure.ac. + +Sam James has submitted similar fixes upstream: + + + +diff --git a/configure.ac b/configure.ac +index 6496679..d927b62 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -500,10 +500,10 @@ int main(void) { exit(0); } + AC_DEFINE(HAVE_BUNDLE, 1, [Define if your system uses bundles instead of ELF shared objects]) + AC_MSG_CHECKING(if we have working getaddrinfo) + AC_TRY_RUN([#include +-main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) +- exit(0); ++int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) ++ return 0; + else +- exit(1); ++ return 1; + }], [AC_MSG_RESULT(working)], + [AC_MSG_RESULT(buggy) + AC_DEFINE(BROKEN_GETADDRINFO, 1, [getaddrinfo is broken (if present)])], +@@ -917,8 +917,8 @@ AC_SUBST(LDFLAGS_SHARED) + AC_MSG_CHECKING(compiler and flags for sanity) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([ +-#include +-int main(){exit(0);} ++#include ++int main(void){exit(0);} + ])], + [ AC_MSG_RESULT(yes) ], + [ +@@ -951,9 +951,9 @@ int main(int argc, char **argv) { + strncpy(buf,"/etc", 32); + s = dirname(buf); + if (!s || strncmp(s, "/", 32) != 0) { +- exit(1); ++ return 1; + } else { +- exit(0); ++ return 0; + } + } + ]])], +@@ -1102,7 +1102,7 @@ AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include + #include +-int main(void){struct dirent d;exit(sizeof(d.d_name)<=sizeof(char));} ++int main(void){struct dirent d;return sizeof(d.d_name)<=sizeof(char);} + ]])], + [AC_MSG_RESULT(yes)], + [ +@@ -1327,8 +1327,10 @@ AC_CHECK_FUNCS(setresuid, [ + AC_MSG_CHECKING(if setresuid seems to work) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ ++#define _GNU_SOURCE + #include + #include ++#include + int main(){errno=0; setresuid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0);} + ]])], + [AC_MSG_RESULT(yes)], +@@ -1344,8 +1346,10 @@ AC_CHECK_FUNCS(setresgid, [ + AC_MSG_CHECKING(if setresgid seems to work) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ ++#define _GNU_SOURCE + #include + #include ++#include + int main(){errno=0; setresgid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0);} + ]])], + [AC_MSG_RESULT(yes)], +@@ -1384,7 +1388,7 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include +-int main(void){char b[5];snprintf(b,5,"123456789");exit(b[4]!='\0');} ++int main(void){char b[5];snprintf(b,5,"123456789");return b[4]!='\0';} + ]])], + [AC_MSG_RESULT(yes)], + [ +@@ -1418,7 +1422,7 @@ int x_snprintf(char *str,size_t count,const char *fmt,...) + int main(void) + { + char x[1]; +- exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1); ++ return x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1; + } ]])], + [AC_MSG_RESULT(yes)], + [ +@@ -1467,7 +1471,8 @@ AC_MSG_CHECKING([for (overly) strict mkstemp]) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include +-main() { char template[]="conftest.mkstemp-test"; ++#include ++int main(void) { char template[]="conftest.mkstemp-test"; + if (mkstemp(template) == -1) + exit(1); + unlink(template); exit(0); +@@ -1492,10 +1497,14 @@ if test ! -z "$check_for_openpty_ctty_bug"; then + AC_MSG_CHECKING(if openpty correctly handles controlling tty) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ ++#include + #include + #include + #include + #include ++#ifdef HAVE_PTY_H ++#include ++#endif + + int + main() +@@ -1543,6 +1552,7 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include ++#include + #include + #include + #include +@@ -1748,6 +1758,7 @@ AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL, 1, + AC_MSG_CHECKING([OpenSSL header version]) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ ++#include + #include + #include + #include +@@ -1794,12 +1805,12 @@ int main(void) { + + fd = fopen(DATA,"w"); + if(fd == NULL) +- exit(1); ++ return 1; + + if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0) +- exit(1); ++ return 1; + +- exit(0); ++ return 0; + } + ]])], + [ +@@ -1829,7 +1840,7 @@ AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include + #include +-int main(void) { exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1); } ++int main(void) { return SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1; } + ]])], + [ + AC_MSG_RESULT(yes) +@@ -2598,7 +2609,7 @@ dnl test snprintf (broken on SCO w/gcc) + #include + #include + #ifdef HAVE_SNPRINTF +-main() ++int main(void) + { + char buf[50]; + char expected_out[50]; +@@ -2611,11 +2622,11 @@ main() + strcpy(expected_out, "9223372036854775807"); + snprintf(buf, mazsize, "%lld", num); + if(strcmp(buf, expected_out) != 0) +- exit(1); +- exit(0); ++ return 1; ++ return 0; + } + #else +-main() { exit(0); } ++int main(void) { return 0; } + #endif + ]])], [ true ], [ AC_DEFINE(BROKEN_SNPRINTF) ], + AC_MSG_WARN([cross compiling: Assuming working snprintf()]) +@@ -2746,11 +2757,11 @@ AC_CACHE_CHECK([for msg_accrights field in struct msghdr], + int main() { + #ifdef msg_accrights + #error "msg_accrights is a macro" +-exit(1); ++return 1; + #endif + struct msghdr m; + m.msg_accrights = 0; +-exit(0); ++return 0; + } + ])], + [ ac_cv_have_accrights_in_msghdr="yes" ], +@@ -2773,11 +2784,11 @@ AC_CACHE_CHECK([for msg_control field in struct msghdr], + int main() { + #ifdef msg_control + #error "msg_control is a macro" +-exit(1); ++return 1; + #endif + struct msghdr m; + m.msg_control = 0; +-exit(0); ++return 0; + } + ])], + [ ac_cv_have_control_in_msghdr="yes" ], +@@ -2791,7 +2802,7 @@ if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then + fi + + AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ +- AC_TRY_LINK([], ++ AC_TRY_LINK([#include ], + [ extern char *__progname; printf("%s", __progname); ], + [ ac_cv_libc_defines___progname="yes" ], + [ ac_cv_libc_defines___progname="no" ] +@@ -2871,7 +2882,7 @@ if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then + fi + + AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [ +- AC_TRY_LINK([], ++ AC_TRY_LINK([#include ], + [ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);], + [ ac_cv_libc_defines_sys_errlist="yes" ], + [ ac_cv_libc_defines_sys_errlist="no" ] +@@ -2884,7 +2895,7 @@ fi + + + AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [ +- AC_TRY_LINK([], ++ AC_TRY_LINK([#include ], + [ extern int sys_nerr; printf("%i", sys_nerr);], + [ ac_cv_libc_defines_sys_nerr="yes" ], + [ ac_cv_libc_defines_sys_nerr="no" ] diff --git a/pam_ssh_agent_auth-0.10.4-rsasha2.patch b/pam_ssh_agent_auth-0.10.4-rsasha2.patch new file mode 100644 index 0000000000000000000000000000000000000000..c8815bbefa19b158686d6e24c5406632fee85e44 --- /dev/null +++ b/pam_ssh_agent_auth-0.10.4-rsasha2.patch @@ -0,0 +1,19 @@ +diff -up openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.rsasha2 openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c +--- openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.rsasha2 2022-07-15 15:08:12.865585410 +0200 ++++ openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c 2022-07-15 15:16:25.164282372 +0200 +@@ -87,8 +87,13 @@ userauth_pubkey_from_id(const char *ruse + (r = sshbuf_put_string(b, pkblob, blen)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + +- if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0) +- goto user_auth_clean_exit; ++ if (sshkey_type_plain(id->key->type) == KEY_RSA ++ && ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), "rsa-sha2-256", 0) == 0) { ++ /* Do nothing */ ++ } else { ++ if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0) ++ goto user_auth_clean_exit; ++ } + + /* test for correct signature */ + if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0, NULL) == 0) diff --git a/ssh-agent.service b/ssh-agent.service index c2150227fb5b25343f853eb3ee907e58f488b397..311f91dd758864d859fb92f470ade2dae1e8a15f 100644 --- a/ssh-agent.service +++ b/ssh-agent.service @@ -5,10 +5,15 @@ ConditionEnvironment=!SSH_AGENT_PID Description=OpenSSH key agent Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1) +Requires=ssh-agent.socket [Service] Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket +ExecStartPre=/usr/bin/rm -f $SSH_AUTH_SOCK ExecStart=/usr/bin/ssh-agent -a $SSH_AUTH_SOCK PassEnvironment=SSH_AGENT_PID SuccessExitStatus=2 Type=forking + +[Install] +Also=ssh-agent.socket diff --git a/ssh-agent.socket b/ssh-agent.socket new file mode 100644 index 0000000000000000000000000000000000000000..d589cbc8ebb8e461e0611a01c6d3e45af9345f05 --- /dev/null +++ b/ssh-agent.socket @@ -0,0 +1,14 @@ +[Unit] +Description=OpenSSH key agent +Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1) + +[Socket] +ListenStream=%t/ssh-agent.socket +Service=ssh-agent.service +Priority=6 +Backlog=5 +SocketMode=0600 +DirectoryMode=0700 + +[Install] +WantedBy=sockets.target