From 70d08634553fc1a55a445a37bf6b8523a450f03a Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 12 Jan 2024 13:55:32 +0100 Subject: [PATCH 01/80] Applying patches to rebase to OpenSSH 9.6p1 Based on Damien Milnes' PR https://src.fedoraproject.org/rpms/openssh/pull-request/63 Also rebasing openssh-8.0p1-pkcs11-uri.patch to 9.6 by Dmitry Belyavskiy --- .gitignore | 2 + openssh-6.6.1p1-selinux-contexts.patch | 22 ++- openssh-6.7p1-coverity.patch | 87 ---------- openssh-7.2p2-x11.patch | 24 +-- openssh-7.8p1-role-mls.patch | 10 +- openssh-8.0p1-gssapi-keyex.patch | 12 +- openssh-8.0p1-pkcs11-uri.patch | 215 ++++++++++++------------- openssh-8.7p1-minrsabits.patch | 22 ++- openssh-8.7p1-recursive-scp.patch | 167 +++++++++---------- openssh-9.3p1-merged-openssl-evp.patch | 55 +++---- openssh.spec | 16 +- sources | 4 +- 12 files changed, 269 insertions(+), 367 deletions(-) diff --git a/.gitignore b/.gitignore index 0ac6ea0..6988bb2 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ pam_ssh_agent_auth-0.9.2.tar.bz2 /openssh-9.0p1.tar.gz.asc /openssh-9.3p1.tar.gz /openssh-9.3p1.tar.gz.asc +/openssh-9.6p1.tar.gz +/openssh-9.6p1.tar.gz.asc diff --git a/openssh-6.6.1p1-selinux-contexts.patch b/openssh-6.6.1p1-selinux-contexts.patch index fa9d591..eab724a 100644 --- a/openssh-6.6.1p1-selinux-contexts.patch +++ b/openssh-6.6.1p1-selinux-contexts.patch @@ -93,19 +93,17 @@ index 8f32464..18a2ca4 100644 #endif diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c -index 22ea8ef..1fc963d 100644 ---- a/openbsd-compat/port-linux.c -+++ b/openbsd-compat/port-linux.c -@@ -179,7 +179,7 @@ ssh_selinux_change_context(const char *newname) - strlcpy(newctx + len, newname, newlen - len); - if ((cx = index(cx + 1, ':'))) - strlcat(newctx, cx, newlen); -- debug3("%s: setting context from '%s' to '%s'", __func__, -+ debug_f("setting context from '%s' to '%s'", - oldctx, newctx); +--- a/openbsd-compat/port-linux.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/openbsd-compat/port-linux.c (date 1703108053912) +@@ -207,7 +207,7 @@ + xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx, + newname, cx2 == NULL ? "" : cx2); + +- debug3_f("setting context from '%s' to '%s'", oldctx, newctx); ++ debug_f("setting context from '%s' to '%s'", oldctx, newctx); if (setcon(newctx) < 0) - do_log2(log_level, "%s: setcon %s from %s failed with %s", - __func__, newctx, oldctx, strerror(errno)); + do_log2_f(log_level, "setcon %s from %s failed with %s", + newctx, oldctx, strerror(errno)); diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h index cb51f99..8b7cda2 100644 --- a/openbsd-compat/port-linux.h diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index 1dca99c..01a061b 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -17,17 +17,6 @@ diff -up openssh-8.5p1/auth-krb5.c.coverity openssh-8.5p1/auth-krb5.c return oerrno; } /* make sure the KRB5CCNAME is set for non-standard location */ -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 */ -+ sshbuf_free(b); - return 0; - } - 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 @@ -45,14 +34,6 @@ diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c 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); -+ /* coverity[leaked_storage : FALSE] */ - return r; - } - @@ -1261,6 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, cons return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); @@ -149,23 +130,6 @@ diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c return (0); error: -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"); -- if (tmp1 > 0) -+ if (tmp1 >= 0) - close(tmp1); -- if (tmp2 > 0) -- close(tmp2); -+ /*DEAD CODE if (tmp2 >= 0) -+ close(tmp2);*/ - return 0; - } - close(tmp1); 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 @@ -219,23 +183,6 @@ diff -up openssh-8.5p1/readconf.c.coverity openssh-8.5p1/readconf.c goto out; } free(arg2); -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); -- waitpid(do_cmd_pid, NULL, 0); -+ (void) waitpid(do_cmd_pid, NULL, 0); - } - if (do_cmd_pid2 > 1) { - kill(do_cmd_pid2, signo ? signo : SIGTERM); -- waitpid(do_cmd_pid2, NULL, 0); -+ (void) waitpid(do_cmd_pid2, NULL, 0); - } - - if (signo) 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 @@ -263,18 +210,6 @@ diff -up openssh-8.7p1/serverloop.c.coverity openssh-8.7p1/serverloop.c if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != (int)tun) goto done; -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); -- waitpid(pid, NULL, 0); -+ (void) waitpid(pid, NULL, 0); - } - - _exit(1); 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 @@ -286,28 +221,6 @@ diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c return NULL; } /* validate also provider from URI */ -@@ -1220,8 +1220,8 @@ main(int ac, char **av) - sanitise_stdfd(); - - /* drop */ -- setegid(getgid()); -- setgid(getgid()); -+ (void) setegid(getgid()); -+ (void) setgid(getgid()); - - platform_disable_tracing(0); /* strict=no */ - -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; -+ /* coverity[leaked_handle: FALSE]*/ - muxclient(options.control_path); - /* muxclient() doesn't return on success. */ - fatal("Failed to connect to new control master"); 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 diff --git a/openssh-7.2p2-x11.patch b/openssh-7.2p2-x11.patch index 0a19ecb..b27d7c4 100644 --- a/openssh-7.2p2-x11.patch +++ b/openssh-7.2p2-x11.patch @@ -1,21 +1,23 @@ -diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c ---- openssh-7.2p2/channels.c.x11 2016-03-09 19:04:48.000000000 +0100 -+++ openssh-7.2p2/channels.c 2016-06-03 10:42:04.775164520 +0200 -@@ -3990,21 +3990,24 @@ x11_create_display_inet(int x11_display_ +diff --git a/channels.c b/channels.c +--- a/channels.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/channels.c (date 1703026069921) +@@ -5075,11 +5075,13 @@ } - + static int -connect_local_xsocket_path(const char *pathname) +connect_local_xsocket_path(const char *pathname, int len) { int sock; struct sockaddr_un addr; - -+ if (len <= 0) -+ return -1; + ++ if (len <= 0) ++ return -1; sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock == -1) + if (sock == -1) { error("socket: %.100s", strerror(errno)); +@@ -5087,11 +5089,12 @@ + } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; - strlcpy(addr.sun_path, pathname, sizeof addr.sun_path); @@ -29,8 +31,8 @@ diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c - error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); return -1; } - -@@ -4012,8 +4015,18 @@ static int + +@@ -5099,8 +5102,18 @@ connect_local_xsocket(u_int dnr) { char buf[1024]; diff --git a/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch index 4dc460a..347766d 100644 --- a/openssh-7.8p1-role-mls.patch +++ b/openssh-7.8p1-role-mls.patch @@ -23,7 +23,7 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c if ((style = strchr(user, ':')) != NULL) *style++ = 0; -@@ -296,8 +304,15 @@ input_userauth_request(int type, u_int32 +@@ -314,8 +314,15 @@ input_userauth_request(int type, u_int32 use_privsep ? " [net]" : ""); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; @@ -34,12 +34,12 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c + if (use_privsep) { mm_inform_authserv(service, style); +#ifdef WITH_SELINUX -+ mm_inform_authrole(role); ++ mm_inform_authrole(role); +#endif -+ } ++ } userauth_banner(ssh); - if (auth2_setup_methods_lists(authctxt) != 0) - ssh_packet_disconnect(ssh, + if ((r = kex_server_update_ext_info(ssh)) != 0) + fatal_fr(r, "kex_server_update_ext_info failed"); diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c --- openssh/auth2-gss.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/auth2-gss.c 2018-08-22 11:15:42.459799171 +0200 diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index 89bcd0d..682d65f 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -144,8 +144,8 @@ index 9351e042..d6446c0c 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,7 +1,7 @@ - /* $OpenBSD: auth2-gss.c,v 1.33 2021/12/19 22:12:07 djm Exp $ */ - + /* $OpenBSD: auth2-gss.c,v 1.34 2023/03/31 04:22:27 djm Exp $ */ + /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. @@ -1268,7 +1268,7 @@ index ce85f043..574c7609 100644 +#endif + /* prototype */ - static int kex_choose_conf(struct ssh *); + static int kex_choose_conf(struct ssh *, uint32_t seq); static int kex_input_newkeys(int, u_int32_t, struct ssh *); @@ -115,15 +120,28 @@ static const struct kexalg kexalgs[] = { #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ @@ -3400,7 +3400,7 @@ index 60de6087..db5c65bc 100644 .It HashKnownHosts .It Host .It HostbasedAcceptedAlgorithms -@@ -579,6 +585,8 @@ flag), +@@ -624,6 +624,8 @@ (supported message integrity codes), .Ar kex (key exchange algorithms), @@ -3408,7 +3408,7 @@ index 60de6087..db5c65bc 100644 +(GSSAPI key exchange algorithms), .Ar key (key types), - .Ar key-cert + .Ar key-ca-sign diff --git a/ssh.c b/ssh.c index 15aee569..110cf9c1 100644 --- a/ssh.c @@ -3444,7 +3444,7 @@ index 5e8ef548..1ff999b6 100644 +# GSSAPIKeyExchange no +# GSSAPITrustDNS no # BatchMode no - # CheckHostIP yes + # CheckHostIP no # AddressFamily any diff --git a/ssh_config.5 b/ssh_config.5 index 06a32d31..3f490697 100644 diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index 551351c..605f878 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -128,20 +128,8 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in + regress/unittests/utf8/test_utf8$(EXEEXT) \ + regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \ - tests: file-tests t-exec interop-tests unit + tests: file-tests t-exec interop-tests extra-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 - - trace "remove pkcs11 keys" -- echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 -+ ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 - r=$? - if [ $r -ne 0 ]; then - fail "ssh-add -e failed: exit code $r" 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 @@ -523,9 +511,9 @@ diff -up openssh-8.7p1/regress/pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/pkcs11 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 @@ +@@ -1,6 +1,6 @@ + # $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $ - REGRESS_FAIL_EARLY?= yes SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion -SUBDIR+=authopt misc sshsig +SUBDIR+=authopt misc sshsig pkcs11 @@ -925,26 +913,29 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c +#endif + 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 +472,11 @@ add_file(int agent_fd, const char *filen - - static int + add_file(int agent_fd, const char *filename, int key_only, int cert_only, + int qflag, const char *skprovider, +@@ -445,15 +472,14 @@ add_file(int agent_fd, const char *filen update_card(int agent_fd, int add, const char *id, int qflag, -- struct dest_constraint **dest_constraints, size_t ndest_constraints) -+ struct dest_constraint **dest_constraints, size_t ndest_constraints, char *pin) + int key_only, int cert_only, + struct dest_constraint **dest_constraints, size_t ndest_constraints, +- struct sshkey **certs, size_t ncerts) ++ struct sshkey **certs, size_t ncerts, char *pin) { - char *pin = NULL; int r, ret = -1; + if (key_only) + ncerts = 0; + - if (add) { + if (add && pin == NULL) { if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; -@@ -630,6 +656,14 @@ static int - const char *skprovider, struct dest_constraint **dest_constraints, - size_t ndest_constraints) +@@ -630,6 +656,14 @@ do_file(int + char *file, int qflag, const char *skprovider, + struct dest_constraint **dest_constraints, size_t ndest_constraints) { +#ifdef ENABLE_PKCS11 + if (strlen(file) >= strlen(PKCS11_URI_SCHEME) && @@ -955,21 +946,21 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c + } +#endif if (deleting) { - if (delete_file(agent_fd, file, key_only, qflag) == -1) - return -1; + if (delete_file(agent_fd, file, key_only, + cert_only, qflag) == -1) @@ -813,7 +846,7 @@ main(int argc, char **argv) - } - if (pkcs11provider != NULL) { if (update_card(agent_fd, !deleting, pkcs11provider, -- qflag, dest_constraints, ndest_constraints) == -1) -+ qflag, dest_constraints, ndest_constraints, NULL) == -1) + qflag, key_only, cert_only, + dest_constraints, ndest_constraints, +- certs, ncerts) == -1) ++ certs, ncerts, NULL) == -1) ret = 1; goto done; } 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) +@@ -1549,10 +1549,72 @@ no_identities(SocketEntry *e) } #ifdef ENABLE_PKCS11 @@ -1043,25 +1034,23 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds = 0; -@@ -869,33 +931,28 @@ process_add_smartcard_key(SocketEntry *e - error_f("failed to parse constraints"); +@@ -1643,25 +1643,18 @@ process_add_smartcard_key(SocketEntry *e + "providers is disabled", provider); goto send; } - if (realpath(provider, canonical_provider) == NULL) { - verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", - provider, strerror(errno)); -- goto send; -- } -- if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { -- verbose("refusing PKCS#11 add of \"%.100s\": " -- "provider not allowed", canonical_provider); -+ + sane_uri = sanitize_pkcs11_provider(provider); + if (sane_uri == NULL) goto send; - } +- if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { +- verbose("refusing PKCS#11 add of \"%.100s\": " +- "provider not allowed", canonical_provider); +- goto send; +- } - debug_f("add %.100s", canonical_provider); -+ if (lifetime && !death) death = monotime() + lifetime; @@ -1069,23 +1058,30 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c + debug_f("add %.100s", sane_uri); + count = pkcs11_add_provider(sane_uri, pin, &keys, &comments); for (i = 0; i < count; i++) { - k = keys[i]; - if (lookup_identity(k) == NULL) { - id = xcalloc(1, sizeof(Identity)); - id->key = k; - keys[i] = NULL; /* transferred */ -- id->provider = xstrdup(canonical_provider); -+ id->provider = xstrdup(sane_uri); - if (*comments[i] != '\0') { - id->comment = comments[i]; - comments[i] = NULL; /* transferred */ - } else { -- id->comment = xstrdup(canonical_provider); -+ id->comment = xstrdup(sane_uri); - } - id->death = death; - id->confirm = confirm; -@@ -910,6 +967,7 @@ process_add_smartcard_key(SocketEntry *e + if (comments[i] == NULL || comments[i][0] == '\0') { + free(comments[i]); +- comments[i] = xstrdup(canonical_provider); ++ comments[i] = xstrdup(sane_uri); + } + for (j = 0; j < ncerts; j++) { + if (!sshkey_is_cert(certs[j])) +@@ -1671,13 +1664,13 @@ process_add_smartcard_key(SocketEntry *e + if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) + continue; + add_p11_identity(k, xstrdup(comments[i]), +- canonical_provider, death, confirm, ++ sane_uri, death, confirm, + dest_constraints, ndest_constraints); + success = 1; + } + if (!cert_only && lookup_identity(keys[i]) == NULL) { + add_p11_identity(keys[i], comments[i], +- canonical_provider, death, confirm, ++ sane_uri, death, confirm, + dest_constraints, ndest_constraints); + keys[i] = NULL; /* transferred */ + comments[i] = NULL; /* transferred */ +@@ -1690,6 +1700,7 @@ process_add_smartcard_key(SocketEntry *e send: free(pin); free(provider); @@ -1093,7 +1089,7 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c free(keys); free(comments); free_dest_constraints(dest_constraints, ndest_constraints); -@@ -918,7 +976,7 @@ send: +@@ -1700,7 +1720,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { @@ -1102,7 +1098,7 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c int r, success = 0; Identity *id, *nxt; -@@ -930,30 +988,29 @@ process_remove_smartcard_key(SocketEntry +@@ -1750,30 +1800,29 @@ process_remove_smartcard_key(SocketEntry } free(pin); @@ -1335,14 +1331,14 @@ diff -up openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-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; + struct helper *helper; + debug_f("called, name = %s", name); + - if (fd < 0 && pkcs11_start_helper() < 0) - return (-1); - + if ((helper = helper_by_provider(name)) == NULL && + (helper = pkcs11_start_helper(name)) == NULL) + return -1; @@ -342,6 +344,7 @@ pkcs11_add_provider(char *name, char *pi *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); if (labelsp) @@ -1774,20 +1770,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c -/* remove trailing spaces */ +/* remove trailing spaces. Note, that this does NOT guarantee the buffer + * will be null terminated if there are no trailing spaces! */ - static void + static char * rmspace(u_char *buf, size_t len) { -@@ -630,8 +788,8 @@ - - if (!len) - return; -- for (i = len - 1; i > 0; i--) -- if (i == len - 1 || buf[i] == ' ') -+ for (i = len - 1; i > 0; i--) -+ if (buf[i] == ' ') - buf[i] = '\0'; - else - break; @@ -650,8 +806,8 @@ pkcs11_open_session(struct pkcs11_provid CK_SESSION_HANDLE session; int login_required, ret; @@ -2191,7 +2176,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c int ret = -1; struct pkcs11_provider *p = NULL; void *handle = NULL; -@@ -1517,164 +1702,305 @@ +@@ -1514,162 +1708,310 @@ pkcs11_initialize_provider(struct pkcs11 CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; @@ -2199,28 +2184,35 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + struct pkcs11_module *m = NULL; - if (providerp == NULL) +- goto fail; +- *providerp = NULL; +- +- if (keyp != NULL) +- *keyp = NULL; +- if (labelsp != NULL) +- *labelsp = NULL; + /* if no provider specified, fallback to p11-kit */ + if (uri->module_path == NULL) { +#ifdef PKCS11_DEFAULT_PROVIDER + provider_module = strdup(PKCS11_DEFAULT_PROVIDER); +#else + error_f("No module path provided"); - goto fail; -- *providerp = NULL; ++ goto fail; +#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); ++ if (lib_contains_symbol(provider_module, "C_GetFunctionList") != 0) { ++ error("provider %s is not a PKCS11 library", provider_module); + goto fail; + } +- if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) { +- error("provider %s is not a PKCS11 library", provider_id); - goto fail; + if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL + && m->valid) { @@ -2247,14 +2239,11 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + 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 = xcalloc(1, sizeof(*p)); - p->name = xstrdup(provider_id); - p->handle = handle; -+ + p->module->handle = handle; /* setup the pkcs11 callbacks */ if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { @@ -2279,15 +2268,13 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + provider_module, rv); goto fail; } -- rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID)); -- rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription)); -- debug("provider %s: manufacturerID <%s> cryptokiVersion %d.%d" -- " libraryDescription <%s> libraryVersion %d.%d", +- debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" +- " libraryDescription <%.*s> libraryVersion %d.%d", - provider_id, -- p->info.manufacturerID, +- RMSPACE(p->info.manufacturerID), - p->info.cryptokiVersion.major, - p->info.cryptokiVersion.minor, -- p->info.libraryDescription, +- RMSPACE(p->info.libraryDescription), - p->info.libraryVersion.major, - p->info.libraryVersion.minor); - if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { @@ -2331,13 +2318,13 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto fail; } - p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); ++ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); p->valid = 1; -- nkeys = 0; ++ m->valid = 1; + nkeys = 0; - for (i = 0; i < p->nslots; i++) { - token = &p->slotinfo[i].token; - if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) -+ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); -+ m->valid = 1; + for (i = 0; i < m->nslots; i++) { + token = &m->slotinfo[i].token; + if ((rv = f->C_GetTokenInfo(m->slotlist[i], token)) @@ -2353,23 +2340,25 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + token->flags = 0; continue; } - rmspace(token->label, sizeof(token->label)); - rmspace(token->manufacturerID, sizeof(token->manufacturerID)); - rmspace(token->model, sizeof(token->model)); - rmspace(token->serialNumber, sizeof(token->serialNumber)); -- debug("provider %s slot %lu: label <%s> manufacturerID <%s> " -- "model <%s> serial <%s> flags 0x%lx", + debug("provider %s slot %lu: label <%.*s> " + "manufacturerID <%.*s> model <%.*s> serial <%.*s> " + "flags 0x%lx", - provider_id, (unsigned long)i, ++ provider_module, (unsigned long)i, + RMSPACE(token->label), RMSPACE(token->manufacturerID), + RMSPACE(token->model), RMSPACE(token->serialNumber), + token->flags); + } + m->module_path = provider_module; + provider_module = NULL; + -+ /* insert unconditionally -- remove if there will be no keys later */ ++ /* now owned by caller */ ++ *providerp = p; ++ + TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); + p->refcount++; /* add to provider list */ -+ *providerp = p; -+ return 0; + ++ return 0; +fail: + if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) + error("C_Finalize for provider %s failed: %lu", @@ -2385,7 +2374,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + } + if (handle) + dlclose(handle); -+ return ret; ++ return (ret); +} + +/* @@ -2451,12 +2440,12 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + debug("provider %s slot %lu: label <%.32s> manufacturerID <%.32s> " + "model <%.16s> serial <%.16s> flags 0x%lx", + provider_uri, (unsigned long)i, - token->label, token->manufacturerID, token->model, - token->serialNumber, token->flags); ++ token->label, token->manufacturerID, token->model, ++ token->serialNumber, token->flags); /* - * open session, login with pin and retrieve public - * keys (if keyp is provided) -+ * open session if not yet openend, login with pin and ++ * open session if not yet opened, login with pin and + * retrieve public keys (if keyp is provided) */ - if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || @@ -2517,8 +2506,8 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c - free(p->slotlist); - free(p->slotinfo); - free(p); -+ TAILQ_REMOVE(&pkcs11_providers, p, next); -+ pkcs11_provider_unref(p); ++ TAILQ_REMOVE(&pkcs11_providers, p, next); ++ pkcs11_provider_unref(p); } - if (handle) - dlclose(handle); diff --git a/openssh-8.7p1-minrsabits.patch b/openssh-8.7p1-minrsabits.patch index 2ed59a3..479b55d 100644 --- a/openssh-8.7p1-minrsabits.patch +++ b/openssh-8.7p1-minrsabits.patch @@ -1,23 +1,21 @@ diff --git a/readconf.c b/readconf.c -index 7f26c680..42be690b 100644 ---- a/readconf.c -+++ b/readconf.c -@@ -320,6 +320,7 @@ static struct { +--- a/readconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/readconf.c (date 1703169891147) +@@ -326,6 +326,7 @@ { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, - { "requiredrsasize", oRequiredRSASize }, + { "requiredrsasize", oRequiredRSASize }, + { "rsaminsize", oRequiredRSASize }, /* alias */ { "enableescapecommandline", oEnableEscapeCommandline }, - - { NULL, oBadOption } + { "obscurekeystroketiming", oObscureKeystrokeTiming }, + { "channeltimeout", oChannelTimeout }, diff --git a/servconf.c b/servconf.c -index 29df0463..423772b1 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -676,6 +680,7 @@ static struct { +--- a/servconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/servconf.c (date 1703169891148) +@@ -691,6 +691,7 @@ { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, - { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, + { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, + { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */ { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, diff --git a/openssh-8.7p1-recursive-scp.patch b/openssh-8.7p1-recursive-scp.patch index f0d9b0f..17c340e 100644 --- a/openssh-8.7p1-recursive-scp.patch +++ b/openssh-8.7p1-recursive-scp.patch @@ -1,28 +1,28 @@ -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 - +diff --git a/scp.c b/scp.c +--- a/scp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/scp.c (date 1703111453316) +@@ -1372,7 +1372,7 @@ + if (src_is_dir && iamrecursive) { - if (upload_dir(conn, src, abs_dst, pflag, + if (sftp_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 - + error("failed to upload directory %s to %s", src, targ); + errs = 1; + } +diff --git a/sftp-client.c b/sftp-client.c +--- a/sftp-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp-client.c (date 1703169614263) +@@ -1003,7 +1003,7 @@ + /* 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) +-sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) ++sftp_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 +@@ -1049,11 +1049,43 @@ if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); @@ -33,7 +33,7 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c - 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) { ++ if ((r = sftp_mkdir(conn, path, &a, 0)) != 0) { + sshbuf_free(msg); + return NULL; + } @@ -71,111 +71,112 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c } 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 +@@ -1078,9 +1110,9 @@ } - + char * --do_realpath(struct sftp_conn *conn, const char *path) -+do_realpath(struct sftp_conn *conn, const char *path, int create_dir) +-sftp_realpath(struct sftp_conn *conn, const char *path) ++sftp_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); +- return sftp_realpath_expand(conn, path, 0); ++ return sftp_realpath_expand(conn, path, 0, create_dir); } - + int -@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c +@@ -1094,9 +1126,9 @@ { - if (!can_expand_path(conn)) { + if (!sftp_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 sftp_realpath_expand(conn, path, 0); ++ return sftp_realpath_expand(conn, path, 0, 0); } -- return do_realpath_expand(conn, path, 1); -+ return do_realpath_expand(conn, path, 1, 0); +- return sftp_realpath_expand(conn, path, 1); ++ return sftp_realpath_expand(conn, path, 1, 0); } - + int -@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con +@@ -2016,7 +2048,7 @@ 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 + +- if ((src_canon = sftp_realpath(conn, src)) == NULL) { ++ if ((src_canon = sftp_realpath(conn, src, 0)) == NULL) { + error("download \"%s\": path canonicalization failed", src); + return -1; + } +@@ -2365,12 +2397,12 @@ int - upload_dir(struct sftp_conn *conn, const char *src, const char *dst, + sftp_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 + +- if ((dst_canon = sftp_realpath(conn, dst)) == NULL) { ++ if ((dst_canon = sftp_realpath(conn, dst, create_dir)) == NULL) { + error("upload \"%s\": path canonicalization failed", dst); + return -1; + } +@@ -2825,7 +2857,7 @@ 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); - + +- if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) { ++ if ((from_path_canon = sftp_realpath(from, from_path, 0)) == NULL) { + error("crossload \"%s\": path canonicalization failed", + from_path); + return -1; +diff --git a/sftp-client.h b/sftp-client.h +--- a/sftp-client.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp-client.h (date 1703111691284) +@@ -111,7 +111,7 @@ + int sftp_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); - +-char *sftp_realpath(struct sftp_conn *, const char *); ++char *sftp_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 + char *sftp_expand_path(struct sftp_conn *, const char *); +@@ -163,7 +163,7 @@ * times if 'pflag' is set */ - int upload_dir(struct sftp_conn *, const char *, const char *, + int sftp_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, + +diff --git a/sftp.c b/sftp.c +--- a/sftp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp.c (date 1703168795365) +@@ -807,7 +807,7 @@ + (rflag || global_rflag)) { + if (sftp_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 (sftp_upload(conn, g.gl_pathv[i], abs_dst, +@@ -1642,7 +1642,7 @@ 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) { + path1 = sftp_make_absolute(path1, *pwd); +- if ((tmp = sftp_realpath(conn, path1)) == NULL) { ++ if ((tmp = sftp_realpath(conn, path1, 0)) == NULL) { err = 1; break; } -@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn, +@@ -2247,7 +2247,7 @@ } #endif /* USE_LIBEDIT */ - -- remote_path = do_realpath(conn, "."); -+ remote_path = do_realpath(conn, ".", 0); - if (remote_path == NULL) + +- if ((remote_path = sftp_realpath(conn, ".")) == NULL) ++ if ((remote_path = sftp_realpath(conn, ".", 0)) == NULL) fatal("Need cwd"); startdir = xstrdup(remote_path); + diff --git a/openssh-9.3p1-merged-openssl-evp.patch b/openssh-9.3p1-merged-openssl-evp.patch index 95d86c3..6a30485 100644 --- a/openssh-9.3p1-merged-openssl-evp.patch +++ b/openssh-9.3p1-merged-openssl-evp.patch @@ -659,15 +659,15 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x # ifdef OPENSSL_HAS_ECC # include # include -@@ -268,6 +271,10 @@ +@@ -266,6 +266,10 @@ const char *sshkey_ssh_name_plain(const struct sshkey *); - int sshkey_names_valid2(const char *, int); + int sshkey_names_valid2(const char *, int, 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 @@ @@ -695,11 +695,11 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x #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 @@ - +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +--- a/ssh-pkcs11.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11.c (date 1703110934679) +@@ -620,8 +620,24 @@ + return (0); } + @@ -711,7 +711,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + return 0; +} #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - + +int +is_rsa_pkcs11(RSA *rsa) +{ @@ -722,14 +722,14 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + /* remove trailing spaces. Note, that this does NOT guarantee the buffer * will be null terminated if there are no trailing spaces! */ - static void -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; + static char * +diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c +--- a/ssh-pkcs11-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11-client.c (date 1703110830967) +@@ -402,8 +402,36 @@ + if (helper->nrsa == 0 && helper->nec == 0) + helper_terminate(helper); + } + +int +is_ecdsa_pkcs11(EC_KEY *ecdsa) @@ -744,8 +744,8 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + return 1; + return 0; +} - #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - + #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ + +int +is_rsa_pkcs11(RSA *rsa) +{ @@ -762,14 +762,15 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + /* 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 - + wrap_key(struct helper *helper, struct sshkey *k) +diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h +--- a/ssh-pkcs11.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11.h (date 1703111023334) +@@ -38,6 +38,12 @@ + /* Only available in ssh-pkcs11-client.c so far */ + int pkcs11_make_cert(const struct sshkey *, + const struct sshkey *, struct sshkey **); ++ +#ifdef HAVE_EC_KEY_METHOD_NEW +int is_ecdsa_pkcs11(EC_KEY *ecdsa); +#endif diff --git a/openssh.spec b/openssh.spec index 3076ac0..6ba18b8 100644 --- a/openssh.spec +++ b/openssh.spec @@ -46,15 +46,15 @@ %{?static_openssl:%global static_libcrypto 1} # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%global openssh_ver 9.3p1 -%global openssh_rel 13 +%global openssh_ver 9.6p1 +%global openssh_rel 1 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 9 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.1 +Release: %{openssh_rel}%{?dist} URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -228,9 +228,6 @@ Patch1006: openssh-8.7p1-negotiate-supported-algs.patch Patch1012: openssh-9.0p1-evp-fips-dh.patch Patch1013: openssh-9.0p1-evp-fips-ecdh.patch Patch1014: openssh-8.7p1-nohostsha1proof.patch -Patch1015: openssh-9.3p1-upstream-cve-2023-38408.patch -# upstream b7afd8a4ecaca8afd3179b55e9db79c0ff210237 -Patch1016: openssh-9.3p1-openssl-compat.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -306,7 +303,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.1 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist} License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -433,8 +430,6 @@ popd %patch -P 1012 -p1 -b .evp-fips-dh %patch -P 1013 -p1 -b .evp-fips-ecdh %patch -P 1014 -p1 -b .nosha1hostproof -%patch -P 1015 -p1 -b .cve-2023-38408 -%patch -P 1016 -p1 -b .ossl-version %patch -P 100 -p1 -b .coverity @@ -744,6 +739,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Tue Dec 26 2023 Daniel Milnes - 9.6p1-1 +- Update to OpenSSH 9.6 + * Fri Dec 22 2023 Florian Weimer - 9.3p1-13.1 - Fix type errors in downstream gssapi-keyex patch diff --git a/sources b/sources index 585760a..62f22c0 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (openssh-9.3p1.tar.gz) = 087ff6fe5f6caab4c6c3001d906399e02beffad7277280f11187420c2939fd4befdcb14643862a657ce4cad2f115b82a0a1a2c99df6ee54dcd76b53647637c19 -SHA512 (openssh-9.3p1.tar.gz.asc) = 6222378eb24a445c6c1db255392b405f5369b1af0e92f558d4ba05b0d83ab0d084cb8f4b91d7ae8636f333d970638a6635e2bc7af885135dd34992d87f2ef1f4 +SHA512 (openssh-9.6p1.tar.gz) = 0ebf81e39914c3a90d7777a001ec7376a94b37e6024baf3e972c58f0982b7ddef942315f5e01d56c00ff95603b4a20ee561ab918ecc55511df007ac138160509 +SHA512 (openssh-9.6p1.tar.gz.asc) = aec5a5bd6ce480a8e5b5879dc55f8186aec90fe61f085aa92ad7d07f324574aa781be09c83b7443a32848d091fd44fb12c1842d49cee77afc351e550ffcc096d SHA512 (pam_ssh_agent_auth-0.10.4.tar.gz) = caccf72174d15e43f4c86a459ac6448682e62116557cf1e1e828955f3d1731595b238df42adec57860e7f341e92daf5d8285020bcb5018f3b8a5145aa32ee1c2 SHA512 (gpgkey-736060BA.gpg) = df44f3fdbcd1d596705348c7f5aed3f738c5f626a55955e0642f7c6c082995cf36a1b1891bb41b8715cb2aff34fef1c877e0eff0d3507dd00a055ba695757a21 From 61f514d27438658836b11ee5875ab1d2a76c7b0d Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 12 Jan 2024 14:43:38 +0100 Subject: [PATCH 02/80] pkcs11-uri cleanup --- openssh-8.0p1-pkcs11-uri.patch | 270 ++++++++++++++++----------------- 1 file changed, 135 insertions(+), 135 deletions(-) diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index 605f878..459832a 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -1,7 +1,7 @@ -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( +diff -up openssh-9.6p1/configure.ac.pkcs11-uri openssh-9.6p1/configure.ac +--- openssh-9.6p1/configure.ac.pkcs11-uri 2024-01-12 14:25:25.228942213 +0100 ++++ openssh-9.6p1/configure.ac 2024-01-12 14:25:25.233942336 +0100 +@@ -2066,12 +2066,14 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) @@ -16,7 +16,7 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac fi ] ) -@@ -2019,6 +2021,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) +@@ -2095,6 +2097,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_FUNCS([dlopen]) AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) @@ -57,7 +57,7 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5624,6 +5660,7 @@ echo " BSD Auth support +@@ -5708,6 +5744,7 @@ echo " BSD Auth support echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" @@ -65,10 +65,10 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac echo " U2F/FIDO support: $enable_sk" echo "" -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 -@@ -105,7 +105,7 @@ +diff -up openssh-9.6p1/Makefile.in.pkcs11-uri openssh-9.6p1/Makefile.in +--- openssh-9.6p1/Makefile.in.pkcs11-uri 2024-01-12 14:25:25.204941622 +0100 ++++ openssh-9.6p1/Makefile.in 2024-01-12 14:25:25.233942336 +0100 +@@ -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 \ @@ -77,7 +77,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in 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 +@@ -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) @@ -86,15 +86,15 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in 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 +@@ -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 + 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 @@ -103,7 +103,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in $(MKDIR_P) `pwd`/regress/misc/sk-dummy [ -f `pwd`/regress/Makefile ] || \ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile -@@ -685,6 +690,16 @@ +@@ -685,6 +690,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) @@ -120,7 +120,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in # 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 +@@ -720,7 +735,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) \ @@ -130,10 +130,10 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in tests: file-tests t-exec interop-tests extra-tests unit echo all tests passed -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 +diff -up openssh-9.6p1/regress/Makefile.pkcs11-uri openssh-9.6p1/regress/Makefile +--- openssh-9.6p1/regress/Makefile.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/regress/Makefile 2024-01-12 14:25:25.233942336 +0100 +@@ -134,7 +134,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 \ @@ -143,7 +143,7 @@ diff -up openssh-8.7p1/regress/Makefile.pkcs11-uri openssh-8.7p1/regress/Makefil 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: +@@ -273,8 +274,9 @@ unit: V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ @@ -155,9 +155,9 @@ diff -up openssh-8.7p1/regress/Makefile.pkcs11-uri openssh-8.7p1/regress/Makefil -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 +diff -up openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri openssh-9.6p1/regress/pkcs11.sh +--- openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri 2024-01-12 14:25:25.233942336 +0100 ++++ openssh-9.6p1/regress/pkcs11.sh 2024-01-12 14:25:25.233942336 +0100 @@ -0,0 +1,349 @@ +# +# Copyright (c) 2017 Red Hat @@ -508,9 +508,9 @@ diff -up openssh-8.7p1/regress/pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/pkcs11 + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi -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 +diff -up openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri openssh-9.6p1/regress/unittests/Makefile +--- openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/regress/unittests/Makefile 2024-01-12 14:25:25.233942336 +0100 @@ -1,6 +1,6 @@ # $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $ @@ -519,9 +519,9 @@ diff -up openssh-8.7p1/regress/unittests/Makefile.pkcs11-uri openssh-8.7p1/regre +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 +diff -up openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-9.6p1/regress/unittests/pkcs11/tests.c +--- openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri 2024-01-12 14:25:25.233942336 +0100 ++++ openssh-9.6p1/regress/unittests/pkcs11/tests.c 2024-01-12 14:25:25.233942336 +0100 @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2017 Red Hat @@ -869,10 +869,10 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 + test_parse_invalid(); + test_generate_valid(); +} -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 @@ +diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c +--- openssh-9.6p1/ssh-add.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-add.c 2024-01-12 14:25:25.233942336 +0100 +@@ -69,6 +69,7 @@ #include "ssh-sk.h" #include "sk-api.h" #include "hostfile.h" @@ -880,7 +880,7 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c /* argv0 */ extern char *__progname; -@@ -229,6 +230,34 @@ delete_all(int agent_fd, int qflag) +@@ -240,6 +241,34 @@ delete_all(int agent_fd, int qflag) return ret; } @@ -915,7 +915,7 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c static int add_file(int agent_fd, const char *filename, int key_only, int cert_only, int qflag, const char *skprovider, -@@ -445,15 +472,14 @@ add_file(int agent_fd, const char *filen +@@ -460,15 +489,14 @@ static int update_card(int agent_fd, int add, const char *id, int qflag, int key_only, int cert_only, struct dest_constraint **dest_constraints, size_t ndest_constraints, @@ -933,7 +933,7 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; -@@ -630,6 +656,14 @@ do_file(int +@@ -656,6 +684,14 @@ do_file(int agent_fd, int deleting, int char *file, int qflag, const char *skprovider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { @@ -948,7 +948,7 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c if (deleting) { if (delete_file(agent_fd, file, key_only, cert_only, qflag) == -1) -@@ -813,7 +846,7 @@ main(int argc, char **argv) +@@ -999,7 +1035,7 @@ main(int argc, char **argv) if (update_card(agent_fd, !deleting, pkcs11provider, qflag, key_only, cert_only, dest_constraints, ndest_constraints, @@ -957,10 +957,10 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c ret = 1; goto done; } -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 -@@ -1549,10 +1549,72 @@ no_identities(SocketEntry *e) +diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c +--- openssh-9.6p1/ssh-agent.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-agent.c 2024-01-12 14:25:25.234942360 +0100 +@@ -1549,10 +1549,72 @@ add_p11_identity(struct sshkey *key, cha } #ifdef ENABLE_PKCS11 @@ -1034,7 +1034,7 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds = 0; -@@ -1643,25 +1643,18 @@ process_add_smartcard_key(SocketEntry *e +@@ -1581,25 +1643,18 @@ process_add_smartcard_key(SocketEntry *e "providers is disabled", provider); goto send; } @@ -1065,7 +1065,7 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c } for (j = 0; j < ncerts; j++) { if (!sshkey_is_cert(certs[j])) -@@ -1671,13 +1664,13 @@ process_add_smartcard_key(SocketEntry *e +@@ -1609,13 +1664,13 @@ process_add_smartcard_key(SocketEntry *e if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) continue; add_p11_identity(k, xstrdup(comments[i]), @@ -1081,15 +1081,15 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c dest_constraints, ndest_constraints); keys[i] = NULL; /* transferred */ comments[i] = NULL; /* transferred */ -@@ -1690,6 +1700,7 @@ process_add_smartcard_key(SocketEntry *e +@@ -1628,6 +1683,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); -@@ -1700,7 +1720,7 @@ send: + free_dest_constraints(dest_constraints, ndest_constraints); +@@ -1640,7 +1696,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { @@ -1098,7 +1098,7 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c int r, success = 0; Identity *id, *nxt; -@@ -1750,30 +1800,29 @@ process_remove_smartcard_key(SocketEntry +@@ -1652,30 +1708,29 @@ process_remove_smartcard_key(SocketEntry } free(pin); @@ -1135,10 +1135,10 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c send_status(e, success); } #endif /* ENABLE_PKCS11 */ -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 +diff -up openssh-9.6p1/ssh_config.5.pkcs11-uri openssh-9.6p1/ssh_config.5 +--- openssh-9.6p1/ssh_config.5.pkcs11-uri 2024-01-12 14:25:25.208941721 +0100 ++++ openssh-9.6p1/ssh_config.5 2024-01-12 14:25:25.234942360 +0100 +@@ -1216,6 +1216,21 @@ may also be used in conjunction with .Cm CertificateFile in order to provide any certificate also needed for authentication with the identity. @@ -1160,10 +1160,10 @@ diff -up openssh-8.7p1/ssh_config.5.pkcs11-uri openssh-8.7p1/ssh_config.5 .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) +diff -up openssh-9.6p1/ssh.c.pkcs11-uri openssh-9.6p1/ssh.c +--- openssh-9.6p1/ssh.c.pkcs11-uri 2024-01-12 14:25:25.208941721 +0100 ++++ openssh-9.6p1/ssh.c 2024-01-12 14:25:25.234942360 +0100 +@@ -882,6 +882,14 @@ main(int ac, char **av) options.gss_deleg_creds = 1; break; case 'i': @@ -1178,7 +1178,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c 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) +@@ -1784,6 +1792,7 @@ main(int ac, char **av) #ifdef ENABLE_PKCS11 (void)pkcs11_del_provider(options.pkcs11_provider); #endif @@ -1186,7 +1186,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c skip_connect: exit_status = ssh_session2(ssh, cinfo); -@@ -2197,6 +2206,45 @@ ssh_session2(struct ssh *ssh, const stru +@@ -2307,6 +2316,45 @@ ssh_session2(struct ssh *ssh, const stru options.escape_char : SSH_ESCAPECHAR_NONE, id); } @@ -1232,7 +1232,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c /* 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 +@@ -2321,11 +2369,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]; @@ -1244,7 +1244,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); -@@ -2228,33 +2271,46 @@ load_public_identity_files(const struct +@@ -2338,33 +2381,46 @@ load_public_identity_files(const struct sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 @@ -1310,10 +1310,10 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c 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) +diff -up openssh-9.6p1/ssh-keygen.c.pkcs11-uri openssh-9.6p1/ssh-keygen.c +--- openssh-9.6p1/ssh-keygen.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-keygen.c 2024-01-12 14:25:25.234942360 +0100 +@@ -862,8 +862,11 @@ do_download(struct passwd *pw) free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ @@ -1327,10 +1327,10 @@ diff -up openssh-8.7p1/ssh-keygen.c.pkcs11-uri openssh-8.7p1/ssh-keygen.c } 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 +diff -up openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-client.c +--- openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11-client.c 2024-01-12 14:25:25.234942360 +0100 +@@ -592,6 +592,8 @@ pkcs11_add_provider(char *name, char *pi struct sshbuf *msg; struct helper *helper; @@ -1339,7 +1339,7 @@ diff -up openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-c if ((helper = helper_by_provider(name)) == NULL && (helper = pkcs11_start_helper(name)) == NULL) return -1; -@@ -342,6 +344,7 @@ pkcs11_add_provider(char *name, char *pi +@@ -612,6 +614,7 @@ pkcs11_add_provider(char *name, char *pi *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); if (labelsp) *labelsp = xcalloc(nkeys, sizeof(char *)); @@ -1347,9 +1347,9 @@ diff -up openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-c 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 +diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c +--- openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11.c 2024-01-12 14:28:09.170975480 +0100 @@ -55,8 +55,8 @@ struct pkcs11_slotinfo { int logged_in; }; @@ -1533,10 +1533,10 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c struct pkcs11_provider *p; + int rv = -1; + char *provider_uri = pkcs11_uri_get(uri); ++ ++ debug3_f("called with provider %s", provider_uri); - if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { -+ debug3_f("called with provider %s", provider_uri); -+ + if ((p = pkcs11_provider_lookup(provider_uri)) != NULL) { TAILQ_REMOVE(&pkcs11_providers, p, next); pkcs11_provider_finalize(p); @@ -1607,7 +1607,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c /* 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, +@@ -208,6 +349,7 @@ pkcs11_k11_free(void *parent, void *ptr, if (k11->provider) pkcs11_provider_unref(k11->provider); free(k11->keyid); @@ -1615,7 +1615,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(k11); } -@@ -222,8 +363,8 @@ pkcs11_find(struct pkcs11_provider *p, C +@@ -222,8 +364,8 @@ pkcs11_find(struct pkcs11_provider *p, C CK_RV rv; int ret = -1; @@ -1626,7 +1626,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); return (-1); -@@ -260,14 +403,14 @@ pkcs11_login_slot(struct pkcs11_provider +@@ -260,14 +402,14 @@ pkcs11_login_slot(struct pkcs11_provider if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) verbose("Deferring PIN entry to reader keypad."); else { @@ -1644,7 +1644,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c (pin != NULL) ? strlen(pin) : 0); if (pin != NULL) freezero(pin, strlen(pin)); -@@ -297,13 +438,14 @@ pkcs11_login_slot(struct pkcs11_provider +@@ -297,13 +439,14 @@ pkcs11_login_slot(struct pkcs11_provider static int pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) { @@ -1661,7 +1661,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c } -@@ -319,13 +461,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs +@@ -319,13 +462,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs *val = 0; @@ -1679,7 +1679,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c attr.type = type; attr.pValue = &flag; -@@ -356,13 +499,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C +@@ -356,13 +500,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C int always_auth = 0; int did_login = 0; @@ -1697,7 +1697,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c 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, con +@@ -439,8 +584,8 @@ pkcs11_rsa_private_encrypt(int flen, con return (-1); } @@ -1708,7 +1708,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c tlen = RSA_size(rsa); /* XXX handle CKR_BUFFER_TOO_SMALL */ -@@ -484,7 +628,7 @@ pkcs11_rsa_start_wrapper(void) +@@ -484,7 +629,7 @@ pkcs11_rsa_start_wrapper(void) /* redirect private key operations for rsa key to pkcs11 token */ static int pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1717,7 +1717,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c { struct pkcs11_key *k11; -@@ -502,6 +646,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * +@@ -502,6 +647,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } @@ -1730,7 +1730,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c 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, +@@ -532,8 +683,8 @@ ecdsa_do_sign(const unsigned char *dgst, return (NULL); } @@ -1741,7 +1741,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c siglen = ECDSA_size(ec); sig = xmalloc(siglen); -@@ -598,7 +748,7 @@ pkcs11_ecdsa_start_wrapper(void) +@@ -598,7 +749,7 @@ pkcs11_ecdsa_start_wrapper(void) static int pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1750,10 +1750,10 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c { struct pkcs11_key *k11; -@@ -614,6 +764,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider +@@ -615,6 +766,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); @@ -1763,7 +1763,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c EC_KEY_set_method(ec, ec_key_method); EC_KEY_set_ex_data(ec, ec_key_idx, k11); -@@ -622,7 +779,8 @@ +@@ -622,7 +779,8 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider } #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ @@ -1773,7 +1773,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c static char * rmspace(u_char *buf, size_t len) { -@@ -650,8 +806,8 @@ pkcs11_open_session(struct pkcs11_provid +@@ -654,8 +812,8 @@ pkcs11_open_session(struct pkcs11_provid CK_SESSION_HANDLE session; int login_required, ret; @@ -1784,7 +1784,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c login_required = si->token.flags & CKF_LOGIN_REQUIRED; -@@ -661,9 +817,9 @@ pkcs11_open_session(struct pkcs11_provid +@@ -665,9 +823,9 @@ pkcs11_open_session(struct pkcs11_provid error("pin required"); return (-SSH_PKCS11_ERR_PIN_REQUIRED); } @@ -1796,7 +1796,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c return (-1); } if (login_required && pin != NULL && strlen(pin) != 0) { -@@ -699,7 +855,8 @@ static struct sshkey * +@@ -703,7 +861,8 @@ static struct sshkey * pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1806,7 +1806,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -713,14 +870,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -717,14 +876,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1827,7 +1827,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -731,19 +889,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -735,19 +895,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1851,7 +1851,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -755,8 +913,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -759,8 +919,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1862,7 +1862,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (group == NULL) { ossl_error("d2i_ECPKParameters failed"); goto fail; -@@ -767,13 +925,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -771,13 +931,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1879,7 +1879,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (octet == NULL) { ossl_error("d2i_ASN1_OCTET_STRING failed"); goto fail; -@@ -790,7 +948,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -794,7 +954,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1888,7 +1888,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -806,7 +964,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -810,7 +970,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ ec = NULL; /* now owned by key */ fail: @@ -1897,7 +1897,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(key_attr[i].pValue); if (ec) EC_KEY_free(ec); -@@ -823,7 +981,8 @@ static struct sshkey * +@@ -827,7 +987,8 @@ static struct sshkey * pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1907,7 +1907,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -834,14 +993,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -838,14 +999,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1928,7 +1928,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -852,19 +1012,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -856,19 +1018,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1952,7 +1952,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -876,8 +1036,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -880,8 +1042,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr goto fail; } @@ -1963,7 +1963,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rsa_n == NULL || rsa_e == NULL) { error("BN_bin2bn failed"); goto fail; -@@ -886,7 +1046,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -890,7 +1052,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr fatal_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ @@ -1972,7 +1972,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -901,7 +1061,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -905,7 +1067,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr rsa = NULL; /* now owned by key */ fail: @@ -1981,7 +1981,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(key_attr[i].pValue); RSA_free(rsa); -@@ -912,7 +1072,8 @@ static int +@@ -916,7 +1078,8 @@ static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { @@ -1991,7 +1991,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -936,14 +1097,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -940,14 +1103,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p memset(&cert_attr, 0, sizeof(cert_attr)); cert_attr[0].type = CKA_ID; @@ -2012,7 +2012,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return -1; -@@ -955,18 +1117,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -959,18 +1123,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p * XXX assumes CKA_ID is always first. */ if (cert_attr[1].ulValueLen == 0 || @@ -2035,7 +2035,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto out; -@@ -980,8 +1143,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -984,8 +1149,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p subject = xstrdup("invalid subject"); X509_NAME_free(x509_name); @@ -2046,7 +2046,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c error("d2i_x509 failed"); goto out; } -@@ -1001,7 +1164,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1005,7 +1170,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2055,7 +2055,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1031,7 +1194,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1035,7 +1200,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2064,7 +2064,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1051,7 +1214,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1055,7 +1220,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } out: @@ -2073,7 +2073,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(cert_attr[i].pValue); X509_free(x509); RSA_free(rsa); -@@ -1102,11 +1265,12 @@ note_key(struct pkcs11_provider *p, CK_U +@@ -1106,11 +1271,12 @@ note_key(struct pkcs11_provider *p, CK_U */ static int pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2088,7 +2088,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1123,10 +1287,23 @@ pkcs11_fetch_certs(struct pkcs11_provide +@@ -1127,10 +1293,23 @@ pkcs11_fetch_certs(struct pkcs11_provide key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2106,16 +2106,16 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + key_attr[nattr].ulValueLen = strlen(uri->object); + nattr++; + } -+ -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - 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, nattr); if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1207,11 +1384,12 @@ fail: +@@ -1211,11 +1390,12 @@ fail: */ static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2130,7 +2130,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1227,10 +1405,23 @@ pkcs11_fetch_keys(struct pkcs11_provider +@@ -1231,10 +1411,23 @@ pkcs11_fetch_keys(struct pkcs11_provider key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2148,16 +2148,16 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + 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; -@@ -1499,16 +1690,10 @@ pkcs11_ecdsa_generate_private_key(struct +@@ -1503,16 +1696,10 @@ pkcs11_ecdsa_generate_private_key(struct } #endif /* WITH_PKCS11_KEYGEN */ @@ -2176,7 +2176,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c int ret = -1; struct pkcs11_provider *p = NULL; void *handle = NULL; -@@ -1514,162 +1708,310 @@ pkcs11_initialize_provider(struct pkcs11 +@@ -1521,162 +1708,309 @@ pkcs11_register_provider(char *provider_ CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; @@ -2320,11 +2320,11 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c - p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); + m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); p->valid = 1; -+ m->valid = 1; - nkeys = 0; +- nkeys = 0; - for (i = 0; i < p->nslots; i++) { - token = &p->slotinfo[i].token; - if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) ++ m->valid = 1; + for (i = 0; i < m->nslots; i++) { + token = &m->slotinfo[i].token; + if ((rv = f->C_GetTokenInfo(m->slotlist[i], token)) @@ -2565,7 +2565,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c /* no keys found or some other error, de-register provider */ if (nkeys <= 0 && p != NULL) { -@@ -1684,7 +2012,37 @@ pkcs11_add_provider(char *provider_id, c +@@ -1685,7 +2019,37 @@ pkcs11_add_provider(char *provider_id, c pkcs11_provider_unref(p); } if (nkeys == 0) @@ -2604,9 +2604,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c 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 +diff -up openssh-9.6p1/ssh-pkcs11.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11.h +--- openssh-9.6p1/ssh-pkcs11.h.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11.h 2024-01-12 14:25:25.235942385 +0100 @@ -22,10 +22,14 @@ #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 @@ -2622,9 +2622,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11.h #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 +diff -up openssh-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri.c +--- openssh-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri 2024-01-12 14:25:25.235942385 +0100 ++++ openssh-9.6p1/ssh-pkcs11-uri.c 2024-01-12 14:25:25.235942385 +0100 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2017 Red Hat @@ -3063,9 +3063,9 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. +} + +#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 +diff -up openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri.h +--- openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri 2024-01-12 14:25:25.235942385 +0100 ++++ openssh-9.6p1/ssh-pkcs11-uri.h 2024-01-12 14:25:25.235942385 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Red Hat From bbc9a8c13f071693a7a559984534125bbe254f33 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 12 Jan 2024 15:03:41 +0100 Subject: [PATCH 03/80] The code is compiling --- openssh-8.0p1-gssapi-keyex.patch | 44 ++++++++++++++++++++++++++++++++ openssh-8.0p1-pkcs11-uri.patch | 12 ++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index 682d65f..3e5ccec 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -4028,3 +4028,47 @@ index 71a3fddc..37a43a67 100644 KEY_UNSPEC }; +diff --git a/packet.h b/packet.h +--- a/packet.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/packet.h (date 1703172586447) +@@ -124,6 +124,7 @@ + int ssh_packet_send2(struct ssh *); + + int ssh_packet_read(struct ssh *); ++int ssh_packet_read_expect(struct ssh *, u_int type); + int ssh_packet_read_poll(struct ssh *); + int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); + int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); +diff --git a/packet.c b/packet.c +--- a/packet.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/packet.c (date 1703172586447) +@@ -1425,6 +1416,29 @@ + return type; + } + ++/* ++ * Waits until a packet has been received, verifies that its type matches ++ * that given, and gives a fatal error and exits if there is a mismatch. ++ */ ++ ++int ++ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) ++{ ++ int r; ++ u_char type; ++ ++ if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) ++ return r; ++ if (type != expected_type) { ++ if ((r = sshpkt_disconnect(ssh, ++ "Protocol error: expected packet type %d, got %d", ++ expected_type, type)) != 0) ++ return r; ++ return SSH_ERR_PROTOCOL_ERROR; ++ } ++ return 0; ++} ++ + static int + ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + { diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index 459832a..1e7940d 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -880,12 +880,16 @@ diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c /* argv0 */ extern char *__progname; -@@ -240,6 +241,34 @@ delete_all(int agent_fd, int qflag) +@@ -240,6 +241,38 @@ delete_all(int agent_fd, int qflag) return ret; } +#ifdef ENABLE_PKCS11 -+static int update_card(int, int, const char *, int, struct dest_constraint **, size_t, char *); ++static int ++update_card(int agent_fd, int add, const char *id, int qflag, ++ int key_only, int cert_only, ++ struct dest_constraint **dest_constraints, size_t ndest_constraints, ++ struct sshkey **certs, size_t ncerts, char *pin); + +int +update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag, @@ -907,8 +911,8 @@ diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c + } + pkcs11_uri_cleanup(uri); + -+ return update_card(agent_fd, adding, pkcs11_uri, qflag, -+ dest_constraints, ndest_constraints, pin); ++ return update_card(agent_fd, adding, pkcs11_uri, qflag, 1, 0, ++ dest_constraints, ndest_constraints, NULL, 0, pin); +} +#endif + From f238307bdf080b28c61bb23e9e50720611d32157 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 12 Jan 2024 13:55:32 +0100 Subject: [PATCH 04/80] Applying patches to rebase to OpenSSH 9.6p1 Based on Damien Milnes' PR https://src.fedoraproject.org/rpms/openssh/pull-request/63 Also rebasing openssh-8.0p1-pkcs11-uri.patch to 9.6 by Dmitry Belyavskiy --- .gitignore | 2 + openssh-6.6.1p1-selinux-contexts.patch | 22 +- openssh-6.7p1-coverity.patch | 87 ----- openssh-7.2p2-x11.patch | 24 +- openssh-7.8p1-role-mls.patch | 10 +- openssh-8.0p1-gssapi-keyex.patch | 56 ++- openssh-8.0p1-pkcs11-uri.patch | 469 ++++++++++++------------- openssh-8.7p1-minrsabits.patch | 22 +- openssh-8.7p1-recursive-scp.patch | 167 ++++----- openssh-9.3p1-merged-openssl-evp.patch | 55 +-- openssh.spec | 18 +- sources | 4 +- 12 files changed, 444 insertions(+), 492 deletions(-) diff --git a/.gitignore b/.gitignore index 0ac6ea0..6988bb2 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,5 @@ pam_ssh_agent_auth-0.9.2.tar.bz2 /openssh-9.0p1.tar.gz.asc /openssh-9.3p1.tar.gz /openssh-9.3p1.tar.gz.asc +/openssh-9.6p1.tar.gz +/openssh-9.6p1.tar.gz.asc diff --git a/openssh-6.6.1p1-selinux-contexts.patch b/openssh-6.6.1p1-selinux-contexts.patch index fa9d591..eab724a 100644 --- a/openssh-6.6.1p1-selinux-contexts.patch +++ b/openssh-6.6.1p1-selinux-contexts.patch @@ -93,19 +93,17 @@ index 8f32464..18a2ca4 100644 #endif diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c -index 22ea8ef..1fc963d 100644 ---- a/openbsd-compat/port-linux.c -+++ b/openbsd-compat/port-linux.c -@@ -179,7 +179,7 @@ ssh_selinux_change_context(const char *newname) - strlcpy(newctx + len, newname, newlen - len); - if ((cx = index(cx + 1, ':'))) - strlcat(newctx, cx, newlen); -- debug3("%s: setting context from '%s' to '%s'", __func__, -+ debug_f("setting context from '%s' to '%s'", - oldctx, newctx); +--- a/openbsd-compat/port-linux.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/openbsd-compat/port-linux.c (date 1703108053912) +@@ -207,7 +207,7 @@ + xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx, + newname, cx2 == NULL ? "" : cx2); + +- debug3_f("setting context from '%s' to '%s'", oldctx, newctx); ++ debug_f("setting context from '%s' to '%s'", oldctx, newctx); if (setcon(newctx) < 0) - do_log2(log_level, "%s: setcon %s from %s failed with %s", - __func__, newctx, oldctx, strerror(errno)); + do_log2_f(log_level, "setcon %s from %s failed with %s", + newctx, oldctx, strerror(errno)); diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h index cb51f99..8b7cda2 100644 --- a/openbsd-compat/port-linux.h diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index 1dca99c..01a061b 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -17,17 +17,6 @@ diff -up openssh-8.5p1/auth-krb5.c.coverity openssh-8.5p1/auth-krb5.c return oerrno; } /* make sure the KRB5CCNAME is set for non-standard location */ -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 */ -+ sshbuf_free(b); - return 0; - } - 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 @@ -45,14 +34,6 @@ diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c 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); -+ /* coverity[leaked_storage : FALSE] */ - return r; - } - @@ -1261,6 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, cons return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); @@ -149,23 +130,6 @@ diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c return (0); error: -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"); -- if (tmp1 > 0) -+ if (tmp1 >= 0) - close(tmp1); -- if (tmp2 > 0) -- close(tmp2); -+ /*DEAD CODE if (tmp2 >= 0) -+ close(tmp2);*/ - return 0; - } - close(tmp1); 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 @@ -219,23 +183,6 @@ diff -up openssh-8.5p1/readconf.c.coverity openssh-8.5p1/readconf.c goto out; } free(arg2); -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); -- waitpid(do_cmd_pid, NULL, 0); -+ (void) waitpid(do_cmd_pid, NULL, 0); - } - if (do_cmd_pid2 > 1) { - kill(do_cmd_pid2, signo ? signo : SIGTERM); -- waitpid(do_cmd_pid2, NULL, 0); -+ (void) waitpid(do_cmd_pid2, NULL, 0); - } - - if (signo) 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 @@ -263,18 +210,6 @@ diff -up openssh-8.7p1/serverloop.c.coverity openssh-8.7p1/serverloop.c if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != (int)tun) goto done; -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); -- waitpid(pid, NULL, 0); -+ (void) waitpid(pid, NULL, 0); - } - - _exit(1); 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 @@ -286,28 +221,6 @@ diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c return NULL; } /* validate also provider from URI */ -@@ -1220,8 +1220,8 @@ main(int ac, char **av) - sanitise_stdfd(); - - /* drop */ -- setegid(getgid()); -- setgid(getgid()); -+ (void) setegid(getgid()); -+ (void) setgid(getgid()); - - platform_disable_tracing(0); /* strict=no */ - -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; -+ /* coverity[leaked_handle: FALSE]*/ - muxclient(options.control_path); - /* muxclient() doesn't return on success. */ - fatal("Failed to connect to new control master"); 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 diff --git a/openssh-7.2p2-x11.patch b/openssh-7.2p2-x11.patch index 0a19ecb..b27d7c4 100644 --- a/openssh-7.2p2-x11.patch +++ b/openssh-7.2p2-x11.patch @@ -1,21 +1,23 @@ -diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c ---- openssh-7.2p2/channels.c.x11 2016-03-09 19:04:48.000000000 +0100 -+++ openssh-7.2p2/channels.c 2016-06-03 10:42:04.775164520 +0200 -@@ -3990,21 +3990,24 @@ x11_create_display_inet(int x11_display_ +diff --git a/channels.c b/channels.c +--- a/channels.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/channels.c (date 1703026069921) +@@ -5075,11 +5075,13 @@ } - + static int -connect_local_xsocket_path(const char *pathname) +connect_local_xsocket_path(const char *pathname, int len) { int sock; struct sockaddr_un addr; - -+ if (len <= 0) -+ return -1; + ++ if (len <= 0) ++ return -1; sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock == -1) + if (sock == -1) { error("socket: %.100s", strerror(errno)); +@@ -5087,11 +5089,12 @@ + } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; - strlcpy(addr.sun_path, pathname, sizeof addr.sun_path); @@ -29,8 +31,8 @@ diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c - error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); return -1; } - -@@ -4012,8 +4015,18 @@ static int + +@@ -5099,8 +5102,18 @@ connect_local_xsocket(u_int dnr) { char buf[1024]; diff --git a/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch index 4dc460a..347766d 100644 --- a/openssh-7.8p1-role-mls.patch +++ b/openssh-7.8p1-role-mls.patch @@ -23,7 +23,7 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c if ((style = strchr(user, ':')) != NULL) *style++ = 0; -@@ -296,8 +304,15 @@ input_userauth_request(int type, u_int32 +@@ -314,8 +314,15 @@ input_userauth_request(int type, u_int32 use_privsep ? " [net]" : ""); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; @@ -34,12 +34,12 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c + if (use_privsep) { mm_inform_authserv(service, style); +#ifdef WITH_SELINUX -+ mm_inform_authrole(role); ++ mm_inform_authrole(role); +#endif -+ } ++ } userauth_banner(ssh); - if (auth2_setup_methods_lists(authctxt) != 0) - ssh_packet_disconnect(ssh, + if ((r = kex_server_update_ext_info(ssh)) != 0) + fatal_fr(r, "kex_server_update_ext_info failed"); diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c --- openssh/auth2-gss.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/auth2-gss.c 2018-08-22 11:15:42.459799171 +0200 diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index 89bcd0d..3e5ccec 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -144,8 +144,8 @@ index 9351e042..d6446c0c 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,7 +1,7 @@ - /* $OpenBSD: auth2-gss.c,v 1.33 2021/12/19 22:12:07 djm Exp $ */ - + /* $OpenBSD: auth2-gss.c,v 1.34 2023/03/31 04:22:27 djm Exp $ */ + /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. + * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. @@ -1268,7 +1268,7 @@ index ce85f043..574c7609 100644 +#endif + /* prototype */ - static int kex_choose_conf(struct ssh *); + static int kex_choose_conf(struct ssh *, uint32_t seq); static int kex_input_newkeys(int, u_int32_t, struct ssh *); @@ -115,15 +120,28 @@ static const struct kexalg kexalgs[] = { #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ @@ -3400,7 +3400,7 @@ index 60de6087..db5c65bc 100644 .It HashKnownHosts .It Host .It HostbasedAcceptedAlgorithms -@@ -579,6 +585,8 @@ flag), +@@ -624,6 +624,8 @@ (supported message integrity codes), .Ar kex (key exchange algorithms), @@ -3408,7 +3408,7 @@ index 60de6087..db5c65bc 100644 +(GSSAPI key exchange algorithms), .Ar key (key types), - .Ar key-cert + .Ar key-ca-sign diff --git a/ssh.c b/ssh.c index 15aee569..110cf9c1 100644 --- a/ssh.c @@ -3444,7 +3444,7 @@ index 5e8ef548..1ff999b6 100644 +# GSSAPIKeyExchange no +# GSSAPITrustDNS no # BatchMode no - # CheckHostIP yes + # CheckHostIP no # AddressFamily any diff --git a/ssh_config.5 b/ssh_config.5 index 06a32d31..3f490697 100644 @@ -4028,3 +4028,47 @@ index 71a3fddc..37a43a67 100644 KEY_UNSPEC }; +diff --git a/packet.h b/packet.h +--- a/packet.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/packet.h (date 1703172586447) +@@ -124,6 +124,7 @@ + int ssh_packet_send2(struct ssh *); + + int ssh_packet_read(struct ssh *); ++int ssh_packet_read_expect(struct ssh *, u_int type); + int ssh_packet_read_poll(struct ssh *); + int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); + int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); +diff --git a/packet.c b/packet.c +--- a/packet.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/packet.c (date 1703172586447) +@@ -1425,6 +1416,29 @@ + return type; + } + ++/* ++ * Waits until a packet has been received, verifies that its type matches ++ * that given, and gives a fatal error and exits if there is a mismatch. ++ */ ++ ++int ++ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) ++{ ++ int r; ++ u_char type; ++ ++ if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) ++ return r; ++ if (type != expected_type) { ++ if ((r = sshpkt_disconnect(ssh, ++ "Protocol error: expected packet type %d, got %d", ++ expected_type, type)) != 0) ++ return r; ++ return SSH_ERR_PROTOCOL_ERROR; ++ } ++ return 0; ++} ++ + static int + ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + { diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index 551351c..1e7940d 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -1,7 +1,7 @@ -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( +diff -up openssh-9.6p1/configure.ac.pkcs11-uri openssh-9.6p1/configure.ac +--- openssh-9.6p1/configure.ac.pkcs11-uri 2024-01-12 14:25:25.228942213 +0100 ++++ openssh-9.6p1/configure.ac 2024-01-12 14:25:25.233942336 +0100 +@@ -2066,12 +2066,14 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) @@ -16,7 +16,7 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac fi ] ) -@@ -2019,6 +2021,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) +@@ -2095,6 +2097,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_FUNCS([dlopen]) AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) @@ -57,7 +57,7 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5624,6 +5660,7 @@ echo " BSD Auth support +@@ -5708,6 +5744,7 @@ echo " BSD Auth support echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" @@ -65,10 +65,10 @@ diff -up openssh-8.7p1/configure.ac.pkcs11-uri openssh-8.7p1/configure.ac echo " U2F/FIDO support: $enable_sk" echo "" -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 -@@ -105,7 +105,7 @@ +diff -up openssh-9.6p1/Makefile.in.pkcs11-uri openssh-9.6p1/Makefile.in +--- openssh-9.6p1/Makefile.in.pkcs11-uri 2024-01-12 14:25:25.204941622 +0100 ++++ openssh-9.6p1/Makefile.in 2024-01-12 14:25:25.233942336 +0100 +@@ -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 \ @@ -77,7 +77,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in 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 +@@ -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) @@ -86,15 +86,15 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in 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 +@@ -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 + 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 @@ -103,7 +103,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in $(MKDIR_P) `pwd`/regress/misc/sk-dummy [ -f `pwd`/regress/Makefile ] || \ ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile -@@ -685,6 +690,16 @@ +@@ -685,6 +690,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) @@ -120,7 +120,7 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in # 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 +@@ -720,7 +735,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) \ @@ -128,24 +128,12 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in + regress/unittests/utf8/test_utf8$(EXEEXT) \ + regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \ - tests: file-tests t-exec interop-tests unit + tests: file-tests t-exec interop-tests extra-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 - - trace "remove pkcs11 keys" -- echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 -+ ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 - r=$? - if [ $r -ne 0 ]; then - fail "ssh-add -e failed: exit code $r" -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 +diff -up openssh-9.6p1/regress/Makefile.pkcs11-uri openssh-9.6p1/regress/Makefile +--- openssh-9.6p1/regress/Makefile.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/regress/Makefile 2024-01-12 14:25:25.233942336 +0100 +@@ -134,7 +134,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 \ @@ -155,7 +143,7 @@ diff -up openssh-8.7p1/regress/Makefile.pkcs11-uri openssh-8.7p1/regress/Makefil 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: +@@ -273,8 +274,9 @@ unit: V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ @@ -167,9 +155,9 @@ diff -up openssh-8.7p1/regress/Makefile.pkcs11-uri openssh-8.7p1/regress/Makefil -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 +diff -up openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri openssh-9.6p1/regress/pkcs11.sh +--- openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri 2024-01-12 14:25:25.233942336 +0100 ++++ openssh-9.6p1/regress/pkcs11.sh 2024-01-12 14:25:25.233942336 +0100 @@ -0,0 +1,349 @@ +# +# Copyright (c) 2017 Red Hat @@ -520,20 +508,20 @@ diff -up openssh-8.7p1/regress/pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/pkcs11 + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi -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 @@ +diff -up openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri openssh-9.6p1/regress/unittests/Makefile +--- openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/regress/unittests/Makefile 2024-01-12 14:25:25.233942336 +0100 +@@ -1,6 +1,6 @@ + # $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $ - 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 +diff -up openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-9.6p1/regress/unittests/pkcs11/tests.c +--- openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri 2024-01-12 14:25:25.233942336 +0100 ++++ openssh-9.6p1/regress/unittests/pkcs11/tests.c 2024-01-12 14:25:25.233942336 +0100 @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2017 Red Hat @@ -881,10 +869,10 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 + test_parse_invalid(); + test_generate_valid(); +} -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 @@ +diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c +--- openssh-9.6p1/ssh-add.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-add.c 2024-01-12 14:25:25.233942336 +0100 +@@ -69,6 +69,7 @@ #include "ssh-sk.h" #include "sk-api.h" #include "hostfile.h" @@ -892,12 +880,16 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c /* argv0 */ extern char *__progname; -@@ -229,6 +230,34 @@ delete_all(int agent_fd, int qflag) +@@ -240,6 +241,38 @@ delete_all(int agent_fd, int qflag) return ret; } +#ifdef ENABLE_PKCS11 -+static int update_card(int, int, const char *, int, struct dest_constraint **, size_t, char *); ++static int ++update_card(int agent_fd, int add, const char *id, int qflag, ++ int key_only, int cert_only, ++ struct dest_constraint **dest_constraints, size_t ndest_constraints, ++ struct sshkey **certs, size_t ncerts, char *pin); + +int +update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag, @@ -919,32 +911,35 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c + } + pkcs11_uri_cleanup(uri); + -+ return update_card(agent_fd, adding, pkcs11_uri, qflag, -+ dest_constraints, ndest_constraints, pin); ++ return update_card(agent_fd, adding, pkcs11_uri, qflag, 1, 0, ++ dest_constraints, ndest_constraints, NULL, 0, pin); +} +#endif + 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 +472,11 @@ add_file(int agent_fd, const char *filen - - static int + add_file(int agent_fd, const char *filename, int key_only, int cert_only, + int qflag, const char *skprovider, +@@ -460,15 +489,14 @@ static int update_card(int agent_fd, int add, const char *id, int qflag, -- struct dest_constraint **dest_constraints, size_t ndest_constraints) -+ struct dest_constraint **dest_constraints, size_t ndest_constraints, char *pin) + int key_only, int cert_only, + struct dest_constraint **dest_constraints, size_t ndest_constraints, +- struct sshkey **certs, size_t ncerts) ++ struct sshkey **certs, size_t ncerts, char *pin) { - char *pin = NULL; int r, ret = -1; + if (key_only) + ncerts = 0; + - if (add) { + if (add && pin == NULL) { if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; -@@ -630,6 +656,14 @@ static int - const char *skprovider, struct dest_constraint **dest_constraints, - size_t ndest_constraints) +@@ -656,6 +684,14 @@ do_file(int agent_fd, int deleting, int + char *file, int qflag, const char *skprovider, + struct dest_constraint **dest_constraints, size_t ndest_constraints) { +#ifdef ENABLE_PKCS11 + if (strlen(file) >= strlen(PKCS11_URI_SCHEME) && @@ -955,21 +950,21 @@ diff -up openssh-8.7p1/ssh-add.c.pkcs11-uri openssh-8.7p1/ssh-add.c + } +#endif if (deleting) { - if (delete_file(agent_fd, file, key_only, qflag) == -1) - return -1; -@@ -813,7 +846,7 @@ main(int argc, char **argv) - } - if (pkcs11provider != NULL) { + if (delete_file(agent_fd, file, key_only, + cert_only, qflag) == -1) +@@ -999,7 +1035,7 @@ main(int argc, char **argv) if (update_card(agent_fd, !deleting, pkcs11provider, -- qflag, dest_constraints, ndest_constraints) == -1) -+ qflag, dest_constraints, ndest_constraints, NULL) == -1) + qflag, key_only, cert_only, + dest_constraints, ndest_constraints, +- certs, ncerts) == -1) ++ certs, ncerts, NULL) == -1) ret = 1; goto done; } -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) +diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c +--- openssh-9.6p1/ssh-agent.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-agent.c 2024-01-12 14:25:25.234942360 +0100 +@@ -1549,10 +1549,72 @@ add_p11_identity(struct sshkey *key, cha } #ifdef ENABLE_PKCS11 @@ -1043,25 +1038,23 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds = 0; -@@ -869,33 +931,28 @@ process_add_smartcard_key(SocketEntry *e - error_f("failed to parse constraints"); +@@ -1581,25 +1643,18 @@ process_add_smartcard_key(SocketEntry *e + "providers is disabled", provider); goto send; } - if (realpath(provider, canonical_provider) == NULL) { - verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", - provider, strerror(errno)); -- goto send; -- } -- if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { -- verbose("refusing PKCS#11 add of \"%.100s\": " -- "provider not allowed", canonical_provider); -+ + sane_uri = sanitize_pkcs11_provider(provider); + if (sane_uri == NULL) goto send; - } +- if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { +- verbose("refusing PKCS#11 add of \"%.100s\": " +- "provider not allowed", canonical_provider); +- goto send; +- } - debug_f("add %.100s", canonical_provider); -+ if (lifetime && !death) death = monotime() + lifetime; @@ -1069,31 +1062,38 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c + debug_f("add %.100s", sane_uri); + count = pkcs11_add_provider(sane_uri, pin, &keys, &comments); for (i = 0; i < count; i++) { - k = keys[i]; - if (lookup_identity(k) == NULL) { - id = xcalloc(1, sizeof(Identity)); - id->key = k; - keys[i] = NULL; /* transferred */ -- id->provider = xstrdup(canonical_provider); -+ id->provider = xstrdup(sane_uri); - if (*comments[i] != '\0') { - id->comment = comments[i]; - comments[i] = NULL; /* transferred */ - } else { -- id->comment = xstrdup(canonical_provider); -+ id->comment = xstrdup(sane_uri); - } - id->death = death; - id->confirm = confirm; -@@ -910,6 +967,7 @@ process_add_smartcard_key(SocketEntry *e + if (comments[i] == NULL || comments[i][0] == '\0') { + free(comments[i]); +- comments[i] = xstrdup(canonical_provider); ++ comments[i] = xstrdup(sane_uri); + } + for (j = 0; j < ncerts; j++) { + if (!sshkey_is_cert(certs[j])) +@@ -1609,13 +1664,13 @@ process_add_smartcard_key(SocketEntry *e + if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) + continue; + add_p11_identity(k, xstrdup(comments[i]), +- canonical_provider, death, confirm, ++ sane_uri, death, confirm, + dest_constraints, ndest_constraints); + success = 1; + } + if (!cert_only && lookup_identity(keys[i]) == NULL) { + add_p11_identity(keys[i], comments[i], +- canonical_provider, death, confirm, ++ sane_uri, death, confirm, + dest_constraints, ndest_constraints); + keys[i] = NULL; /* transferred */ + comments[i] = NULL; /* transferred */ +@@ -1628,6 +1683,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); -@@ -918,7 +976,7 @@ send: + free_dest_constraints(dest_constraints, ndest_constraints); +@@ -1640,7 +1696,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { @@ -1102,7 +1102,7 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c int r, success = 0; Identity *id, *nxt; -@@ -930,30 +988,29 @@ process_remove_smartcard_key(SocketEntry +@@ -1652,30 +1708,29 @@ process_remove_smartcard_key(SocketEntry } free(pin); @@ -1139,10 +1139,10 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c send_status(e, success); } #endif /* ENABLE_PKCS11 */ -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 +diff -up openssh-9.6p1/ssh_config.5.pkcs11-uri openssh-9.6p1/ssh_config.5 +--- openssh-9.6p1/ssh_config.5.pkcs11-uri 2024-01-12 14:25:25.208941721 +0100 ++++ openssh-9.6p1/ssh_config.5 2024-01-12 14:25:25.234942360 +0100 +@@ -1216,6 +1216,21 @@ may also be used in conjunction with .Cm CertificateFile in order to provide any certificate also needed for authentication with the identity. @@ -1164,10 +1164,10 @@ diff -up openssh-8.7p1/ssh_config.5.pkcs11-uri openssh-8.7p1/ssh_config.5 .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) +diff -up openssh-9.6p1/ssh.c.pkcs11-uri openssh-9.6p1/ssh.c +--- openssh-9.6p1/ssh.c.pkcs11-uri 2024-01-12 14:25:25.208941721 +0100 ++++ openssh-9.6p1/ssh.c 2024-01-12 14:25:25.234942360 +0100 +@@ -882,6 +882,14 @@ main(int ac, char **av) options.gss_deleg_creds = 1; break; case 'i': @@ -1182,7 +1182,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c 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) +@@ -1784,6 +1792,7 @@ main(int ac, char **av) #ifdef ENABLE_PKCS11 (void)pkcs11_del_provider(options.pkcs11_provider); #endif @@ -1190,7 +1190,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c skip_connect: exit_status = ssh_session2(ssh, cinfo); -@@ -2197,6 +2206,45 @@ ssh_session2(struct ssh *ssh, const stru +@@ -2307,6 +2316,45 @@ ssh_session2(struct ssh *ssh, const stru options.escape_char : SSH_ESCAPECHAR_NONE, id); } @@ -1236,7 +1236,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c /* 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 +@@ -2321,11 +2369,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]; @@ -1248,7 +1248,7 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); -@@ -2228,33 +2271,46 @@ load_public_identity_files(const struct +@@ -2338,33 +2381,46 @@ load_public_identity_files(const struct sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 @@ -1314,10 +1314,10 @@ diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c 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) +diff -up openssh-9.6p1/ssh-keygen.c.pkcs11-uri openssh-9.6p1/ssh-keygen.c +--- openssh-9.6p1/ssh-keygen.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-keygen.c 2024-01-12 14:25:25.234942360 +0100 +@@ -862,8 +862,11 @@ do_download(struct passwd *pw) free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ @@ -1331,19 +1331,19 @@ diff -up openssh-8.7p1/ssh-keygen.c.pkcs11-uri openssh-8.7p1/ssh-keygen.c } 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; +diff -up openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-client.c +--- openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11-client.c 2024-01-12 14:25:25.234942360 +0100 +@@ -592,6 +592,8 @@ pkcs11_add_provider(char *name, char *pi struct sshbuf *msg; + struct helper *helper; + debug_f("called, name = %s", name); + - if (fd < 0 && pkcs11_start_helper() < 0) - return (-1); - -@@ -342,6 +344,7 @@ pkcs11_add_provider(char *name, char *pi + if ((helper = helper_by_provider(name)) == NULL && + (helper = pkcs11_start_helper(name)) == NULL) + return -1; +@@ -612,6 +614,7 @@ pkcs11_add_provider(char *name, char *pi *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); if (labelsp) *labelsp = xcalloc(nkeys, sizeof(char *)); @@ -1351,9 +1351,9 @@ diff -up openssh-8.7p1/ssh-pkcs11-client.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-c 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 +diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c +--- openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11.c 2024-01-12 14:28:09.170975480 +0100 @@ -55,8 +55,8 @@ struct pkcs11_slotinfo { int logged_in; }; @@ -1537,10 +1537,10 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c struct pkcs11_provider *p; + int rv = -1; + char *provider_uri = pkcs11_uri_get(uri); ++ ++ debug3_f("called with provider %s", provider_uri); - if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { -+ debug3_f("called with provider %s", provider_uri); -+ + if ((p = pkcs11_provider_lookup(provider_uri)) != NULL) { TAILQ_REMOVE(&pkcs11_providers, p, next); pkcs11_provider_finalize(p); @@ -1611,7 +1611,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c /* 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, +@@ -208,6 +349,7 @@ pkcs11_k11_free(void *parent, void *ptr, if (k11->provider) pkcs11_provider_unref(k11->provider); free(k11->keyid); @@ -1619,7 +1619,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(k11); } -@@ -222,8 +363,8 @@ pkcs11_find(struct pkcs11_provider *p, C +@@ -222,8 +364,8 @@ pkcs11_find(struct pkcs11_provider *p, C CK_RV rv; int ret = -1; @@ -1630,7 +1630,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); return (-1); -@@ -260,14 +403,14 @@ pkcs11_login_slot(struct pkcs11_provider +@@ -260,14 +402,14 @@ pkcs11_login_slot(struct pkcs11_provider if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) verbose("Deferring PIN entry to reader keypad."); else { @@ -1648,7 +1648,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c (pin != NULL) ? strlen(pin) : 0); if (pin != NULL) freezero(pin, strlen(pin)); -@@ -297,13 +438,14 @@ pkcs11_login_slot(struct pkcs11_provider +@@ -297,13 +439,14 @@ pkcs11_login_slot(struct pkcs11_provider static int pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) { @@ -1665,7 +1665,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c } -@@ -319,13 +461,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs +@@ -319,13 +462,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs *val = 0; @@ -1683,7 +1683,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c attr.type = type; attr.pValue = &flag; -@@ -356,13 +499,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C +@@ -356,13 +500,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C int always_auth = 0; int did_login = 0; @@ -1701,7 +1701,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c 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, con +@@ -439,8 +584,8 @@ pkcs11_rsa_private_encrypt(int flen, con return (-1); } @@ -1712,7 +1712,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c tlen = RSA_size(rsa); /* XXX handle CKR_BUFFER_TOO_SMALL */ -@@ -484,7 +628,7 @@ pkcs11_rsa_start_wrapper(void) +@@ -484,7 +629,7 @@ pkcs11_rsa_start_wrapper(void) /* redirect private key operations for rsa key to pkcs11 token */ static int pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1721,7 +1721,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c { struct pkcs11_key *k11; -@@ -502,6 +646,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * +@@ -502,6 +647,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } @@ -1734,7 +1734,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c 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, +@@ -532,8 +683,8 @@ ecdsa_do_sign(const unsigned char *dgst, return (NULL); } @@ -1745,7 +1745,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c siglen = ECDSA_size(ec); sig = xmalloc(siglen); -@@ -598,7 +748,7 @@ pkcs11_ecdsa_start_wrapper(void) +@@ -598,7 +749,7 @@ pkcs11_ecdsa_start_wrapper(void) static int pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1754,10 +1754,10 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c { struct pkcs11_key *k11; -@@ -614,6 +764,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider +@@ -615,6 +766,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); @@ -1767,28 +1767,17 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c EC_KEY_set_method(ec, ec_key_method); EC_KEY_set_ex_data(ec, ec_key_idx, k11); -@@ -622,7 +779,8 @@ +@@ -622,7 +779,8 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider } #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ -/* remove trailing spaces */ +/* remove trailing spaces. Note, that this does NOT guarantee the buffer + * will be null terminated if there are no trailing spaces! */ - static void + static char * rmspace(u_char *buf, size_t len) { -@@ -630,8 +788,8 @@ - - if (!len) - return; -- for (i = len - 1; i > 0; i--) -- if (i == len - 1 || buf[i] == ' ') -+ for (i = len - 1; i > 0; i--) -+ if (buf[i] == ' ') - buf[i] = '\0'; - else - break; -@@ -650,8 +806,8 @@ pkcs11_open_session(struct pkcs11_provid +@@ -654,8 +812,8 @@ pkcs11_open_session(struct pkcs11_provid CK_SESSION_HANDLE session; int login_required, ret; @@ -1799,7 +1788,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c login_required = si->token.flags & CKF_LOGIN_REQUIRED; -@@ -661,9 +817,9 @@ pkcs11_open_session(struct pkcs11_provid +@@ -665,9 +823,9 @@ pkcs11_open_session(struct pkcs11_provid error("pin required"); return (-SSH_PKCS11_ERR_PIN_REQUIRED); } @@ -1811,7 +1800,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c return (-1); } if (login_required && pin != NULL && strlen(pin) != 0) { -@@ -699,7 +855,8 @@ static struct sshkey * +@@ -703,7 +861,8 @@ static struct sshkey * pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1821,7 +1810,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -713,14 +870,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -717,14 +876,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1842,7 +1831,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -731,19 +889,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -735,19 +895,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1866,7 +1855,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -755,8 +913,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -759,8 +919,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1877,7 +1866,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (group == NULL) { ossl_error("d2i_ECPKParameters failed"); goto fail; -@@ -767,13 +925,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -771,13 +931,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1894,7 +1883,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (octet == NULL) { ossl_error("d2i_ASN1_OCTET_STRING failed"); goto fail; -@@ -790,7 +948,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -794,7 +954,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ goto fail; } @@ -1903,7 +1892,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -806,7 +964,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ +@@ -810,7 +970,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ ec = NULL; /* now owned by key */ fail: @@ -1912,7 +1901,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(key_attr[i].pValue); if (ec) EC_KEY_free(ec); -@@ -823,7 +981,8 @@ static struct sshkey * +@@ -827,7 +987,8 @@ static struct sshkey * pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1922,7 +1911,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -834,14 +993,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -838,14 +999,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1943,7 +1932,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -852,19 +1012,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -856,19 +1018,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1967,7 +1956,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -876,8 +1036,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -880,8 +1042,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr goto fail; } @@ -1978,7 +1967,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rsa_n == NULL || rsa_e == NULL) { error("BN_bin2bn failed"); goto fail; -@@ -886,7 +1046,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -890,7 +1052,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr fatal_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ @@ -1987,7 +1976,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto fail; key = sshkey_new(KEY_UNSPEC); -@@ -901,7 +1061,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr +@@ -905,7 +1067,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr rsa = NULL; /* now owned by key */ fail: @@ -1996,7 +1985,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(key_attr[i].pValue); RSA_free(rsa); -@@ -912,7 +1072,8 @@ static int +@@ -916,7 +1078,8 @@ static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { @@ -2006,7 +1995,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -936,14 +1097,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -940,14 +1103,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p memset(&cert_attr, 0, sizeof(cert_attr)); cert_attr[0].type = CKA_ID; @@ -2027,7 +2016,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return -1; -@@ -955,18 +1117,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -959,18 +1123,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p * XXX assumes CKA_ID is always first. */ if (cert_attr[1].ulValueLen == 0 || @@ -2050,7 +2039,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto out; -@@ -980,8 +1143,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -984,8 +1149,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p subject = xstrdup("invalid subject"); X509_NAME_free(x509_name); @@ -2061,7 +2050,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c error("d2i_x509 failed"); goto out; } -@@ -1001,7 +1164,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1005,7 +1170,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2070,7 +2059,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1031,7 +1194,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1035,7 +1200,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } @@ -2079,7 +2068,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto out; key = sshkey_new(KEY_UNSPEC); -@@ -1051,7 +1214,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p +@@ -1055,7 +1220,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p goto out; } out: @@ -2088,7 +2077,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(cert_attr[i].pValue); X509_free(x509); RSA_free(rsa); -@@ -1102,11 +1265,12 @@ note_key(struct pkcs11_provider *p, CK_U +@@ -1106,11 +1271,12 @@ note_key(struct pkcs11_provider *p, CK_U */ static int pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2103,7 +2092,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1123,10 +1287,23 @@ pkcs11_fetch_certs(struct pkcs11_provide +@@ -1127,10 +1293,23 @@ pkcs11_fetch_certs(struct pkcs11_provide key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2121,16 +2110,16 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + key_attr[nattr].ulValueLen = strlen(uri->object); + nattr++; + } -+ -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - 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, nattr); if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1207,11 +1384,12 @@ fail: +@@ -1211,11 +1390,12 @@ fail: */ static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2145,7 +2134,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1227,10 +1405,23 @@ pkcs11_fetch_keys(struct pkcs11_provider +@@ -1231,10 +1411,23 @@ pkcs11_fetch_keys(struct pkcs11_provider key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2163,16 +2152,16 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + 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; -@@ -1499,16 +1690,10 @@ pkcs11_ecdsa_generate_private_key(struct +@@ -1503,16 +1696,10 @@ pkcs11_ecdsa_generate_private_key(struct } #endif /* WITH_PKCS11_KEYGEN */ @@ -2191,7 +2180,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c int ret = -1; struct pkcs11_provider *p = NULL; void *handle = NULL; -@@ -1517,164 +1702,305 @@ +@@ -1521,162 +1708,309 @@ pkcs11_register_provider(char *provider_ CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; @@ -2199,28 +2188,35 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + struct pkcs11_module *m = NULL; - if (providerp == NULL) +- goto fail; +- *providerp = NULL; +- +- if (keyp != NULL) +- *keyp = NULL; +- if (labelsp != NULL) +- *labelsp = NULL; + /* if no provider specified, fallback to p11-kit */ + if (uri->module_path == NULL) { +#ifdef PKCS11_DEFAULT_PROVIDER + provider_module = strdup(PKCS11_DEFAULT_PROVIDER); +#else + error_f("No module path provided"); - goto fail; -- *providerp = NULL; ++ goto fail; +#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); ++ if (lib_contains_symbol(provider_module, "C_GetFunctionList") != 0) { ++ error("provider %s is not a PKCS11 library", provider_module); + goto fail; + } +- if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) { +- error("provider %s is not a PKCS11 library", provider_id); - goto fail; + if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL + && m->valid) { @@ -2247,14 +2243,11 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + 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 = xcalloc(1, sizeof(*p)); - p->name = xstrdup(provider_id); - p->handle = handle; -+ + p->module->handle = handle; /* setup the pkcs11 callbacks */ if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { @@ -2279,15 +2272,13 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + provider_module, rv); goto fail; } -- rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID)); -- rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription)); -- debug("provider %s: manufacturerID <%s> cryptokiVersion %d.%d" -- " libraryDescription <%s> libraryVersion %d.%d", +- debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" +- " libraryDescription <%.*s> libraryVersion %d.%d", - provider_id, -- p->info.manufacturerID, +- RMSPACE(p->info.manufacturerID), - p->info.cryptokiVersion.major, - p->info.cryptokiVersion.minor, -- p->info.libraryDescription, +- RMSPACE(p->info.libraryDescription), - p->info.libraryVersion.major, - p->info.libraryVersion.minor); - if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { @@ -2331,12 +2322,12 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c goto fail; } - p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); ++ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); p->valid = 1; - nkeys = 0; - for (i = 0; i < p->nslots; i++) { - token = &p->slotinfo[i].token; - if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) -+ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); + m->valid = 1; + for (i = 0; i < m->nslots; i++) { + token = &m->slotinfo[i].token; @@ -2353,23 +2344,25 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + token->flags = 0; continue; } - rmspace(token->label, sizeof(token->label)); - rmspace(token->manufacturerID, sizeof(token->manufacturerID)); - rmspace(token->model, sizeof(token->model)); - rmspace(token->serialNumber, sizeof(token->serialNumber)); -- debug("provider %s slot %lu: label <%s> manufacturerID <%s> " -- "model <%s> serial <%s> flags 0x%lx", + debug("provider %s slot %lu: label <%.*s> " + "manufacturerID <%.*s> model <%.*s> serial <%.*s> " + "flags 0x%lx", - provider_id, (unsigned long)i, ++ provider_module, (unsigned long)i, + RMSPACE(token->label), RMSPACE(token->manufacturerID), + RMSPACE(token->model), RMSPACE(token->serialNumber), + token->flags); + } + m->module_path = provider_module; + provider_module = NULL; + -+ /* insert unconditionally -- remove if there will be no keys later */ ++ /* now owned by caller */ ++ *providerp = p; ++ + TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); + p->refcount++; /* add to provider list */ -+ *providerp = p; -+ return 0; + ++ return 0; +fail: + if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) + error("C_Finalize for provider %s failed: %lu", @@ -2385,7 +2378,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + } + if (handle) + dlclose(handle); -+ return ret; ++ return (ret); +} + +/* @@ -2451,12 +2444,12 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + debug("provider %s slot %lu: label <%.32s> manufacturerID <%.32s> " + "model <%.16s> serial <%.16s> flags 0x%lx", + provider_uri, (unsigned long)i, - token->label, token->manufacturerID, token->model, - token->serialNumber, token->flags); ++ token->label, token->manufacturerID, token->model, ++ token->serialNumber, token->flags); /* - * open session, login with pin and retrieve public - * keys (if keyp is provided) -+ * open session if not yet openend, login with pin and ++ * open session if not yet opened, login with pin and + * retrieve public keys (if keyp is provided) */ - if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || @@ -2517,8 +2510,8 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c - free(p->slotlist); - free(p->slotinfo); - free(p); -+ TAILQ_REMOVE(&pkcs11_providers, p, next); -+ pkcs11_provider_unref(p); ++ TAILQ_REMOVE(&pkcs11_providers, p, next); ++ pkcs11_provider_unref(p); } - if (handle) - dlclose(handle); @@ -2576,7 +2569,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c /* no keys found or some other error, de-register provider */ if (nkeys <= 0 && p != NULL) { -@@ -1684,7 +2012,37 @@ pkcs11_add_provider(char *provider_id, c +@@ -1685,7 +2019,37 @@ pkcs11_add_provider(char *provider_id, c pkcs11_provider_unref(p); } if (nkeys == 0) @@ -2615,9 +2608,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c 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 +diff -up openssh-9.6p1/ssh-pkcs11.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11.h +--- openssh-9.6p1/ssh-pkcs11.h.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 ++++ openssh-9.6p1/ssh-pkcs11.h 2024-01-12 14:25:25.235942385 +0100 @@ -22,10 +22,14 @@ #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 @@ -2633,9 +2626,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11.h #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 +diff -up openssh-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri.c +--- openssh-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri 2024-01-12 14:25:25.235942385 +0100 ++++ openssh-9.6p1/ssh-pkcs11-uri.c 2024-01-12 14:25:25.235942385 +0100 @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2017 Red Hat @@ -3074,9 +3067,9 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. +} + +#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 +diff -up openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri.h +--- openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri 2024-01-12 14:25:25.235942385 +0100 ++++ openssh-9.6p1/ssh-pkcs11-uri.h 2024-01-12 14:25:25.235942385 +0100 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Red Hat diff --git a/openssh-8.7p1-minrsabits.patch b/openssh-8.7p1-minrsabits.patch index 2ed59a3..479b55d 100644 --- a/openssh-8.7p1-minrsabits.patch +++ b/openssh-8.7p1-minrsabits.patch @@ -1,23 +1,21 @@ diff --git a/readconf.c b/readconf.c -index 7f26c680..42be690b 100644 ---- a/readconf.c -+++ b/readconf.c -@@ -320,6 +320,7 @@ static struct { +--- a/readconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/readconf.c (date 1703169891147) +@@ -326,6 +326,7 @@ { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, - { "requiredrsasize", oRequiredRSASize }, + { "requiredrsasize", oRequiredRSASize }, + { "rsaminsize", oRequiredRSASize }, /* alias */ { "enableescapecommandline", oEnableEscapeCommandline }, - - { NULL, oBadOption } + { "obscurekeystroketiming", oObscureKeystrokeTiming }, + { "channeltimeout", oChannelTimeout }, diff --git a/servconf.c b/servconf.c -index 29df0463..423772b1 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -676,6 +680,7 @@ static struct { +--- a/servconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/servconf.c (date 1703169891148) +@@ -691,6 +691,7 @@ { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, - { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, + { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, + { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */ { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, diff --git a/openssh-8.7p1-recursive-scp.patch b/openssh-8.7p1-recursive-scp.patch index f0d9b0f..17c340e 100644 --- a/openssh-8.7p1-recursive-scp.patch +++ b/openssh-8.7p1-recursive-scp.patch @@ -1,28 +1,28 @@ -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 - +diff --git a/scp.c b/scp.c +--- a/scp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/scp.c (date 1703111453316) +@@ -1372,7 +1372,7 @@ + if (src_is_dir && iamrecursive) { - if (upload_dir(conn, src, abs_dst, pflag, + if (sftp_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 - + error("failed to upload directory %s to %s", src, targ); + errs = 1; + } +diff --git a/sftp-client.c b/sftp-client.c +--- a/sftp-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp-client.c (date 1703169614263) +@@ -1003,7 +1003,7 @@ + /* 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) +-sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) ++sftp_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 +@@ -1049,11 +1049,43 @@ if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); @@ -33,7 +33,7 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c - 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) { ++ if ((r = sftp_mkdir(conn, path, &a, 0)) != 0) { + sshbuf_free(msg); + return NULL; + } @@ -71,111 +71,112 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c } 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 +@@ -1078,9 +1110,9 @@ } - + char * --do_realpath(struct sftp_conn *conn, const char *path) -+do_realpath(struct sftp_conn *conn, const char *path, int create_dir) +-sftp_realpath(struct sftp_conn *conn, const char *path) ++sftp_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); +- return sftp_realpath_expand(conn, path, 0); ++ return sftp_realpath_expand(conn, path, 0, create_dir); } - + int -@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c +@@ -1094,9 +1126,9 @@ { - if (!can_expand_path(conn)) { + if (!sftp_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 sftp_realpath_expand(conn, path, 0); ++ return sftp_realpath_expand(conn, path, 0, 0); } -- return do_realpath_expand(conn, path, 1); -+ return do_realpath_expand(conn, path, 1, 0); +- return sftp_realpath_expand(conn, path, 1); ++ return sftp_realpath_expand(conn, path, 1, 0); } - + int -@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con +@@ -2016,7 +2048,7 @@ 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 + +- if ((src_canon = sftp_realpath(conn, src)) == NULL) { ++ if ((src_canon = sftp_realpath(conn, src, 0)) == NULL) { + error("download \"%s\": path canonicalization failed", src); + return -1; + } +@@ -2365,12 +2397,12 @@ int - upload_dir(struct sftp_conn *conn, const char *src, const char *dst, + sftp_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 + +- if ((dst_canon = sftp_realpath(conn, dst)) == NULL) { ++ if ((dst_canon = sftp_realpath(conn, dst, create_dir)) == NULL) { + error("upload \"%s\": path canonicalization failed", dst); + return -1; + } +@@ -2825,7 +2857,7 @@ 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); - + +- if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) { ++ if ((from_path_canon = sftp_realpath(from, from_path, 0)) == NULL) { + error("crossload \"%s\": path canonicalization failed", + from_path); + return -1; +diff --git a/sftp-client.h b/sftp-client.h +--- a/sftp-client.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp-client.h (date 1703111691284) +@@ -111,7 +111,7 @@ + int sftp_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); - +-char *sftp_realpath(struct sftp_conn *, const char *); ++char *sftp_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 + char *sftp_expand_path(struct sftp_conn *, const char *); +@@ -163,7 +163,7 @@ * times if 'pflag' is set */ - int upload_dir(struct sftp_conn *, const char *, const char *, + int sftp_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, + +diff --git a/sftp.c b/sftp.c +--- a/sftp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/sftp.c (date 1703168795365) +@@ -807,7 +807,7 @@ + (rflag || global_rflag)) { + if (sftp_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 (sftp_upload(conn, g.gl_pathv[i], abs_dst, +@@ -1642,7 +1642,7 @@ 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) { + path1 = sftp_make_absolute(path1, *pwd); +- if ((tmp = sftp_realpath(conn, path1)) == NULL) { ++ if ((tmp = sftp_realpath(conn, path1, 0)) == NULL) { err = 1; break; } -@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn, +@@ -2247,7 +2247,7 @@ } #endif /* USE_LIBEDIT */ - -- remote_path = do_realpath(conn, "."); -+ remote_path = do_realpath(conn, ".", 0); - if (remote_path == NULL) + +- if ((remote_path = sftp_realpath(conn, ".")) == NULL) ++ if ((remote_path = sftp_realpath(conn, ".", 0)) == NULL) fatal("Need cwd"); startdir = xstrdup(remote_path); + diff --git a/openssh-9.3p1-merged-openssl-evp.patch b/openssh-9.3p1-merged-openssl-evp.patch index 95d86c3..6a30485 100644 --- a/openssh-9.3p1-merged-openssl-evp.patch +++ b/openssh-9.3p1-merged-openssl-evp.patch @@ -659,15 +659,15 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x # ifdef OPENSSL_HAS_ECC # include # include -@@ -268,6 +271,10 @@ +@@ -266,6 +266,10 @@ const char *sshkey_ssh_name_plain(const struct sshkey *); - int sshkey_names_valid2(const char *, int); + int sshkey_names_valid2(const char *, int, 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 @@ @@ -695,11 +695,11 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x #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 @@ - +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +--- a/ssh-pkcs11.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11.c (date 1703110934679) +@@ -620,8 +620,24 @@ + return (0); } + @@ -711,7 +711,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + return 0; +} #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - + +int +is_rsa_pkcs11(RSA *rsa) +{ @@ -722,14 +722,14 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + /* remove trailing spaces. Note, that this does NOT guarantee the buffer * will be null terminated if there are no trailing spaces! */ - static void -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; + static char * +diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c +--- a/ssh-pkcs11-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11-client.c (date 1703110830967) +@@ -402,8 +402,36 @@ + if (helper->nrsa == 0 && helper->nec == 0) + helper_terminate(helper); + } + +int +is_ecdsa_pkcs11(EC_KEY *ecdsa) @@ -744,8 +744,8 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + return 1; + return 0; +} - #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - + #endif /* defined(OPENSSL_HAS_ECC) && defined(HAVE_EC_KEY_METHOD_NEW) */ + +int +is_rsa_pkcs11(RSA *rsa) +{ @@ -762,14 +762,15 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + /* 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 - + wrap_key(struct helper *helper, struct sshkey *k) +diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h +--- a/ssh-pkcs11.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) ++++ b/ssh-pkcs11.h (date 1703111023334) +@@ -38,6 +38,12 @@ + /* Only available in ssh-pkcs11-client.c so far */ + int pkcs11_make_cert(const struct sshkey *, + const struct sshkey *, struct sshkey **); ++ +#ifdef HAVE_EC_KEY_METHOD_NEW +int is_ecdsa_pkcs11(EC_KEY *ecdsa); +#endif diff --git a/openssh.spec b/openssh.spec index 3076ac0..77e5775 100644 --- a/openssh.spec +++ b/openssh.spec @@ -46,15 +46,15 @@ %{?static_openssl:%global static_libcrypto 1} # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%global openssh_ver 9.3p1 -%global openssh_rel 13 +%global openssh_ver 9.6p1 +%global openssh_rel 1 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 9 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.1 +Release: %{openssh_rel}%{?dist} URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -228,9 +228,6 @@ Patch1006: openssh-8.7p1-negotiate-supported-algs.patch Patch1012: openssh-9.0p1-evp-fips-dh.patch Patch1013: openssh-9.0p1-evp-fips-ecdh.patch Patch1014: openssh-8.7p1-nohostsha1proof.patch -Patch1015: openssh-9.3p1-upstream-cve-2023-38408.patch -# upstream b7afd8a4ecaca8afd3179b55e9db79c0ff210237 -Patch1016: openssh-9.3p1-openssl-compat.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -306,7 +303,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.1 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist} License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -433,8 +430,6 @@ popd %patch -P 1012 -p1 -b .evp-fips-dh %patch -P 1013 -p1 -b .evp-fips-ecdh %patch -P 1014 -p1 -b .nosha1hostproof -%patch -P 1015 -p1 -b .cve-2023-38408 -%patch -P 1016 -p1 -b .ossl-version %patch -P 100 -p1 -b .coverity @@ -744,6 +739,11 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Tue Dec 26 2023 Daniel Milnes - 9.6p1-1 +- Update to OpenSSH 9.6 + Original patches from https://src.fedoraproject.org/rpms/openssh/pull-request/63 + Tuned by Dmitry Belyavskiy for GSS and PKCS#11 URI processing + * Fri Dec 22 2023 Florian Weimer - 9.3p1-13.1 - Fix type errors in downstream gssapi-keyex patch diff --git a/sources b/sources index 585760a..62f22c0 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (openssh-9.3p1.tar.gz) = 087ff6fe5f6caab4c6c3001d906399e02beffad7277280f11187420c2939fd4befdcb14643862a657ce4cad2f115b82a0a1a2c99df6ee54dcd76b53647637c19 -SHA512 (openssh-9.3p1.tar.gz.asc) = 6222378eb24a445c6c1db255392b405f5369b1af0e92f558d4ba05b0d83ab0d084cb8f4b91d7ae8636f333d970638a6635e2bc7af885135dd34992d87f2ef1f4 +SHA512 (openssh-9.6p1.tar.gz) = 0ebf81e39914c3a90d7777a001ec7376a94b37e6024baf3e972c58f0982b7ddef942315f5e01d56c00ff95603b4a20ee561ab918ecc55511df007ac138160509 +SHA512 (openssh-9.6p1.tar.gz.asc) = aec5a5bd6ce480a8e5b5879dc55f8186aec90fe61f085aa92ad7d07f324574aa781be09c83b7443a32848d091fd44fb12c1842d49cee77afc351e550ffcc096d SHA512 (pam_ssh_agent_auth-0.10.4.tar.gz) = caccf72174d15e43f4c86a459ac6448682e62116557cf1e1e828955f3d1731595b238df42adec57860e7f341e92daf5d8285020bcb5018f3b8a5145aa32ee1c2 SHA512 (gpgkey-736060BA.gpg) = df44f3fdbcd1d596705348c7f5aed3f738c5f626a55955e0642f7c6c082995cf36a1b1891bb41b8715cb2aff34fef1c877e0eff0d3507dd00a055ba695757a21 From d089d5f71b42eecdd5a1278d3477452d16803269 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Sun, 21 Jan 2024 11:22:01 +0000 Subject: [PATCH 05/80] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- openssh.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 77e5775..4b24148 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist} +Release: %{openssh_rel}%{?dist}.1 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -303,7 +303,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist} +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.1 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -739,6 +739,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Sun Jan 21 2024 Fedora Release Engineering - 9.6p1-1.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Tue Dec 26 2023 Daniel Milnes - 9.6p1-1 - Update to OpenSSH 9.6 Original patches from https://src.fedoraproject.org/rpms/openssh/pull-request/63 From 2f41ca7cd3f05b21bc95e8871ad55b244c26c468 Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 25 Jan 2024 11:29:57 +0000 Subject: [PATCH 06/80] Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild --- openssh.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 4b24148..1f8ab4e 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.1 +Release: %{openssh_rel}%{?dist}.2 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -303,7 +303,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.1 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.2 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -739,6 +739,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Thu Jan 25 2024 Fedora Release Engineering - 9.6p1-1.2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + * Sun Jan 21 2024 Fedora Release Engineering - 9.6p1-1.1 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From 086e6f64e1b48c5cae7f0559c6382013d0d196cc Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 13 Mar 2024 13:39:46 +0100 Subject: [PATCH 07/80] Disable openssl engine support in openssh --- openssh.spec | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 1f8ab4e..a51c301 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.2 +Release: %{openssh_rel}%{?dist}.3 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -303,7 +303,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.2 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.3 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -489,6 +489,7 @@ fi --with-default-pkcs11-provider=yes \ --with-security-key-builtin=yes \ --with-pam \ + --without-ssl-engine \ %if %{WITH_SELINUX} --with-selinux --with-audit=linux \ --with-sandbox=seccomp_filter \ @@ -539,6 +540,7 @@ LDFLAGS="$SAVE_LDFLAGS" %configure --with-selinux \ --libexecdir=/%{_libdir}/security \ --with-mantype=man \ + --without-ssl-engine \ --without-openssl-header-check `# The check is broken` %make_build popd @@ -739,6 +741,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Wed Mar 13 2024 Dmitry Belyavskiy - 9.6p1-1.3 +- Build OpenSSH without engine support + * Thu Jan 25 2024 Fedora Release Engineering - 9.6p1-1.2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild From 176421c4e42b13b3e14757461538951db59f6d09 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 13 Mar 2024 17:26:14 +0100 Subject: [PATCH 08/80] Run tests on building OpenSSH --- openssh-8.7p1-nohostsha1proof.patch | 6 +- openssh.spec | 8 +-- parallel_test.Makefile | 14 +++++ parallel_test.sh | 91 +++++++++++++++++++++++++++++ 4 files changed, 112 insertions(+), 7 deletions(-) create mode 100644 parallel_test.Makefile create mode 100755 parallel_test.sh diff --git a/openssh-8.7p1-nohostsha1proof.patch b/openssh-8.7p1-nohostsha1proof.patch index 7fea800..6a6b63d 100644 --- a/openssh-8.7p1-nohostsha1proof.patch +++ b/openssh-8.7p1-nohostsha1proof.patch @@ -241,10 +241,10 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss { size_t len; u_char *sig; -+ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */ -+ int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0; ++ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp in RHEL, permitted in Fedora */ ++ int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0) : 0; + if (k && (sshkey_type_plain(k->type) == KEY_DSA || sshkey_type_plain(k->type) == KEY_DSA_CERT)) -+ expected = SSH_ERR_LIBCRYPTO_ERROR; ++ expected = sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0); ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, - NULL, NULL, 0), 0); diff --git a/openssh.spec b/openssh.spec index a51c301..63d40d7 100644 --- a/openssh.spec +++ b/openssh.spec @@ -76,6 +76,8 @@ Source17: ssh-agent.socket Source19: openssh-server-systemd-sysusers.conf Source20: ssh-host-keys-migration.sh Source21: ssh-host-keys-migration.service +Source22: parallel_test.sh +Source23: parallel_test.Makefile #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 Patch100: openssh-6.7p1-coverity.patch @@ -547,10 +549,7 @@ popd %endif %check -#to run tests use "--with check" -%if %{?_with_check:1}%{!?_with_check:0} -make tests -%endif +%{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile %install rm -rf $RPM_BUILD_ROOT @@ -743,6 +742,7 @@ test -f %{sysconfig_anaconda} && \ %changelog * Wed Mar 13 2024 Dmitry Belyavskiy - 9.6p1-1.3 - Build OpenSSH without engine support +- Make tests run at build phase (using parallel run mechanism by Alexander Sosedkin) * Thu Jan 25 2024 Fedora Release Engineering - 9.6p1-1.2 - Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild diff --git a/parallel_test.Makefile b/parallel_test.Makefile new file mode 100644 index 0000000..a645710 --- /dev/null +++ b/parallel_test.Makefile @@ -0,0 +1,14 @@ +# just a Makefile parallel_test.sh uses to run stuff in parallel with make +%: + $(MAKE) -j1 -C .test/tree/$* $* + +t-exec-%: + $(MAKE) -j1 -C ".test/tree/t-exec-$*" \ + TEST_SSH_PORT=10$*0 \ + SKIP_LTESTS="$(shell cat .test/ltests/not-in/$*)" \ + BUILDDIR="$(shell pwd)/.test/tree/t-exec-$*" \ + TEST_SHELL=sh \ + MAKE=make \ + TEST_SSH_TRACE=yes \ + TEST_SSH_FAIL_FATAL=yes \ + t-exec \ diff --git a/parallel_test.sh b/parallel_test.sh new file mode 100755 index 0000000..54ba343 --- /dev/null +++ b/parallel_test.sh @@ -0,0 +1,91 @@ +#!/usr/bin/bash +set -uexo pipefail + +# The custom %check script to run the OpenSSH upstream testsuite in parallel. +# +# The upstream testsuite is serial, +# so the idea here is to split the testsuite into several $PARTS: +# * file-tests +# * interop-tests +# * unit +# * ltests-00 +# * ltests-01 +# * ... +# * ltests-23 +# and run them in parallel, using make, each in its own build subtree. + +PARALLEL_MAKEFILE=$1 + +SPLIT=24 +PARTS='file-tests interop-tests unit ' +for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i); + PARTS+="t-exec-$ii " +done + +# work around a selinux restriction: +chcon -t unconfined_exec_t ssh-sk-helper + +# work around something else that only crops up in brew +export TEST_SSH_UNSAFE_PERMISSIONS=1 + +# create a .test directory to store all our files in: +mkdir -p .test/tree .test/ltests/{in,not-in} + +# patch testsuite: use different ports to avoid port collisions +grep -REi 'port=[2-9][0-9]*' regress +sed -i 's|PORT=4242|PORT=$(expr $TEST_SSH_PORT + 1)|' \ + regress/test-exec.sh* +sed -i 's|^P=3301 # test port|P=$(expr $TEST_SSH_PORT + 1)|' \ + regress/multiplex.sh* +sed -i 's|^fwdport=3301|fwdport=$(expr $TEST_SSH_PORT + 1)|' \ + regress/cfgmatch.sh* regress/cfgmatchlisten.sh* +sed -i 's|^LFWD_PORT=.*|LFWD_PORT=$(expr $TEST_SSH_PORT + 1)|' \ + regress/forward-control.sh* +sed -i 's|^RFWD_PORT=.*|RFWD_PORT=$(expr $TEST_SSH_PORT + 2)|' \ + regress/forward-control.sh* +( ! grep -REi 'port=[2-9][0-9]*' regress) # try to find more of those + +# patch testsuite: speed up +sed -i 's|sleep 1$|sleep .25|' regress/forward-control.sh + +# extract LTESTS list to .tests/ltests/all: +grep -Ex 'tests:[[:space:]]*file-tests t-exec interop-tests extra-tests unit' Makefile +echo -ne '\necho-ltests:\n\techo ${LTESTS}' >> regress/Makefile +make -s -C regress echo-ltests | tr ' ' '\n' > .test/ltests/all + +# separate ltests into $SPLIT roughly equal .tests/ltests/in/$ii parts: +grep -qFx connect .test/ltests/all +( ! grep -qFx nonex .test/ltests/all ) +split -d -a2 --number=l/$SPLIT .test/ltests/all .test/ltests/in/ +wc -l .test/ltests/in/* +grep -qFx connect .test/ltests/in/* + +# generate the inverses of them --- .test/ltests/not-in/$ii: +( ! grep -qFx nonex .test/ltests/in/* ) +for ((i = 0; i < SPLIT; i++)); do ii=$(printf %02d $i); + while read -r tname; do + if ! grep -qFx "$tname" ".test/ltests/in/$ii"; then + echo -n "$tname " >> ".test/ltests/not-in/$ii" + fi + done < .test/ltests/all +done +grep . .test/ltests/not-in/* +( ! grep -q ^connect .test/ltests/not-in/0 ) +for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i); + grep -q ^connect .test/ltests/not-in/$ii +done + +# prepare several test directories: +for PART in $PARTS; do + mkdir .test/tree/${PART} + cp -ra * .test/tree/${PART}/ + sed -i "s|abs_top_srcdir=.*|abs_top_srcdir=$(pwd)/.test/tree/${PART}|" \ + .test/tree/${PART}/Makefile + sed -i "s|abs_top_builddir=.*|abs_top_builddir=$(pwd)/.test/tree/${PART}|" \ + .test/tree/${PART}/Makefile + sed -i "s|^BUILDDIR=.*|BUILDDIR=$(pwd)/.test/tree/${PART}|" \ + .test/tree/${PART}/Makefile +done + +# finally, run tests $PARTS in parallel in their own subtrees: +time make -f "$PARALLEL_MAKEFILE" -j$(nproc) $PARTS From 031b4c6f3661ba0aca243335b8834e1d54c94372 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Tue, 2 Apr 2024 15:43:15 -0700 Subject: [PATCH 09/80] Build OpenSSH without libsystemd dependency, using reference implementation --- openssh-7.4p1-systemd.patch | 98 ------------------ openssh-7.6p1-audit.patch | 4 +- openssh-9.8p1-systemd.patch | 201 ++++++++++++++++++++++++++++++++++++ openssh.spec | 7 +- 4 files changed, 208 insertions(+), 102 deletions(-) delete mode 100644 openssh-7.4p1-systemd.patch create mode 100644 openssh-9.8p1-systemd.patch diff --git a/openssh-7.4p1-systemd.patch b/openssh-7.4p1-systemd.patch deleted file mode 100644 index 1242aac..0000000 --- a/openssh-7.4p1-systemd.patch +++ /dev/null @@ -1,98 +0,0 @@ -commit 0e22b79bfde45a7cf7a2e51a68ec11c4285f3b31 -Author: Jakub Jelen -Date: Mon Nov 21 15:04:06 2016 +0100 - - systemd stuff - -diff --git a/configure.ac b/configure.ac -index 2ffc369..162ce92 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -4265,6 +4265,30 @@ AC_ARG_WITH([kerberos5], - AC_SUBST([K5LIBS]) - AC_SUBST([CHANNELLIBS]) - -+# Check whether user wants systemd support -+SYSTEMD_MSG="no" -+AC_ARG_WITH(systemd, -+ [ --with-systemd Enable systemd support], -+ [ if test "x$withval" != "xno" ; then -+ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no]) -+ if test "$PKGCONFIG" != "no"; then -+ AC_MSG_CHECKING([for libsystemd]) -+ if $PKGCONFIG --exists libsystemd; then -+ SYSTEMD_CFLAGS=`$PKGCONFIG --cflags libsystemd` -+ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd` -+ CPPFLAGS="$CPPFLAGS $SYSTEMD_CFLAGS" -+ SSHDLIBS="$SSHDLIBS $SYSTEMD_LIBS" -+ AC_MSG_RESULT([yes]) -+ AC_DEFINE(HAVE_SYSTEMD, 1, [Define if you want systemd support.]) -+ SYSTEMD_MSG="yes" -+ else -+ AC_MSG_RESULT([no]) -+ fi -+ fi -+ fi ] -+) -+ -+ - # Looking for programs, paths and files - - PRIVSEP_PATH=/var/empty -@@ -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" -+echo " systemd support: $SYSTEMD_MSG" - echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG" - echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" - echo " BSD Auth support: $BSD_AUTH_MSG" -diff --git a/contrib/sshd.service b/contrib/sshd.service -new file mode 100644 -index 0000000..e0d4923 ---- /dev/null -+++ b/contrib/sshd.service -@@ -0,0 +1,16 @@ -+[Unit] -+Description=OpenSSH server daemon -+Documentation=man:sshd(8) man:sshd_config(5) -+After=network.target -+ -+[Service] -+Type=notify -+ExecStart=/usr/sbin/sshd -D $OPTIONS -+ExecReload=/bin/kill -HUP $MAINPID -+KillMode=process -+Restart=on-failure -+RestartPreventExitStatus=255 -+ -+[Install] -+WantedBy=multi-user.target -+ -diff --git a/sshd.c b/sshd.c -index 816611c..b8b9d13 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -85,6 +85,10 @@ - #include - #endif - -+#ifdef HAVE_SYSTEMD -+#include -+#endif -+ - #include "xmalloc.h" - #include "ssh.h" - #include "ssh2.h" -@@ -1888,6 +1892,11 @@ main(int ac, char **av) - } - } - -+#ifdef HAVE_SYSTEMD -+ /* Signal systemd that we are ready to accept connections */ -+ sd_notify(0, "READY=1"); -+#endif -+ - /* Accept a connection and return in a forked child */ - server_accept_loop(&sock_in, &sock_out, - &newsock, config_s); diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index 748c4b6..cec5b23 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -2206,8 +2206,8 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c close_listen_socks(); if (options.pid_file != NULL) unlink(options.pid_file); -@@ -2098,7 +2154,7 @@ main(int ac, char **av) - #endif +@@ -2189,7 +2189,7 @@ + } /* Accept a connection and return in a forked child */ - server_accept_loop(&sock_in, &sock_out, diff --git a/openssh-9.8p1-systemd.patch b/openssh-9.8p1-systemd.patch new file mode 100644 index 0000000..b20624e --- /dev/null +++ b/openssh-9.8p1-systemd.patch @@ -0,0 +1,201 @@ +diff --git a/configure.ac b/configure.ac +index 379cd746b..15e2ecdb7 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -907,6 +907,7 @@ int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) + AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts]) + AC_DEFINE([USE_BTMP]) + AC_DEFINE([LINUX_OOM_ADJUST], [1], [Adjust Linux out-of-memory killer]) ++ AC_DEFINE([SYSTEMD_NOTIFY], [1], [Have sshd notify systemd on start/reload]) + inet6_default_4in6=yes + case `uname -r` in + 1.*|2.0.*) +diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c +index 0457e28d0..df7290246 100644 +--- a/openbsd-compat/port-linux.c ++++ b/openbsd-compat/port-linux.c +@@ -21,16 +21,23 @@ + + #include "includes.h" + +-#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) ++#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) || \ ++ defined(SYSTEMD_NOTIFY) ++#include ++#include ++ + #include ++#include + #include + #include + #include + #include ++#include + + #include "log.h" + #include "xmalloc.h" + #include "port-linux.h" ++#include "misc.h" + + #ifdef WITH_SELINUX + #include +@@ -310,4 +317,90 @@ oom_adjust_restore(void) + return; + } + #endif /* LINUX_OOM_ADJUST */ +-#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */ ++ ++#ifdef SYSTEMD_NOTIFY ++ ++static void ssh_systemd_notify(const char *, ...) ++ __attribute__((__format__ (printf, 1, 2))) __attribute__((__nonnull__ (1))); ++ ++static void ++ssh_systemd_notify(const char *fmt, ...) ++{ ++ char *s = NULL; ++ const char *path; ++ struct stat sb; ++ struct sockaddr_un addr; ++ int fd = -1; ++ va_list ap; ++ ++ if ((path = getenv("NOTIFY_SOCKET")) == NULL || strlen(path) == 0) ++ return; ++ ++ va_start(ap, fmt); ++ xvasprintf(&s, fmt, ap); ++ va_end(ap); ++ ++ /* Only AF_UNIX is supported, with path or abstract sockets */ ++ if (path[0] != '/' && path[0] != '@') { ++ error_f("socket \"%s\" is not compatible with AF_UNIX", path); ++ goto out; ++ } ++ ++ if (path[0] == '/' && stat(path, &sb) != 0) { ++ error_f("socket \"%s\" stat: %s", path, strerror(errno)); ++ goto out; ++ } ++ ++ memset(&addr, 0, sizeof(addr)); ++ addr.sun_family = AF_UNIX; ++ if (strlcpy(addr.sun_path, path, ++ sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) { ++ error_f("socket path \"%s\" too long", path); ++ goto out; ++ } ++ /* Support for abstract socket */ ++ if (addr.sun_path[0] == '@') ++ addr.sun_path[0] = 0; ++ if ((fd = socket(PF_UNIX, SOCK_DGRAM, 0)) == -1) { ++ error_f("socket \"%s\": %s", path, strerror(errno)); ++ goto out; ++ } ++ if (connect(fd, &addr, sizeof(addr)) != 0) { ++ error_f("socket \"%s\" connect: %s", path, strerror(errno)); ++ goto out; ++ } ++ if (write(fd, s, strlen(s)) != (ssize_t)strlen(s)) { ++ error_f("socket \"%s\" write: %s", path, strerror(errno)); ++ goto out; ++ } ++ debug_f("socket \"%s\" notified %s", path, s); ++ out: ++ if (fd != -1) ++ close(fd); ++ free(s); ++} ++ ++void ++ssh_systemd_notify_ready(void) ++{ ++ ssh_systemd_notify("READY=1"); ++} ++ ++void ++ssh_systemd_notify_reload(void) ++{ ++ struct timespec now; ++ ++ monotime_ts(&now); ++ if (now.tv_sec < 0 || now.tv_nsec < 0) { ++ error_f("monotime returned negative value"); ++ ssh_systemd_notify("RELOADING=1"); ++ } else { ++ ssh_systemd_notify("RELOADING=1\nMONOTONIC_USEC=%llu", ++ ((uint64_t)now.tv_sec * 1000000ULL) + ++ ((uint64_t)now.tv_nsec / 1000ULL)); ++ } ++} ++#endif /* SYSTEMD_NOTIFY */ ++ ++#endif /* WITH_SELINUX || LINUX_OOM_ADJUST || SYSTEMD_NOTIFY */ +diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h +index 3c22a854d..14064f87d 100644 +--- a/openbsd-compat/port-linux.h ++++ b/openbsd-compat/port-linux.h +@@ -30,4 +30,9 @@ void oom_adjust_restore(void); + void oom_adjust_setup(void); + #endif + ++#ifdef SYSTEMD_NOTIFY ++void ssh_systemd_notify_ready(void); ++void ssh_systemd_notify_reload(void); ++#endif ++ + #endif /* ! _PORT_LINUX_H */ +diff --git a/platform.c b/platform.c +index 4fe8744ee..9cf818153 100644 +--- a/platform.c ++++ b/platform.c +@@ -44,6 +44,14 @@ platform_pre_listen(void) + #endif + } + ++void ++platform_post_listen(void) ++{ ++#ifdef SYSTEMD_NOTIFY ++ ssh_systemd_notify_ready(); ++#endif ++} ++ + void + platform_pre_fork(void) + { +@@ -55,6 +63,9 @@ platform_pre_fork(void) + void + platform_pre_restart(void) + { ++#ifdef SYSTEMD_NOTIFY ++ ssh_systemd_notify_reload(); ++#endif + #ifdef LINUX_OOM_ADJUST + oom_adjust_restore(); + #endif +diff --git a/platform.h b/platform.h +index 7fef8c983..5dec23276 100644 +--- a/platform.h ++++ b/platform.h +@@ -21,6 +21,7 @@ + void platform_pre_listen(void); + void platform_pre_fork(void); + void platform_pre_restart(void); ++void platform_post_listen(void); + void platform_post_fork_parent(pid_t child_pid); + void platform_post_fork_child(void); + int platform_privileged_uidswap(void); +diff --git a/sshd.c b/sshd.c +index 9cbe92293..3c3f2dd6b 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -2077,6 +2077,8 @@ main(int ac, char **av) + ssh_signal(SIGTERM, sigterm_handler); + ssh_signal(SIGQUIT, sigterm_handler); + ++ platform_post_listen(); ++ + /* + * Write out the pid file after the sigterm handler + * is setup and the listen sockets are bound diff --git a/openssh.spec b/openssh.spec index 63d40d7..20577a1 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.3 +Release: %{openssh_rel}%{?dist}.4 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -175,7 +175,7 @@ Patch939: openssh-7.2p2-s390-closefrom.patch # Move MAX_DISPLAYS to a configuration option (#1341302) Patch944: openssh-7.3p1-x11-max-displays.patch # Help systemd to track the running service -Patch948: openssh-7.4p1-systemd.patch +Patch948: openssh-9.8p1-systemd.patch # Pass inetd flags for SELinux down to openbsd compat level Patch949: openssh-7.6p1-cleanup-selinux.patch # Sandbox adjustments for s390 and audit @@ -740,6 +740,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Tue Apr 02 2024 Gordon Messmer - 9.6p1-1.4 +- Build OpenSSH without libsystemd dependency, using reference implementation + * Wed Mar 13 2024 Dmitry Belyavskiy - 9.6p1-1.3 - Build OpenSSH without engine support - Make tests run at build phase (using parallel run mechanism by Alexander Sosedkin) From 56e678546d32c1025d7d92a361c8e32df8beb5d4 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 4 Apr 2024 20:36:51 +0200 Subject: [PATCH 10/80] Bump pam_ssh_agent version --- openssh.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 20577a1..9c66bac 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.4 +Release: %{openssh_rel}%{?dist}.5 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -305,7 +305,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.3 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.4 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -740,6 +740,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Thu Apr 04 2024 Dmitry Belyavskiy - 9.6p1-1.5 +- rebuilt + * Tue Apr 02 2024 Gordon Messmer - 9.6p1-1.4 - Build OpenSSH without libsystemd dependency, using reference implementation From 055c4e2de729d2eb506f4fdce90455847eb15394 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 4 Apr 2024 20:56:51 +0200 Subject: [PATCH 11/80] Rebuild --- openssh.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 9c66bac..fe75a1c 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.5 +Release: %{openssh_rel}%{?dist}.6 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -305,7 +305,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.4 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.5 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -740,6 +740,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Thu Apr 04 2024 Dmitry Belyavskiy - 9.6p1-1.6 +- rebuilt + * Thu Apr 04 2024 Dmitry Belyavskiy - 9.6p1-1.5 - rebuilt From 8fb8f02a0d20c36145d00309f91356e4552ebcd3 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Tue, 2 Apr 2024 15:34:14 +0200 Subject: [PATCH 12/80] Only set PAM_RHOST if the remote host is not "UNKNOWN" When using sshd's -i option with stdio that is not a AF_INET/AF_INET6 socket, auth_get_canonical_hostname() returns "UNKNOWN" which is then set as the value of PAM_RHOST, causing pam to try to do a reverse DNS query of "UNKNOWN", which times out multiple times, causing a substantial slowdown when logging in. To fix this, let's only set PAM_RHOST if the hostname is not "UNKNOWN". The upstream PR (https://github.com/openssh/openssh-portable/pull/388) has gone unreviewed for more than a year, even after multiple pings on the PR and the mailing list. This greatly improves the experience of using systemd's new ssh-generator (https://github.com/systemd/systemd/pull/30777) which allows connecting to VMs via VSOCK. --- openssh-9.6p1-pam-rhost.patch | 32 ++++++++++++++++++++++++++++++++ openssh.spec | 5 ++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 openssh-9.6p1-pam-rhost.patch diff --git a/openssh-9.6p1-pam-rhost.patch b/openssh-9.6p1-pam-rhost.patch new file mode 100644 index 0000000..b1b0d04 --- /dev/null +++ b/openssh-9.6p1-pam-rhost.patch @@ -0,0 +1,32 @@ +From 26f366e263e575c4e1a18e2e64ba418f58878b37 Mon Sep 17 00:00:00 2001 +From: Daan De Meyer +Date: Mon, 20 Mar 2023 20:22:14 +0100 +Subject: [PATCH] Only set PAM_RHOST if the remote host is not "UNKNOWN" + +When using sshd's -i option with stdio that is not a AF_INET/AF_INET6 +socket, auth_get_canonical_hostname() returns "UNKNOWN" which is then +set as the value of PAM_RHOST, causing pam to try to do a reverse DNS +query of "UNKNOWN", which times out multiple times, causing a +substantial slowdown when logging in. + +To fix this, let's only set PAM_RHOST if the hostname is not "UNKNOWN". +--- + auth-pam.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/auth-pam.c b/auth-pam.c +index e143304e3..39b4e4563 100644 +--- a/auth-pam.c ++++ b/auth-pam.c +@@ -735,7 +735,7 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt) + sshpam_laddr = get_local_ipaddr( + ssh_packet_get_connection_in(ssh)); + } +- if (sshpam_rhost != NULL) { ++ if (sshpam_rhost != NULL && strcmp(sshpam_rhost, "UNKNOWN") != 0) { + debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost); + sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, + sshpam_rhost); +-- +2.44.0 + diff --git a/openssh.spec b/openssh.spec index fe75a1c..474cb39 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.6 +Release: %{openssh_rel}%{?dist}.7 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -231,6 +231,8 @@ Patch1012: openssh-9.0p1-evp-fips-dh.patch Patch1013: openssh-9.0p1-evp-fips-ecdh.patch Patch1014: openssh-8.7p1-nohostsha1proof.patch +Patch1015: openssh-9.6p1-pam-rhost.patch + License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -432,6 +434,7 @@ popd %patch -P 1012 -p1 -b .evp-fips-dh %patch -P 1013 -p1 -b .evp-fips-ecdh %patch -P 1014 -p1 -b .nosha1hostproof +%patch -P 1015 -p1 -b .pam-rhost %patch -P 100 -p1 -b .coverity From 665f4ad35fbd4ece7a489a83e6a0aa81182cd008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Apr 2024 22:31:24 +0200 Subject: [PATCH 13/80] Allow %check to run on systems without selinux chcon will fail in builds where selinux is disabled, but this is just a workaround that is needed with selinux, so ignore the result. --- parallel_test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parallel_test.sh b/parallel_test.sh index 54ba343..e7208c7 100755 --- a/parallel_test.sh +++ b/parallel_test.sh @@ -23,7 +23,7 @@ for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i); done # work around a selinux restriction: -chcon -t unconfined_exec_t ssh-sk-helper +chcon -t unconfined_exec_t ssh-sk-helper || : # work around something else that only crops up in brew export TEST_SSH_UNSAFE_PERMISSIONS=1 From b001382b227249574e66101d1127b53672508839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 16 Apr 2024 22:35:55 +0200 Subject: [PATCH 14/80] Drop %attr for a symlink This removes the following warning: RPM build warnings: Explicit %attr() mode not applicable to symlink: /builddir/build/BUILDROOT/openssh-9.6p1-1.fc41.6.x86_64/usr/libexec/openssh/ssh-askpass --- openssh.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssh.spec b/openssh.spec index 474cb39..0fe92a1 100644 --- a/openssh.spec +++ b/openssh.spec @@ -729,7 +729,7 @@ test -f %{sysconfig_anaconda} && \ %files askpass %attr(0644,root,root) %{_sysconfdir}/profile.d/gnome-ssh-askpass.* %attr(0755,root,root) %{_libexecdir}/openssh/gnome-ssh-askpass -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-askpass +%{_libexecdir}/openssh/ssh-askpass %endif %files sk-dummy From 80ba97c338af85549038d65c771494d9c1beacc1 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 17 Apr 2024 10:44:40 +0200 Subject: [PATCH 15/80] Bump spec --- openssh.spec | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/openssh.spec b/openssh.spec index 0fe92a1..da06fbb 100644 --- a/openssh.spec +++ b/openssh.spec @@ -307,7 +307,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.5 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.6 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -743,6 +743,14 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Wed Apr 17 2024 Dmitry Belyavskiy - 9.6p1-1.7 +- Only set PAM_RHOST if the remote host is not "UNKNOWN" + https://src.fedoraproject.org/rpms/openssh/pull-request/71 + Patch by Daan De Meyer +- Some spec cleanup + https://src.fedoraproject.org/rpms/openssh/pull-request/74 + by Zbigniew Jędrzejewski-Szmek + * Thu Apr 04 2024 Dmitry Belyavskiy - 9.6p1-1.6 - rebuilt From 855a9d9c41abc0e322dd7fba7a8b419e02730eb3 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 24 Apr 2024 12:00:24 +0200 Subject: [PATCH 16/80] Use OpenSSL SSH KDF implementation --- openssh-7.7p1-fips.patch | 2 +- openssh-8.0p1-openssl-kdf.patch | 95 +++++++++++++++++++-------------- openssh.spec | 7 ++- 3 files changed, 60 insertions(+), 44 deletions(-) diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index 5351571..b1007b2 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -81,7 +81,7 @@ diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c #include +#include #include - # ifdef HAVE_EVP_KDF_CTX_NEW_ID + # ifdef HAVE_EVP_KDF_CTX_NEW # include @@ -203,7 +203,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; diff --git a/openssh-8.0p1-openssl-kdf.patch b/openssh-8.0p1-openssl-kdf.patch index 5d76a4f..13fb9e6 100644 --- a/openssh-8.0p1-openssl-kdf.patch +++ b/openssh-8.0p1-openssl-kdf.patch @@ -12,7 +12,7 @@ index 2a455e4e..e01c3d43 100644 HMAC_CTX_init \ RSA_generate_key_ex \ RSA_get_default_method \ -+ EVP_KDF_CTX_new_id \ ++ EVP_KDF_CTX_new \ ]) # OpenSSL_add_all_algorithms may be a macro. @@ -20,33 +20,35 @@ diff --git a/kex.c b/kex.c index b6f041f4..1fbce2bb 100644 --- a/kex.c +++ b/kex.c -@@ -38,6 +38,9 @@ +@@ -38,6 +38,11 @@ #ifdef WITH_OPENSSL #include #include -+# ifdef HAVE_EVP_KDF_CTX_NEW_ID ++# ifdef HAVE_EVP_KDF_CTX_NEW +# include ++# include ++# include +# endif #endif #include "ssh.h" -@@ -942,6 +945,95 @@ kex_choose_conf(struct ssh *ssh) +@@ -942,6 +945,106 @@ kex_choose_conf(struct ssh *ssh) return r; } -+#ifdef HAVE_EVP_KDF_CTX_NEW_ID -+static const EVP_MD * ++#ifdef HAVE_EVP_KDF_CTX_NEW ++static const char * +digest_to_md(int digest_type) +{ + switch (digest_type) { + case SSH_DIGEST_SHA1: -+ return EVP_sha1(); ++ return SN_sha1; + case SSH_DIGEST_SHA256: -+ return EVP_sha256(); ++ return SN_sha256; + case SSH_DIGEST_SHA384: -+ return EVP_sha384(); ++ return SN_sha384; + case SSH_DIGEST_SHA512: -+ return EVP_sha512(); ++ return SN_sha512; + } + return NULL; +} @@ -56,52 +58,61 @@ index b6f041f4..1fbce2bb 100644 + const struct sshbuf *shared_secret, u_char **keyp) +{ + struct kex *kex = ssh->kex; -+ EVP_KDF_CTX *ctx = NULL; + u_char *key = NULL; + int r, key_len; + -+ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) -+ return SSH_ERR_INVALID_ARGUMENT; ++ EVP_KDF *kdf = EVP_KDF_fetch(NULL, "SSHKDF", NULL); ++ EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf); ++ OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); ++ OSSL_PARAM *params = NULL; ++ const char *md = digest_to_md(kex->hash_alg); ++ ++ EVP_KDF_free(kdf); ++ if (!ctx) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (md == NULL) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } ++ ++ if (param_bld == NULL) { ++ EVP_KDF_CTX_free(ctx); ++ return -1; ++ } ++ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } ++ + key_len = ROUNDUP(need, key_len); + if ((key = calloc(1, key_len)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + -+ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF); -+ if (!ctx) { ++ r = OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_DIGEST, ++ md, strlen(md)) && /* SN */ ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_KEY, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)) && ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_XCGHASH, ++ hash, hashlen) && ++ OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_SESSION_ID, ++ sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id)) && ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_SSHKDF_TYPE, ++ (const char*)&id, 1); ++ if (r != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest_to_md(kex->hash_alg)); -+ if (r != 1) { ++ params = OSSL_PARAM_BLD_to_param(param_bld); ++ if (params == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, -+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, hash, hashlen); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, id); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, -+ sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id)); -+ if (r != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = EVP_KDF_derive(ctx, key, key_len); ++ r = EVP_KDF_derive(ctx, key, key_len, params); + if (r != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; @@ -115,6 +126,8 @@ index b6f041f4..1fbce2bb 100644 + r = 0; + +out: ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); + free (key); + EVP_KDF_CTX_free(ctx); + if (r < 0) { @@ -130,7 +143,7 @@ index b6f041f4..1fbce2bb 100644 ssh_digest_free(hashctx); return r; } -+#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */ ++#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW */ #define NKEYS 6 int diff --git a/openssh.spec b/openssh.spec index da06fbb..9b67cb1 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.7 +Release: %{openssh_rel}%{?dist}.8 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -307,7 +307,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.6 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.7 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -743,6 +743,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Wed Apr 24 2024 Dmitry Belyavskiy - 9.6p1-1.8 +- Use OpenSSL SSH KDF implementation + * Wed Apr 17 2024 Dmitry Belyavskiy - 9.6p1-1.7 - Only set PAM_RHOST if the remote host is not "UNKNOWN" https://src.fedoraproject.org/rpms/openssh/pull-request/71 From 53eafa2b19d0703e4db769946756385cfa078d2c Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 24 Apr 2024 15:13:42 +0200 Subject: [PATCH 17/80] Use OpenSSL SSH KDF implementation - s390x fixup --- openssh-8.0p1-openssl-kdf.patch | 5 +++-- openssh.spec | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/openssh-8.0p1-openssl-kdf.patch b/openssh-8.0p1-openssl-kdf.patch index 13fb9e6..c22b210 100644 --- a/openssh-8.0p1-openssl-kdf.patch +++ b/openssh-8.0p1-openssl-kdf.patch @@ -32,7 +32,7 @@ index b6f041f4..1fbce2bb 100644 #endif #include "ssh.h" -@@ -942,6 +945,106 @@ kex_choose_conf(struct ssh *ssh) +@@ -942,6 +945,107 @@ kex_choose_conf(struct ssh *ssh) return r; } @@ -66,6 +66,7 @@ index b6f041f4..1fbce2bb 100644 + OSSL_PARAM_BLD *param_bld = OSSL_PARAM_BLD_new(); + OSSL_PARAM *params = NULL; + const char *md = digest_to_md(kex->hash_alg); ++ char keytype = (char)id; + + EVP_KDF_free(kdf); + if (!ctx) { @@ -101,7 +102,7 @@ index b6f041f4..1fbce2bb 100644 + OSSL_PARAM_BLD_push_octet_string(param_bld, OSSL_KDF_PARAM_SSHKDF_SESSION_ID, + sshbuf_ptr(kex->session_id), sshbuf_len(kex->session_id)) && + OSSL_PARAM_BLD_push_utf8_string(param_bld, OSSL_KDF_PARAM_SSHKDF_TYPE, -+ (const char*)&id, 1); ++ &keytype, 1); + if (r != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; diff --git a/openssh.spec b/openssh.spec index 9b67cb1..6a2558e 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.8 +Release: %{openssh_rel}%{?dist}.9 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -307,7 +307,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.7 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.8 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -743,6 +743,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Wed Apr 24 2024 Dmitry Belyavskiy - 9.6p1-1.9 +- Use OpenSSL SSH KDF implementation - s390x fixup + * Wed Apr 24 2024 Dmitry Belyavskiy - 9.6p1-1.8 - Use OpenSSL SSH KDF implementation From dc8423673e255ca9ac3ee8c5b615b08ac74269b4 Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Thu, 9 May 2024 16:29:32 +0200 Subject: [PATCH 18/80] Correctly audit hostname and IP address Signed-off-by: Zoltan Fridrich --- openssh-8.7p1-audit-hostname.patch | 106 +++++++++++++++++++++++++++++ openssh.spec | 8 ++- 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 openssh-8.7p1-audit-hostname.patch diff --git a/openssh-8.7p1-audit-hostname.patch b/openssh-8.7p1-audit-hostname.patch new file mode 100644 index 0000000..e450c00 --- /dev/null +++ b/openssh-8.7p1-audit-hostname.patch @@ -0,0 +1,106 @@ +diff --color -ruNp a/audit-linux.c b/audit-linux.c +--- a/audit-linux.c 2024-05-09 12:38:08.843017319 +0200 ++++ b/audit-linux.c 2024-05-09 12:47:05.162267634 +0200 +@@ -52,7 +52,7 @@ extern u_int utmp_len; + const char *audit_username(void); + + static void +-linux_audit_user_logxxx(int uid, const char *username, ++linux_audit_user_logxxx(int uid, const char *username, const char *hostname, + const char *ip, const char *ttyn, int success, int event) + { + int audit_fd, rc, saved_errno; +@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const c + } + rc = audit_log_acct_message(audit_fd, event, + NULL, "login", username ? username : "(unknown)", +- username == NULL ? uid : -1, NULL, ip, ttyn, success); ++ username == NULL ? uid : -1, hostname, ip, ttyn, success); + saved_errno = errno; + close(audit_fd); + +@@ -181,9 +181,11 @@ audit_run_command(struct ssh *ssh, const + { + if (!user_login_count++) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGIN); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_START); + return 0; +@@ -193,10 +195,12 @@ void + audit_end_command(struct ssh *ssh, int handle, const char *command) + { + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); + } +@@ -211,19 +215,27 @@ void + audit_session_open(struct logininfo *li) + { + if (!user_login_count++) +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_LOGIN); +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_START); + } + + void + audit_session_close(struct logininfo *li) + { +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_LOGOUT); + } + +@@ -236,6 +248,7 @@ audit_event(struct ssh *ssh, ssh_audit_e + linux_audit_user_auth(-1, audit_username(), + ssh_remote_ipaddr(ssh), "ssh", 0, event); + linux_audit_user_logxxx(-1, audit_username(), ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + case SSH_AUTH_FAIL_PASSWD: +@@ -254,9 +267,11 @@ audit_event(struct ssh *ssh, ssh_audit_e + if (user_login_count) { + while (user_login_count--) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); + } +@@ -265,6 +280,7 @@ audit_event(struct ssh *ssh, ssh_audit_e + case SSH_CONNECTION_ABANDON: + case SSH_INVALID_USER: + linux_audit_user_logxxx(-1, audit_username(), ++ options.use_dns ? remote_hostname(ssh) : NULL, + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + default: diff --git a/openssh.spec b/openssh.spec index 6a2558e..841d818 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.9 +Release: %{openssh_rel}%{?dist}.10 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -90,6 +90,8 @@ Patch200: openssh-7.6p1-audit.patch Patch201: openssh-7.1p2-audit-race-condition.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2049947 Patch202: openssh-9.0p1-audit-log.patch +# Correctly audit hostname and IP address +Patch203: openssh-8.7p1-audit-hostname.patch # --- pam_ssh-agent --- # make it build reusing the openssh sources @@ -425,6 +427,7 @@ popd %patch -P 200 -p1 -b .audit %patch -P 201 -p1 -b .audit-race %patch -P 202 -p1 -b .audit-log +%patch -P 203 -p1 -b .audit-hostname %patch -P 700 -p1 -b .fips %patch -P 1002 -p1 -b .ssh-manpage @@ -743,6 +746,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Thu May 09 2024 Zoltan Fridrich - 9.6p1-10 +- Correctly audit hostname and IP address + * Wed Apr 24 2024 Dmitry Belyavskiy - 9.6p1-1.9 - Use OpenSSL SSH KDF implementation - s390x fixup From b77eafa86b6affb89ab5002b3d8925199945e47f Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Thu, 9 May 2024 16:30:24 +0200 Subject: [PATCH 19/80] Make default key sizes configurable in sshd-keygen Signed-off-by: Zoltan Fridrich --- openssh.spec | 1 + sshd-keygen | 12 +++++++++--- sshd.sysconfig | 3 +++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/openssh.spec b/openssh.spec index 841d818..1f1829d 100644 --- a/openssh.spec +++ b/openssh.spec @@ -748,6 +748,7 @@ test -f %{sysconfig_anaconda} && \ %changelog * Thu May 09 2024 Zoltan Fridrich - 9.6p1-10 - Correctly audit hostname and IP address +- Make default key sizes configurable in sshd-keygen * Wed Apr 24 2024 Dmitry Belyavskiy - 9.6p1-1.9 - Use OpenSSL SSH KDF implementation - s390x fixup diff --git a/sshd-keygen b/sshd-keygen index 170ada0..b15fc8c 100644 --- a/sshd-keygen +++ b/sshd-keygen @@ -9,8 +9,14 @@ case $KEYTYPE in if [[ -r "$FIPS" && $(cat $FIPS) == "1" ]]; then exit 0 fi ;; - "rsa") ;; # always ok - "ecdsa") ;; + "rsa") + if [[ ! -z $SSH_RSA_BITS ]]; then + SSH_KEYGEN_OPTIONS="-b $SSH_RSA_BITS" + fi ;; # always ok + "ecdsa") + if [[ ! -z $SSH_ECDSA_BITS ]]; then + SSH_KEYGEN_OPTIONS="-b $SSH_ECDSA_BITS" + fi ;; *) # wrong argument exit 12 ;; esac @@ -25,7 +31,7 @@ fi rm -f $KEY{,.pub} # create new keys -if ! $KEYGEN -q -t $KEYTYPE -f $KEY -C '' -N '' >&/dev/null; then +if ! $KEYGEN -q -t $KEYTYPE $SSH_KEYGEN_OPTIONS -f $KEY -C '' -N '' >&/dev/null; then exit 1 fi diff --git a/sshd.sysconfig b/sshd.sysconfig index a217ce7..ee44ae6 100644 --- a/sshd.sysconfig +++ b/sshd.sysconfig @@ -5,3 +5,6 @@ # example using systemctl enable sshd-keygen@dsa.service to allow creation # of DSA key or systemctl mask sshd-keygen@rsa.service to disable RSA key # creation. + +#SSH_RSA_BITS=3072 +#SSH_ECDSA_BITS=256 From 69c52aa2991c51d15b1eb51919c6e4f304e4bd69 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Mon, 1 Jul 2024 20:23:20 -0700 Subject: [PATCH 20/80] Shorten paths used for parallel tests to fix BZ#2295117 --- openssh.spec | 5 ++++- parallel_test.Makefile | 8 ++++---- parallel_test.sh | 46 +++++++++++++++++++++--------------------- 3 files changed, 31 insertions(+), 28 deletions(-) diff --git a/openssh.spec b/openssh.spec index 1f1829d..fbd8866 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.10 +Release: %{openssh_rel}%{?dist}.11 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -746,6 +746,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Mon Jul 01 2024 Gordon Messmer - 9.6p1-11 +- Shorten paths used for parallel tests to fix BZ#2295117 + * Thu May 09 2024 Zoltan Fridrich - 9.6p1-10 - Correctly audit hostname and IP address - Make default key sizes configurable in sshd-keygen diff --git a/parallel_test.Makefile b/parallel_test.Makefile index a645710..f49df30 100644 --- a/parallel_test.Makefile +++ b/parallel_test.Makefile @@ -1,12 +1,12 @@ # just a Makefile parallel_test.sh uses to run stuff in parallel with make %: - $(MAKE) -j1 -C .test/tree/$* $* + $(MAKE) -j1 -C .t/$* $* t-exec-%: - $(MAKE) -j1 -C ".test/tree/t-exec-$*" \ + $(MAKE) -j1 -C ".t/t-exec-$*" \ TEST_SSH_PORT=10$*0 \ - SKIP_LTESTS="$(shell cat .test/ltests/not-in/$*)" \ - BUILDDIR="$(shell pwd)/.test/tree/t-exec-$*" \ + SKIP_LTESTS="$(shell cat .ltests/not-in/$*)" \ + BUILDDIR="$(shell pwd)/.t/t-exec-$*" \ TEST_SHELL=sh \ MAKE=make \ TEST_SSH_TRACE=yes \ diff --git a/parallel_test.sh b/parallel_test.sh index e7208c7..682c7e8 100755 --- a/parallel_test.sh +++ b/parallel_test.sh @@ -29,7 +29,7 @@ chcon -t unconfined_exec_t ssh-sk-helper || : export TEST_SSH_UNSAFE_PERMISSIONS=1 # create a .test directory to store all our files in: -mkdir -p .test/tree .test/ltests/{in,not-in} +mkdir -p .t .ltests/{in,not-in} # patch testsuite: use different ports to avoid port collisions grep -REi 'port=[2-9][0-9]*' regress @@ -51,40 +51,40 @@ sed -i 's|sleep 1$|sleep .25|' regress/forward-control.sh # extract LTESTS list to .tests/ltests/all: grep -Ex 'tests:[[:space:]]*file-tests t-exec interop-tests extra-tests unit' Makefile echo -ne '\necho-ltests:\n\techo ${LTESTS}' >> regress/Makefile -make -s -C regress echo-ltests | tr ' ' '\n' > .test/ltests/all +make -s -C regress echo-ltests | tr ' ' '\n' > .ltests/all # separate ltests into $SPLIT roughly equal .tests/ltests/in/$ii parts: -grep -qFx connect .test/ltests/all -( ! grep -qFx nonex .test/ltests/all ) -split -d -a2 --number=l/$SPLIT .test/ltests/all .test/ltests/in/ -wc -l .test/ltests/in/* -grep -qFx connect .test/ltests/in/* +grep -qFx connect .ltests/all +( ! grep -qFx nonex .ltests/all ) +split -d -a2 --number=l/$SPLIT .ltests/all .ltests/in/ +wc -l .ltests/in/* +grep -qFx connect .ltests/in/* -# generate the inverses of them --- .test/ltests/not-in/$ii: -( ! grep -qFx nonex .test/ltests/in/* ) +# generate the inverses of them --- .ltests/not-in/$ii: +( ! grep -qFx nonex .ltests/in/* ) for ((i = 0; i < SPLIT; i++)); do ii=$(printf %02d $i); while read -r tname; do - if ! grep -qFx "$tname" ".test/ltests/in/$ii"; then - echo -n "$tname " >> ".test/ltests/not-in/$ii" + if ! grep -qFx "$tname" ".ltests/in/$ii"; then + echo -n "$tname " >> ".ltests/not-in/$ii" fi - done < .test/ltests/all + done < .ltests/all done -grep . .test/ltests/not-in/* -( ! grep -q ^connect .test/ltests/not-in/0 ) +grep . .ltests/not-in/* +( ! grep -q ^connect .ltests/not-in/0 ) for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i); - grep -q ^connect .test/ltests/not-in/$ii + grep -q ^connect .ltests/not-in/$ii done # prepare several test directories: for PART in $PARTS; do - mkdir .test/tree/${PART} - cp -ra * .test/tree/${PART}/ - sed -i "s|abs_top_srcdir=.*|abs_top_srcdir=$(pwd)/.test/tree/${PART}|" \ - .test/tree/${PART}/Makefile - sed -i "s|abs_top_builddir=.*|abs_top_builddir=$(pwd)/.test/tree/${PART}|" \ - .test/tree/${PART}/Makefile - sed -i "s|^BUILDDIR=.*|BUILDDIR=$(pwd)/.test/tree/${PART}|" \ - .test/tree/${PART}/Makefile + mkdir .t/${PART} + cp -ra * .t/${PART}/ + sed -i "s|abs_top_srcdir=.*|abs_top_srcdir=$(pwd)/.t/${PART}|" \ + .t/${PART}/Makefile + sed -i "s|abs_top_builddir=.*|abs_top_builddir=$(pwd)/.t/${PART}|" \ + .t/${PART}/Makefile + sed -i "s|^BUILDDIR=.*|BUILDDIR=$(pwd)/.t/${PART}|" \ + .t/${PART}/Makefile done # finally, run tests $PARTS in parallel in their own subtrees: From dcbca7b947cf82c30d6f477a26efd2f765204fe6 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Mon, 1 Jul 2024 20:49:16 -0700 Subject: [PATCH 21/80] Patch 9.6p1 for CVE-2024-6387 --- CVE-2024-6387.patch | 18 ++++++++++++++++++ openssh.spec | 8 +++++++- 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 CVE-2024-6387.patch diff --git a/CVE-2024-6387.patch b/CVE-2024-6387.patch new file mode 100644 index 0000000..0b976c0 --- /dev/null +++ b/CVE-2024-6387.patch @@ -0,0 +1,18 @@ +diff --git a/log.c b/log.c +index 9fc1a2e2e..191ff4a5a 100644 +--- a/log.c ++++ b/log.c +@@ -451,12 +451,14 @@ void + sshsigdie(const char *file, const char *func, int line, int showfunc, + LogLevel level, const char *suffix, const char *fmt, ...) + { ++#ifdef SYSLOG_R_SAFE_IN_SIGHAND + va_list args; + + va_start(args, fmt); + sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL, + suffix, fmt, args); + va_end(args); ++#endif + _exit(1); + } diff --git a/openssh.spec b/openssh.spec index fbd8866..7144775 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.11 +Release: %{openssh_rel}%{?dist}.12 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -235,6 +235,8 @@ Patch1014: openssh-8.7p1-nohostsha1proof.patch Patch1015: openssh-9.6p1-pam-rhost.patch +Patch1016: CVE-2024-6387.patch + License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -438,6 +440,7 @@ popd %patch -P 1013 -p1 -b .evp-fips-ecdh %patch -P 1014 -p1 -b .nosha1hostproof %patch -P 1015 -p1 -b .pam-rhost +%patch -P 1016 -p1 -b .cve-2024-6387 %patch -P 100 -p1 -b .coverity @@ -746,6 +749,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Mon Jul 01 2024 Gordon Messmer - 9.6p1-12 +- Patch 9.6p1 for CVE-2024-6387 + * Mon Jul 01 2024 Gordon Messmer - 9.6p1-11 - Shorten paths used for parallel tests to fix BZ#2295117 From c58fea86cd5c7a905a02a14a44538c9aec5e11a6 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Tue, 2 Jul 2024 11:12:42 +0200 Subject: [PATCH 22/80] Version bump --- openssh.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 7144775..5195f39 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.12 +Release: %{openssh_rel}%{?dist}.13 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -311,7 +311,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.8 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.13 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -749,6 +749,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Tue Jul 02 2024 Dmitry Belyavskiy - 9.6p1-1.13 +- rebuilt + * Mon Jul 01 2024 Gordon Messmer - 9.6p1-12 - Patch 9.6p1 for CVE-2024-6387 From 2b3c43fd47527548fb0cfab89da647ec69b55808 Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Mon, 27 May 2024 12:00:57 +0200 Subject: [PATCH 23/80] Rewriting OpenSSH GSS KEX to use new packet API Signed-off-by: Zoltan Fridrich --- openssh-9.6p1-gsskex-new-api.patch | 1965 ++++++++++++++++++++++++++++ openssh.spec | 4 +- 2 files changed, 1968 insertions(+), 1 deletion(-) create mode 100644 openssh-9.6p1-gsskex-new-api.patch diff --git a/openssh-9.6p1-gsskex-new-api.patch b/openssh-9.6p1-gsskex-new-api.patch new file mode 100644 index 0000000..ed09319 --- /dev/null +++ b/openssh-9.6p1-gsskex-new-api.patch @@ -0,0 +1,1965 @@ +diff --color -ruNp a/gss-genr.c b/gss-genr.c +--- a/gss-genr.c 2024-05-16 15:49:43.999411060 +0200 ++++ b/gss-genr.c 2024-06-26 12:17:55.586856954 +0200 +@@ -346,6 +346,7 @@ ssh_gssapi_build_ctx(Gssctxt **ctx) + (*ctx)->creds = GSS_C_NO_CREDENTIAL; + (*ctx)->client = GSS_C_NO_NAME; + (*ctx)->client_creds = GSS_C_NO_CREDENTIAL; ++ (*ctx)->first = 1; + } + + /* Delete our context, providing it has been built correctly */ +@@ -371,6 +372,12 @@ ssh_gssapi_delete_ctx(Gssctxt **ctx) + gss_release_name(&ms, &(*ctx)->client); + if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) + gss_release_cred(&ms, &(*ctx)->client_creds); ++ sshbuf_free((*ctx)->shared_secret); ++ sshbuf_free((*ctx)->server_pubkey); ++ sshbuf_free((*ctx)->server_host_key_blob); ++ sshbuf_free((*ctx)->server_blob); ++ explicit_bzero((*ctx)->hash, sizeof((*ctx)->hash)); ++ BN_clear_free((*ctx)->dh_client_pub); + + free(*ctx); + *ctx = NULL; +diff --color -ruNp a/kexgssc.c b/kexgssc.c +--- a/kexgssc.c 2024-05-16 15:49:43.820407648 +0200 ++++ b/kexgssc.c 2024-07-02 16:26:25.628746744 +0200 +@@ -47,566 +47,658 @@ + + #include "ssh-gss.h" + +-int +-kexgss_client(struct ssh *ssh) ++static int input_kexgss_hostkey(int, u_int32_t, struct ssh *); ++static int input_kexgss_continue(int, u_int32_t, struct ssh *); ++static int input_kexgss_complete(int, u_int32_t, struct ssh *); ++static int input_kexgss_error(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_group(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_continue(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_complete(int, u_int32_t, struct ssh *); ++ ++static int ++kexgss_final(struct ssh *ssh) + { + struct kex *kex = ssh->kex; +- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, +- recv_tok = GSS_C_EMPTY_BUFFER, +- gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; +- Gssctxt *ctxt; +- OM_uint32 maj_status, min_status, ret_flags; +- struct sshbuf *server_blob = NULL; +- struct sshbuf *shared_secret = NULL; +- struct sshbuf *server_host_key_blob = NULL; ++ Gssctxt *gss = kex->gss; + struct sshbuf *empty = NULL; +- u_char *msg; +- int type = 0; +- int first = 1; ++ struct sshbuf *shared_secret = NULL; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t hashlen; +- u_char c; + int r; + +- /* Initialise our GSSAPI world */ +- ssh_gssapi_build_ctx(&ctxt); +- if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) +- == GSS_C_NO_OID) +- fatal("Couldn't identify host exchange"); +- +- if (ssh_gssapi_import_name(ctxt, kex->gss_host)) +- fatal("Couldn't import hostname"); +- +- if (kex->gss_client && +- ssh_gssapi_client_identity(ctxt, kex->gss_client)) +- fatal("Couldn't acquire client credentials"); +- +- /* Step 1 */ +- switch (kex->kex_type) { +- case KEX_GSS_GRP1_SHA1: +- case KEX_GSS_GRP14_SHA1: +- case KEX_GSS_GRP14_SHA256: +- case KEX_GSS_GRP16_SHA512: +- r = kex_dh_keypair(kex); +- break; +- case KEX_GSS_NISTP256_SHA256: +- r = kex_ecdh_keypair(kex); +- break; +- case KEX_GSS_C25519_SHA256: +- r = kex_c25519_keypair(kex); +- break; +- default: +- fatal_f("Unexpected KEX type %d", kex->kex_type); +- } +- if (r != 0) { +- ssh_gssapi_delete_ctx(&ctxt); +- return r; +- } +- +- token_ptr = GSS_C_NO_BUFFER; +- +- do { +- debug("Calling gss_init_sec_context"); +- +- maj_status = ssh_gssapi_init_ctx(ctxt, +- kex->gss_deleg_creds, token_ptr, &send_tok, +- &ret_flags); +- +- if (GSS_ERROR(maj_status)) { +- /* XXX Useles code: Missing send? */ +- if (send_tok.length != 0) { +- if ((r = sshpkt_start(ssh, +- SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- } +- fatal("gss_init_context failed"); +- } +- +- /* If we've got an old receive buffer get rid of it */ +- if (token_ptr != GSS_C_NO_BUFFER) +- gss_release_buffer(&min_status, &recv_tok); +- +- if (maj_status == GSS_S_COMPLETE) { +- /* If mutual state flag is not true, kex fails */ +- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) +- fatal("Mutual authentication failed"); +- +- /* If integ avail flag is not true kex fails */ +- if (!(ret_flags & GSS_C_INTEG_FLAG)) +- fatal("Integrity check failed"); +- } +- +- /* +- * If we have data to send, then the last message that we +- * received cannot have been a 'complete'. +- */ +- if (send_tok.length != 0) { +- if (first) { +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0 || +- (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) +- fatal("failed to construct packet: %s", ssh_err(r)); +- first = 0; +- } else { +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0) +- fatal("failed to construct packet: %s", ssh_err(r)); +- } +- if ((r = sshpkt_send(ssh)) != 0) +- fatal("failed to send packet: %s", ssh_err(r)); +- gss_release_buffer(&min_status, &send_tok); +- +- /* If we've sent them data, they should reply */ +- do { +- type = ssh_packet_read(ssh); +- if (type == SSH2_MSG_KEXGSS_HOSTKEY) { +- u_char *tmp = NULL; +- size_t tmp_len = 0; +- +- debug("Received KEXGSS_HOSTKEY"); +- if (server_host_key_blob) +- fatal("Server host key received more than once"); +- if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) +- fatal("Failed to read server host key: %s", ssh_err(r)); +- if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) +- fatal("sshbuf_from failed"); +- } +- } while (type == SSH2_MSG_KEXGSS_HOSTKEY); +- +- switch (type) { +- case SSH2_MSG_KEXGSS_CONTINUE: +- debug("Received GSSAPI_CONTINUE"); +- if (maj_status == GSS_S_COMPLETE) +- fatal("GSSAPI Continue received from server when complete"); +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("Failed to read token: %s", ssh_err(r)); +- break; +- case SSH2_MSG_KEXGSS_COMPLETE: +- debug("Received GSSAPI_COMPLETE"); +- if (msg_tok.value != NULL) +- fatal("Received GSSAPI_COMPLETE twice?"); +- if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || +- (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &msg_tok)) != 0) +- fatal("Failed to read message: %s", ssh_err(r)); +- +- /* Is there a token included? */ +- if ((r = sshpkt_get_u8(ssh, &c)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- if (c) { +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc( +- ssh, &recv_tok)) != 0) +- fatal("Failed to read token: %s", ssh_err(r)); +- /* If we're already complete - protocol error */ +- if (maj_status == GSS_S_COMPLETE) +- sshpkt_disconnect(ssh, "Protocol error: received token when complete"); +- } else { +- /* No token included */ +- if (maj_status != GSS_S_COMPLETE) +- sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); +- } +- if ((r = sshpkt_get_end(ssh)) != 0) { +- fatal("Expecting end of packet."); +- } +- break; +- case SSH2_MSG_KEXGSS_ERROR: +- debug("Received Error"); +- if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || +- (r = sshpkt_get_u32(ssh, &min_status)) != 0 || +- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || +- (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt_get failed: %s", ssh_err(r)); +- fatal("GSSAPI Error: \n%.400s", msg); +- default: +- sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", +- type); +- } +- token_ptr = &recv_tok; +- } else { +- /* No data, and not complete */ +- if (maj_status != GSS_S_COMPLETE) +- fatal("Not complete, and no token output"); +- } +- } while (maj_status & GSS_S_CONTINUE_NEEDED); +- + /* + * We _must_ have received a COMPLETE message in reply from the + * server, which will have set server_blob and msg_tok + */ + +- if (type != SSH2_MSG_KEXGSS_COMPLETE) +- fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); +- + /* compute shared secret */ + switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + case KEX_GSS_GRP14_SHA1: + case KEX_GSS_GRP14_SHA256: + case KEX_GSS_GRP16_SHA512: +- r = kex_dh_dec(kex, server_blob, &shared_secret); ++ r = kex_dh_dec(kex, gss->server_blob, &shared_secret); + break; + case KEX_GSS_C25519_SHA256: +- if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80) ++ if (sshbuf_ptr(gss->server_blob)[sshbuf_len(gss->server_blob)] & 0x80) + fatal("The received key has MSB of last octet set!"); +- r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ r = kex_c25519_dec(kex, gss->server_blob, &shared_secret); + break; + case KEX_GSS_NISTP256_SHA256: +- if (sshbuf_len(server_blob) != 65) +- fatal("The received NIST-P256 key did not match" +- "expected length (expected 65, got %zu)", sshbuf_len(server_blob)); ++ if (sshbuf_len(gss->server_blob) != 65) ++ fatal("The received NIST-P256 key did not match " ++ "expected length (expected 65, got %zu)", ++ sshbuf_len(gss->server_blob)); + +- if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) ++ if (sshbuf_ptr(gss->server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) + fatal("The received NIST-P256 key does not have first octet 0x04"); + +- r = kex_ecdh_dec(kex, server_blob, &shared_secret); ++ r = kex_ecdh_dec(kex, gss->server_blob, &shared_secret); + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; + } +- if (r != 0) ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } + + if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + + hashlen = sizeof(hash); +- if ((r = kex_gen_hash( +- kex->hash_alg, +- kex->client_version, +- kex->server_version, +- kex->my, +- kex->peer, +- (server_host_key_blob ? server_host_key_blob : empty), +- kex->client_pub, +- server_blob, +- shared_secret, +- hash, &hashlen)) != 0) ++ r = kex_gen_hash(kex->hash_alg, kex->client_version, ++ kex->server_version, kex->my, kex->peer, ++ (gss->server_host_key_blob ? gss->server_host_key_blob : empty), ++ kex->client_pub, gss->server_blob, shared_secret, ++ hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) + fatal_f("Unexpected KEX type %d", kex->kex_type); + +- gssbuf.value = hash; +- gssbuf.length = hashlen; ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; + + /* Verify that the hash matches the MIC we just got. */ +- if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(ssh_gssapi_checkmic(gss, &gss->buf, &gss->msg_tok))) + sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); + +- gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, &gss->msg_tok); + + if (kex->gss_deleg_creds) +- ssh_gssapi_credentials_updated(ctxt); ++ ssh_gssapi_credentials_updated(gss); + + if (gss_kex_context == NULL) +- gss_kex_context = ctxt; ++ gss_kex_context = gss; + else +- ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + ++ if (kex->gss != NULL) { ++ sshbuf_free(gss->server_host_key_blob); ++ gss->server_host_key_blob = NULL; ++ sshbuf_free(gss->server_blob); ++ gss->server_blob = NULL; ++ } + out: +- explicit_bzero(hash, sizeof(hash)); + explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); +- sshbuf_free(empty); +- sshbuf_free(server_host_key_blob); +- sshbuf_free(server_blob); ++ explicit_bzero(hash, sizeof(hash)); + sshbuf_free(shared_secret); + sshbuf_free(kex->client_pub); + kex->client_pub = NULL; + return r; + } + ++static int ++kexgss_init_ctx(struct ssh *ssh, ++ gss_buffer_desc *token_ptr) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags; ++ int r; ++ ++ debug("Calling gss_init_sec_context"); ++ ++ gss->major = ssh_gssapi_init_ctx(gss, kex->gss_deleg_creds, ++ token_ptr, &send_tok, &ret_flags); ++ ++ if (GSS_ERROR(gss->major)) { ++ /* XXX Useless code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&gss->minor, token_ptr); ++ ++ if (gss->major == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (gss->first) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ gss->first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("failed to send packet: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, &input_kexgss_hostkey); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgss_continue); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, &input_kexgss_complete); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, &input_kexgss_error); ++ return 0; ++ } ++ /* No data, and not complete */ ++ if (gss->major != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgss_init_ctx(ssh, token_ptr); ++ ++ return kexgss_final(ssh); ++} ++ + int +-kexgssgex_client(struct ssh *ssh) ++kexgss_client(struct ssh *ssh) + { + struct kex *kex = ssh->kex; +- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, +- recv_tok = GSS_C_EMPTY_BUFFER, gssbuf, +- msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; +- Gssctxt *ctxt; +- OM_uint32 maj_status, min_status, ret_flags; +- struct sshbuf *shared_secret = NULL; +- BIGNUM *p = NULL; +- BIGNUM *g = NULL; +- struct sshbuf *buf = NULL; +- struct sshbuf *server_host_key_blob = NULL; +- struct sshbuf *server_blob = NULL; +- BIGNUM *dh_server_pub = NULL; +- u_char *msg; +- int type = 0; +- int first = 1; +- u_char hash[SSH_DIGEST_MAX_LENGTH]; +- size_t hashlen; +- const BIGNUM *pub_key, *dh_p, *dh_g; +- int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; +- struct sshbuf *empty = NULL; +- u_char c; + int r; + + /* Initialise our GSSAPI world */ +- ssh_gssapi_build_ctx(&ctxt); +- if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) +- == GSS_C_NO_OID) ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (ssh_gssapi_id_kex(kex->gss, kex->name, kex->kex_type) == GSS_C_NO_OID) + fatal("Couldn't identify host exchange"); + +- if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ if (ssh_gssapi_import_name(kex->gss, kex->gss_host)) + fatal("Couldn't import hostname"); + + if (kex->gss_client && +- ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ ssh_gssapi_client_identity(kex->gss, kex->gss_client)) + fatal("Couldn't acquire client credentials"); + +- debug("Doing group exchange"); +- nbits = dh_estimate(kex->dh_need * 8); ++ /* Step 1 */ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_keypair(kex); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_keypair(kex); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_keypair(kex); ++ break; ++ default: ++ fatal_f("Unexpected KEX type %d", kex->kex_type); ++ } ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return r; ++ } ++ return kexgss_init_ctx(ssh, GSS_C_NO_BUFFER); ++} + +- kex->min = DH_GRP_MIN; +- kex->max = DH_GRP_MAX; +- kex->nbits = nbits; +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || +- (r = sshpkt_put_u32(ssh, min)) != 0 || +- (r = sshpkt_put_u32(ssh, nbits)) != 0 || +- (r = sshpkt_put_u32(ssh, max)) != 0 || +- (r = sshpkt_send(ssh)) != 0) +- fatal("Failed to construct a packet: %s", ssh_err(r)); ++static int ++input_kexgss_hostkey(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ u_char *tmp = NULL; ++ size_t tmp_len = 0; ++ int r; ++ ++ debug("Received KEXGSS_HOSTKEY"); ++ if (gss->server_host_key_blob) ++ fatal("Server host key received more than once"); ++ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) ++ fatal("Failed to read server host key: %s", ssh_err(r)); ++ if ((gss->server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) ++ fatal("sshbuf_from failed"); ++ return 0; ++} + +- if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0) +- fatal("Error: %s", ssh_err(r)); ++static int ++input_kexgss_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ int r; + +- if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || +- (r = sshpkt_get_bignum2(ssh, &g)) != 0 || ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_CONTINUE"); ++ if (gss->major == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) +- fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); ++ fatal("Failed to read token: %s", ssh_err(r)); ++ if (!(gss->major & GSS_S_CONTINUE_NEEDED)) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ return kexgss_init_ctx(ssh, &recv_tok); ++} + +- if (BN_num_bits(p) < min || BN_num_bits(p) > max) +- fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", +- min, BN_num_bits(p), max); ++static int ++input_kexgss_complete(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ u_char c; ++ int r; + +- if ((kex->dh = dh_new_group(g, p)) == NULL) +- fatal("dn_new_group() failed"); +- p = g = NULL; /* belong to kex->dh now */ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_COMPLETE"); ++ if (gss->msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &gss->server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &gss->msg_tok)) != 0) ++ fatal("Failed to read message: %s", ssh_err(r)); ++ ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (gss->major == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ if (gss->major != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ if ((r = sshpkt_get_end(ssh)) != 0) ++ fatal("Expecting end of packet."); + +- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) +- goto out; +- DH_get0_key(kex->dh, &pub_key, NULL); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgss_init_ctx(ssh, &recv_tok); + +- token_ptr = GSS_C_NO_BUFFER; ++ return kexgss_final(ssh); ++} + +- do { +- /* Step 2 - call GSS_Init_sec_context() */ +- debug("Calling gss_init_sec_context"); +- +- maj_status = ssh_gssapi_init_ctx(ctxt, +- kex->gss_deleg_creds, token_ptr, &send_tok, +- &ret_flags); +- +- if (GSS_ERROR(maj_status)) { +- /* XXX Useles code: Missing send? */ +- if (send_tok.length != 0) { +- if ((r = sshpkt_start(ssh, +- SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- } +- fatal("gss_init_context failed"); +- } ++static int ++input_kexgss_error(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ u_char *msg; ++ int r; + +- /* If we've got an old receive buffer get rid of it */ +- if (token_ptr != GSS_C_NO_BUFFER) +- gss_release_buffer(&min_status, &recv_tok); +- +- if (maj_status == GSS_S_COMPLETE) { +- /* If mutual state flag is not true, kex fails */ +- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) +- fatal("Mutual authentication failed"); +- +- /* If integ avail flag is not true kex fails */ +- if (!(ret_flags & GSS_C_INTEG_FLAG)) +- fatal("Integrity check failed"); +- } ++ debug("Received Error"); ++ if ((r = sshpkt_get_u32(ssh, &gss->major)) != 0 || ++ (r = sshpkt_get_u32(ssh, &gss->minor)) != 0 || ++ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || ++ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt_get failed: %s", ssh_err(r)); ++ fatal("GSSAPI Error: \n%.400s", msg); ++ return 0; ++} + +- /* +- * If we have data to send, then the last message that we +- * received cannot have been a 'complete'. +- */ +- if (send_tok.length != 0) { +- if (first) { +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, +- send_tok.length)) != 0 || +- (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- first = 0; +- } else { +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh,send_tok.value, +- send_tok.length)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- } +- if ((r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt_send failed: %s", ssh_err(r)); +- gss_release_buffer(&min_status, &send_tok); +- +- /* If we've sent them data, they should reply */ +- do { +- type = ssh_packet_read(ssh); +- if (type == SSH2_MSG_KEXGSS_HOSTKEY) { +- u_char *tmp = NULL; +- size_t tmp_len = 0; +- +- debug("Received KEXGSS_HOSTKEY"); +- if (server_host_key_blob) +- fatal("Server host key received more than once"); +- if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) +- fatal("sshbuf_from failed"); +- } +- } while (type == SSH2_MSG_KEXGSS_HOSTKEY); +- +- switch (type) { +- case SSH2_MSG_KEXGSS_CONTINUE: +- debug("Received GSSAPI_CONTINUE"); +- if (maj_status == GSS_S_COMPLETE) +- fatal("GSSAPI Continue received from server when complete"); +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- break; +- case SSH2_MSG_KEXGSS_COMPLETE: +- debug("Received GSSAPI_COMPLETE"); +- if (msg_tok.value != NULL) +- fatal("Received GSSAPI_COMPLETE twice?"); +- if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || +- (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &msg_tok)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- +- /* Is there a token included? */ +- if ((r = sshpkt_get_u8(ssh, &c)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- if (c) { +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc( +- ssh, &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- /* If we're already complete - protocol error */ +- if (maj_status == GSS_S_COMPLETE) +- sshpkt_disconnect(ssh, "Protocol error: received token when complete"); +- } else { +- /* No token included */ +- if (maj_status != GSS_S_COMPLETE) +- sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); +- } +- break; +- case SSH2_MSG_KEXGSS_ERROR: +- debug("Received Error"); +- if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || +- (r = sshpkt_get_u32(ssh, &min_status)) != 0 || +- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || +- (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- fatal("GSSAPI Error: \n%.400s", msg); +- default: +- sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", +- type); +- } +- token_ptr = &recv_tok; +- } else { +- /* No data, and not complete */ +- if (maj_status != GSS_S_COMPLETE) +- fatal("Not complete, and no token output"); +- } +- } while (maj_status & GSS_S_CONTINUE_NEEDED); ++/*******************************************************/ ++/******************** KEXGSSGEX ************************/ ++/*******************************************************/ ++ ++int ++kexgssgex_client(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ int r; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (ssh_gssapi_id_kex(kex->gss, kex->name, kex->kex_type) == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ if (ssh_gssapi_import_name(kex->gss, kex->gss_host)) ++ fatal("Couldn't import hostname"); ++ ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(kex->gss, kex->gss_client)) ++ fatal("Couldn't acquire client credentials"); ++ ++ debug("Doing group exchange"); ++ kex->min = DH_GRP_MIN; ++ kex->max = DH_GRP_MAX; ++ kex->nbits = dh_estimate(kex->dh_need * 8); ++ ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->min)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->max)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("Failed to construct a packet: %s", ssh_err(r)); ++ ++ debug("Wait SSH2_MSG_KEXGSS_GROUP"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUP, &input_kexgssgex_group); ++ return 0; ++} ++ ++static int ++kexgssgex_final(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ struct sshbuf *buf = NULL; ++ struct sshbuf *empty = NULL; ++ struct sshbuf *shared_secret = NULL; ++ BIGNUM *dh_server_pub = NULL; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ int r; + + /* + * We _must_ have received a COMPLETE message in reply from the +- * server, which will have set dh_server_pub and msg_tok ++ * server, which will have set server_blob and msg_tok + */ + +- if (type != SSH2_MSG_KEXGSS_COMPLETE) +- fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); +- + /* 7. C verifies that the key Q_S is valid */ + /* 8. C computes shared secret */ + if ((buf = sshbuf_new()) == NULL || +- (r = sshbuf_put_stringb(buf, server_blob)) != 0 || +- (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) ++ (r = sshbuf_put_stringb(buf, gss->server_blob)) != 0 || ++ (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } + sshbuf_free(buf); + buf = NULL; + + if ((shared_secret = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + +- if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) ++ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } ++ + if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + ++ DH_get0_key(kex->dh, &pub_key, NULL); + DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); + hashlen = sizeof(hash); +- if ((r = kexgex_hash( +- kex->hash_alg, +- kex->client_version, +- kex->server_version, +- kex->my, +- kex->peer, +- (server_host_key_blob ? server_host_key_blob : empty), +- kex->min, kex->nbits, kex->max, +- dh_p, dh_g, +- pub_key, +- dh_server_pub, +- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), +- hash, &hashlen)) != 0) ++ r = kexgex_hash(kex->hash_alg, kex->client_version, ++ kex->server_version, kex->my, kex->peer, ++ (gss->server_host_key_blob ? gss->server_host_key_blob : empty), ++ kex->min, kex->nbits, kex->max, dh_p, dh_g, pub_key, ++ dh_server_pub, sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), ++ hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) + fatal("Failed to calculate hash: %s", ssh_err(r)); + +- gssbuf.value = hash; +- gssbuf.length = hashlen; ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; + + /* Verify that the hash matches the MIC we just got. */ +- if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(ssh_gssapi_checkmic(gss, &gss->buf, &gss->msg_tok))) + sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); + +- gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, &gss->msg_tok); + + if (kex->gss_deleg_creds) +- ssh_gssapi_credentials_updated(ctxt); ++ ssh_gssapi_credentials_updated(gss); + + if (gss_kex_context == NULL) +- gss_kex_context = ctxt; ++ gss_kex_context = gss; + else +- ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + + /* Finally derive the keys and send them */ + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); ++ ++ if (kex->gss != NULL) { ++ sshbuf_free(gss->server_host_key_blob); ++ gss->server_host_key_blob = NULL; ++ sshbuf_free(gss->server_blob); ++ gss->server_blob = NULL; ++ } + out: +- sshbuf_free(buf); +- sshbuf_free(server_blob); +- sshbuf_free(empty); + explicit_bzero(hash, sizeof(hash)); + DH_free(kex->dh); + kex->dh = NULL; + BN_clear_free(dh_server_pub); + sshbuf_free(shared_secret); +- sshbuf_free(server_host_key_blob); + return r; + } + ++static int ++kexgssgex_init_ctx(struct ssh *ssh, ++ gss_buffer_desc *token_ptr) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ const BIGNUM *pub_key; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags; ++ int r; ++ ++ /* Step 2 - call GSS_Init_sec_context() */ ++ debug("Calling gss_init_sec_context"); ++ ++ gss->major = ssh_gssapi_init_ctx(gss, kex->gss_deleg_creds, ++ token_ptr, &send_tok, &ret_flags); ++ ++ if (GSS_ERROR(gss->major)) { ++ /* XXX Useless code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&gss->minor, token_ptr); ++ ++ if (gss->major == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (gss->first) { ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ gss->first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("failed to send packet: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, &input_kexgss_hostkey); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgssgex_continue); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, &input_kexgssgex_complete); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, &input_kexgss_error); ++ return 0; ++ } ++ /* No data, and not complete */ ++ if (gss->major != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgssgex_init_ctx(ssh, token_ptr); ++ ++ return kexgssgex_final(ssh); ++} ++ ++static int ++input_kexgssgex_group(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ BIGNUM *p = NULL; ++ BIGNUM *g = NULL; ++ int r; ++ ++ debug("Received SSH2_MSG_KEXGSS_GROUP"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUP, NULL); ++ ++ if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &g)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); ++ ++ if (BN_num_bits(p) < kex->min || BN_num_bits(p) > kex->max) ++ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", ++ kex->min, BN_num_bits(p), kex->max); ++ ++ if ((kex->dh = dh_new_group(g, p)) == NULL) ++ fatal("dn_new_group() failed"); ++ p = g = NULL; /* belong to kex->dh now */ ++ ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ return r; ++ } ++ ++ return kexgssgex_init_ctx(ssh, GSS_C_NO_BUFFER); ++} ++ ++static int ++input_kexgssgex_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ int r; ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_CONTINUE"); ++ if (gss->major == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ if (!(gss->major & GSS_S_CONTINUE_NEEDED)) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ return kexgssgex_init_ctx(ssh, &recv_tok); ++} ++ ++static int ++input_kexgssgex_complete(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ u_char c; ++ int r; ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_COMPLETE"); ++ if (gss->msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &gss->server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &gss->msg_tok)) != 0) ++ fatal("Failed to read message: %s", ssh_err(r)); ++ ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (gss->major == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ if (gss->major != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ if ((r = sshpkt_get_end(ssh)) != 0) ++ fatal("Expecting end of packet."); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgssgex_init_ctx(ssh, &recv_tok); ++ ++ return kexgssgex_final(ssh); ++} ++ + #endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ +diff --color -ruNp a/kexgsss.c b/kexgsss.c +--- a/kexgsss.c 2024-05-16 15:49:43.820407648 +0200 ++++ b/kexgsss.c 2024-07-02 16:29:05.744790839 +0200 +@@ -50,33 +50,18 @@ + + extern ServerOptions options; + ++static int input_kexgss_init(int, u_int32_t, struct ssh *); ++static int input_kexgss_continue(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_groupreq(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_init(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_continue(int, u_int32_t, struct ssh *); ++ + int + kexgss_server(struct ssh *ssh) + { + struct kex *kex = ssh->kex; +- OM_uint32 maj_status, min_status; +- +- /* +- * Some GSSAPI implementations use the input value of ret_flags (an +- * output variable) as a means of triggering mechanism specific +- * features. Initializing it to zero avoids inadvertently +- * activating this non-standard behaviour. +- */ +- +- OM_uint32 ret_flags = 0; +- gss_buffer_desc gssbuf = {0, NULL}, recv_tok, msg_tok; +- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; +- Gssctxt *ctxt = NULL; +- struct sshbuf *shared_secret = NULL; +- struct sshbuf *client_pubkey = NULL; +- struct sshbuf *server_pubkey = NULL; +- struct sshbuf *empty = sshbuf_new(); +- int type = 0; + gss_OID oid; + char *mechs; +- u_char hash[SSH_DIGEST_MAX_LENGTH]; +- size_t hashlen; +- int r; + + /* Initialise GSSAPI */ + +@@ -92,135 +77,91 @@ kexgss_server(struct ssh *ssh) + debug2_f("Identifying %s", kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) +- fatal("Unknown gssapi mechanism"); ++ fatal("Unknown gssapi mechanism"); + + debug2_f("Acquiring credentials"); + +- if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&kex->gss, oid)))) + fatal("Unable to acquire credentials for the server"); + +- do { +- debug("Wait SSH2_MSG_KEXGSS_INIT"); +- type = ssh_packet_read(ssh); +- switch(type) { +- case SSH2_MSG_KEXGSS_INIT: +- if (gssbuf.value != NULL) +- fatal("Received KEXGSS_INIT after initialising"); +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (kex->gss == NULL) ++ fatal("Unable to allocate memory for gss context"); ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, &input_kexgss_init); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgss_continue); ++ debug("Wait SSH2_MSG_KEXGSS_INIT"); ++ return 0; ++} + +- switch (kex->kex_type) { +- case KEX_GSS_GRP1_SHA1: +- case KEX_GSS_GRP14_SHA1: +- case KEX_GSS_GRP14_SHA256: +- case KEX_GSS_GRP16_SHA512: +- r = kex_dh_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); +- break; +- case KEX_GSS_NISTP256_SHA256: +- r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); +- break; +- case KEX_GSS_C25519_SHA256: +- r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); +- break; +- default: +- fatal_f("Unexpected KEX type %d", kex->kex_type); +- } +- if (r != 0) +- goto out; +- +- /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ +- +- /* Calculate the hash early so we can free the +- * client_pubkey, which has reference to the parent +- * buffer state->incoming_packet +- */ +- hashlen = sizeof(hash); +- if ((r = kex_gen_hash( +- kex->hash_alg, +- kex->client_version, +- kex->server_version, +- kex->peer, +- kex->my, +- empty, +- client_pubkey, +- server_pubkey, +- shared_secret, +- hash, &hashlen)) != 0) +- goto out; +- +- gssbuf.value = hash; +- gssbuf.length = hashlen; +- +- sshbuf_free(client_pubkey); +- client_pubkey = NULL; +- +- break; +- case SSH2_MSG_KEXGSS_CONTINUE: +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- break; +- default: +- sshpkt_disconnect(ssh, +- "Protocol error: didn't expect packet type %d", +- type); +- } ++static inline void ++kexgss_accept_ctx(struct ssh *ssh, ++ gss_buffer_desc *recv_tok, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ int r; + +- maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, +- &send_tok, &ret_flags)); ++ gss->major = PRIVSEP(ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags)); ++ gss_release_buffer(&gss->minor, recv_tok); + +- gss_release_buffer(&min_status, &recv_tok); ++ if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) ++ fatal("Zero length token output when incomplete"); + +- if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) +- fatal("Zero length token output when incomplete"); ++ if (gss->buf.value == NULL) ++ fatal("No client public key"); + +- if (gssbuf.value == NULL) +- fatal("No client public key"); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, send_tok); ++ } ++} + +- if (maj_status & GSS_S_CONTINUE_NEEDED) { +- debug("Sending GSSAPI_CONTINUE"); +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || +- (r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- gss_release_buffer(&min_status, &send_tok); +- } +- } while (maj_status & GSS_S_CONTINUE_NEEDED); ++static inline int ++kexgss_final(struct ssh *ssh, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc msg_tok; ++ int r; ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); + +- if (GSS_ERROR(maj_status)) { +- if (send_tok.length > 0) { ++ if (GSS_ERROR(gss->major)) { ++ if (send_tok->length > 0) { + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } + fatal("accept_ctx died"); + } + +- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ if (!(*ret_flags & GSS_C_MUTUAL_FLAG)) + fatal("Mutual Authentication flag wasn't set"); + +- if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ if (!(*ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + +- if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(gss, &gss->buf, &msg_tok)))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || +- (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || ++ (r = sshpkt_put_stringb(ssh, gss->server_pubkey)) != 0 || + (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + +- if (send_tok.length != 0) { ++ if (send_tok->length != 0) { + if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } else { + if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ +@@ -229,59 +170,139 @@ kexgss_server(struct ssh *ssh) + if ((r = sshpkt_send(ssh)) != 0) + fatal("sshpkt_send failed: %s", ssh_err(r)); + +- gss_release_buffer(&min_status, &send_tok); +- gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, send_tok); ++ gss_release_buffer(&gss->minor, &msg_tok); + + if (gss_kex_context == NULL) +- gss_kex_context = ctxt; ++ gss_kex_context = gss; + else +- ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + +- if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ if ((r = kex_derive_keys(ssh, gss->hash, gss->hashlen, gss->shared_secret)) == 0) + r = kex_send_newkeys(ssh); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); +-out: +- sshbuf_free(empty); +- explicit_bzero(hash, sizeof(hash)); +- sshbuf_free(shared_secret); +- sshbuf_free(client_pubkey); +- sshbuf_free(server_pubkey); ++ ++ if (kex->gss != NULL) { ++ explicit_bzero(gss->hash, sizeof(gss->hash)); ++ sshbuf_free(gss->shared_secret); ++ gss->shared_secret = NULL; ++ sshbuf_free(gss->server_pubkey); ++ gss->server_pubkey = NULL; ++ } + return r; + } + +-int +-kexgssgex_server(struct ssh *ssh) ++static int ++input_kexgss_init(int type, ++ u_int32_t seq, ++ struct ssh *ssh) + { + struct kex *kex = ssh->kex; +- OM_uint32 maj_status, min_status; ++ Gssctxt *gss = kex->gss; ++ struct sshbuf *empty; ++ struct sshbuf *client_pubkey = NULL; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ debug("SSH2_MSG_KEXGSS_INIT received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); + +- /* +- * Some GSSAPI implementations use the input value of ret_flags (an +- * output variable) as a means of triggering mechanism specific +- * features. Initializing it to zero avoids inadvertently +- * activating this non-standard behaviour. ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ default: ++ fatal_f("Unexpected KEX type %d", kex->kex_type); ++ } ++ if (r != 0) { ++ sshbuf_free(client_pubkey); ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return r; ++ } ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ ++ if ((empty = sshbuf_new()) == NULL) { ++ sshbuf_free(client_pubkey); ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ /* Calculate the hash early so we can free the ++ * client_pubkey, which has reference to the parent ++ * buffer state->incoming_packet + */ ++ gss->hashlen = sizeof(gss->hash); ++ r = kex_gen_hash(kex->hash_alg, kex->client_version, kex->server_version, ++ kex->peer, kex->my, empty, client_pubkey, gss->server_pubkey, ++ gss->shared_secret, gss->hash, &gss->hashlen); ++ sshbuf_free(empty); ++ sshbuf_free(client_pubkey); ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return r; ++ } ++ ++ gss->buf.value = gss->hash; ++ gss->buf.length = gss->hashlen; ++ ++ kexgss_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; + ++ return kexgss_final(ssh, &send_tok, &ret_flags); ++} ++ ++static int ++input_kexgss_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; + OM_uint32 ret_flags = 0; +- gss_buffer_desc gssbuf, recv_tok, msg_tok; +- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; +- Gssctxt *ctxt = NULL; +- struct sshbuf *shared_secret = NULL; +- int type = 0; ++ int r; ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ kexgss_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgss_final(ssh, &send_tok, &ret_flags); ++} ++ ++/*******************************************************/ ++/******************** KEXGSSGEX ************************/ ++/*******************************************************/ ++ ++int ++kexgssgex_server(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; + gss_OID oid; + char *mechs; +- u_char hash[SSH_DIGEST_MAX_LENGTH]; +- size_t hashlen; +- BIGNUM *dh_client_pub = NULL; +- const BIGNUM *pub_key, *dh_p, *dh_g; +- int min = -1, max = -1, nbits = -1; +- int cmin = -1, cmax = -1; /* client proposal */ +- struct sshbuf *empty = sshbuf_new(); +- int r; + + /* Initialise GSSAPI */ + +@@ -289,153 +310,125 @@ kexgssgex_server(struct ssh *ssh) + * in the GSSAPI code are no longer available. This kludges them back + * into life + */ +- if (!ssh_gssapi_oid_table_ok()) +- if ((mechs = ssh_gssapi_server_mechanisms())) +- free(mechs); ++ if (!ssh_gssapi_oid_table_ok()) { ++ mechs = ssh_gssapi_server_mechanisms(); ++ free(mechs); ++ } + + debug2_f("Identifying %s", kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) +- fatal("Unknown gssapi mechanism"); ++ fatal("Unknown gssapi mechanism"); + + debug2_f("Acquiring credentials"); + +- if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&kex->gss, oid)))) + fatal("Unable to acquire credentials for the server"); + +- /* 5. S generates an ephemeral key pair (do the allocations early) */ +- debug("Doing group exchange"); +- ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUPREQ); +- /* store client proposal to provide valid signature */ +- if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || +- (r = sshpkt_get_u32(ssh, &nbits)) != 0 || +- (r = sshpkt_get_u32(ssh, &cmax)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- kex->nbits = nbits; +- kex->min = cmin; +- kex->max = cmax; +- min = MAX(DH_GRP_MIN, cmin); +- max = MIN(DH_GRP_MAX, cmax); +- nbits = MAXIMUM(DH_GRP_MIN, nbits); +- nbits = MINIMUM(DH_GRP_MAX, nbits); +- if (max < min || nbits < min || max < nbits) +- fatal("GSS_GEX, bad parameters: %d !< %d !< %d", +- min, nbits, max); +- kex->dh = PRIVSEP(choose_dh(min, nbits, max)); +- if (kex->dh == NULL) { +- sshpkt_disconnect(ssh, "Protocol error: no matching group found"); +- fatal("Protocol error: no matching group found"); +- } ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (kex->gss == NULL) ++ fatal("Unable to allocate memory for gss context"); + +- DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 || +- (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || +- (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || +- (r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- +- if ((r = ssh_packet_write_wait(ssh)) != 0) +- fatal("ssh_packet_write_wait: %s", ssh_err(r)); +- +- /* Compute our exchange value in parallel with the client */ +- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) +- goto out; ++ debug("Doing group exchange"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUPREQ, &input_kexgssgex_groupreq); ++ return 0; ++} + +- do { +- debug("Wait SSH2_MSG_GSSAPI_INIT"); +- type = ssh_packet_read(ssh); +- switch(type) { +- case SSH2_MSG_KEXGSS_INIT: +- if (dh_client_pub != NULL) +- fatal("Received KEXGSS_INIT after initialising"); +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); ++static inline void ++kexgssgex_accept_ctx(struct ssh *ssh, ++ gss_buffer_desc *recv_tok, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ int r; + +- /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ +- break; +- case SSH2_MSG_KEXGSS_CONTINUE: +- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, +- &recv_tok)) != 0 || +- (r = sshpkt_get_end(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- break; +- default: +- sshpkt_disconnect(ssh, +- "Protocol error: didn't expect packet type %d", +- type); +- } ++ gss->major = PRIVSEP(ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags)); ++ gss_release_buffer(&gss->minor, recv_tok); + +- maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, +- &send_tok, &ret_flags)); ++ if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) ++ fatal("Zero length token output when incomplete"); + +- gss_release_buffer(&min_status, &recv_tok); ++ if (gss->dh_client_pub == NULL) ++ fatal("No client public key"); + +- if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) +- fatal("Zero length token output when incomplete"); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, send_tok); ++ } ++} + +- if (dh_client_pub == NULL) +- fatal("No client public key"); ++static inline int ++kexgssgex_final(struct ssh *ssh, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc msg_tok; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ struct sshbuf *shared_secret = NULL; ++ struct sshbuf *empty = NULL; ++ int r; + +- if (maj_status & GSS_S_CONTINUE_NEEDED) { +- debug("Sending GSSAPI_CONTINUE"); +- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || +- (r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); +- gss_release_buffer(&min_status, &send_tok); +- } +- } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); + +- if (GSS_ERROR(maj_status)) { +- if (send_tok.length > 0) { ++ if (GSS_ERROR(gss->major)) { ++ if (send_tok->length > 0) { + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } + fatal("accept_ctx died"); + } + +- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ if (!(*ret_flags & GSS_C_MUTUAL_FLAG)) + fatal("Mutual Authentication flag wasn't set"); + +- if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ if (!(*ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + + /* calculate shared secret */ +- if ((shared_secret = sshbuf_new()) == NULL) { ++ shared_secret = sshbuf_new(); ++ if (shared_secret == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) ++ if ((r = kex_dh_compute_key(kex, gss->dh_client_pub, shared_secret)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } ++ ++ if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + + DH_get0_key(kex->dh, &pub_key, NULL); + DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); + hashlen = sizeof(hash); +- if ((r = kexgex_hash( +- kex->hash_alg, +- kex->client_version, +- kex->server_version, +- kex->peer, +- kex->my, +- empty, +- cmin, nbits, cmax, +- dh_p, dh_g, +- dh_client_pub, +- pub_key, +- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), +- hash, &hashlen)) != 0) ++ r = kexgex_hash(kex->hash_alg, kex->client_version, kex->server_version, ++ kex->peer, kex->my, empty, kex->min, kex->nbits, kex->max, dh_p, dh_g, ++ gss->dh_client_pub, pub_key, sshbuf_ptr(shared_secret), ++ sshbuf_len(shared_secret), hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) + fatal("kexgex_hash failed: %s", ssh_err(r)); + +- gssbuf.value = hash; +- gssbuf.length = hashlen; ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; + +- if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(gss, &gss->buf, &msg_tok)))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || +@@ -443,24 +436,24 @@ kexgssgex_server(struct ssh *ssh) + (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + +- if (send_tok.length != 0) { ++ if (send_tok->length != 0) { + if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ +- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } else { + if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ + fatal("sshpkt failed: %s", ssh_err(r)); + } + if ((r = sshpkt_send(ssh)) != 0) +- fatal("sshpkt failed: %s", ssh_err(r)); ++ fatal("sshpkt_send failed: %s", ssh_err(r)); + +- gss_release_buffer(&min_status, &send_tok); +- gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, send_tok); ++ gss_release_buffer(&gss->minor, &msg_tok); + + if (gss_kex_context == NULL) +- gss_kex_context = ctxt; ++ gss_kex_context = gss; + else +- ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + + /* Finally derive the keys and send them */ + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) +@@ -470,13 +463,128 @@ kexgssgex_server(struct ssh *ssh) + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); ++ ++ if (kex->gss != NULL) ++ BN_clear_free(gss->dh_client_pub); ++ + out: +- sshbuf_free(empty); + explicit_bzero(hash, sizeof(hash)); + DH_free(kex->dh); + kex->dh = NULL; +- BN_clear_free(dh_client_pub); + sshbuf_free(shared_secret); + return r; + } ++ ++static int ++input_kexgssgex_groupreq(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ const BIGNUM *dh_p, *dh_g; ++ int min = -1, max = -1, nbits = -1; ++ int cmin = -1, cmax = -1; /* client proposal */ ++ int r; ++ ++ /* 5. S generates an ephemeral key pair (do the allocations early) */ ++ ++ debug("SSH2_MSG_KEXGSS_GROUPREQ received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUPREQ, NULL); ++ ++ /* store client proposal to provide valid signature */ ++ if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || ++ (r = sshpkt_get_u32(ssh, &nbits)) != 0 || ++ (r = sshpkt_get_u32(ssh, &cmax)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ kex->nbits = nbits; ++ kex->min = cmin; ++ kex->max = cmax; ++ min = MAX(DH_GRP_MIN, cmin); ++ max = MIN(DH_GRP_MAX, cmax); ++ nbits = MAXIMUM(DH_GRP_MIN, nbits); ++ nbits = MINIMUM(DH_GRP_MAX, nbits); ++ ++ if (max < min || nbits < min || max < nbits) ++ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", min, nbits, max); ++ ++ kex->dh = PRIVSEP(choose_dh(min, nbits, max)); ++ if (kex->dh == NULL) { ++ sshpkt_disconnect(ssh, "Protocol error: no matching group found"); ++ fatal("Protocol error: no matching group found"); ++ } ++ ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ if ((r = ssh_packet_write_wait(ssh)) != 0) ++ fatal("ssh_packet_write_wait: %s", ssh_err(r)); ++ ++ /* Compute our exchange value in parallel with the client */ ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ return r; ++ } ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, &input_kexgssgex_init); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgssgex_continue); ++ debug("Wait SSH2_MSG_KEXGSS_INIT"); ++ return 0; ++} ++ ++static int ++input_kexgssgex_init(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ debug("SSH2_MSG_KEXGSS_INIT received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &gss->dh_client_pub)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ ++ kexgssgex_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgssgex_final(ssh, &send_tok, &ret_flags); ++} ++ ++static int ++input_kexgssgex_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ kexgssgex_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgssgex_final(ssh, &send_tok, &ret_flags); ++} ++ + #endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ +diff --color -ruNp a/kex.h b/kex.h +--- a/kex.h 2024-05-16 15:49:43.986410812 +0200 ++++ b/kex.h 2024-06-18 12:19:48.580347469 +0200 +@@ -29,6 +29,10 @@ + #include "mac.h" + #include "crypto_api.h" + ++#ifdef GSSAPI ++# include "ssh-gss.h" /* Gssctxt */ ++#endif ++ + #ifdef WITH_OPENSSL + # include + # include +@@ -177,6 +181,7 @@ struct kex { + int hash_alg; + int ec_nid; + #ifdef GSSAPI ++ Gssctxt *gss; + int gss_deleg_creds; + int gss_trust_dns; + char *gss_host; +diff --color -ruNp a/ssh-gss.h b/ssh-gss.h +--- a/ssh-gss.h 2024-05-16 15:49:43.837407972 +0200 ++++ b/ssh-gss.h 2024-06-27 14:12:48.659866937 +0200 +@@ -88,6 +88,8 @@ extern char **k5users_allowed_cmds; + KEX_GSS_GRP14_SHA1_ID "," \ + KEX_GSS_GEX_SHA1_ID + ++#include "digest.h" /* SSH_DIGEST_MAX_LENGTH */ ++ + typedef struct { + char *filename; + char *envvar; +@@ -127,6 +129,16 @@ typedef struct { + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ + gss_cred_id_t client_creds; /* both */ ++ struct sshbuf *shared_secret; /* both */ ++ struct sshbuf *server_pubkey; /* server */ ++ struct sshbuf *server_blob; /* client */ ++ struct sshbuf *server_host_key_blob; /* client */ ++ gss_buffer_desc msg_tok; /* client */ ++ gss_buffer_desc buf; /* both */ ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; /* both */ ++ size_t hashlen; /* both */ ++ int first; /* client */ ++ BIGNUM *dh_client_pub; /* server (gex) */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; diff --git a/openssh.spec b/openssh.spec index 5195f39..08b1b4a 100644 --- a/openssh.spec +++ b/openssh.spec @@ -156,7 +156,8 @@ Patch802: openssh-6.6p1-GSSAPIEnablek5users.patch Patch804: openssh-7.7p1-gssapi-new-unique.patch # Respect k5login_directory option in krk5.conf (#1328243) Patch805: openssh-7.2p2-k5login_directory.patch - +# Rewriting OpenSSH GSS KEX to use new packet API +Patch806: openssh-9.6p1-gsskex-new-api.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 Patch901: openssh-6.6p1-kuserok.patch @@ -396,6 +397,7 @@ popd %patch -P 801 -p1 -b .force_krb %patch -P 804 -p1 -b .ccache_name %patch -P 805 -p1 -b .k5login +%patch -P 806 -p1 -b .gsskex-new-api # %patch -P 901 -p1 -b .kuserok %patch -P 906 -p1 -b .fromto-remote From fe837a30149b62c7b36452846dbc0da6254d1dfa Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 18 Jul 2024 21:00:36 +0000 Subject: [PATCH 24/80] Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild --- openssh.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 08b1b4a..fc82b78 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.13 +Release: %{openssh_rel}%{?dist}.14 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -312,7 +312,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.13 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.14 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -751,6 +751,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Thu Jul 18 2024 Fedora Release Engineering - 9.6p1-1.14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + * Tue Jul 02 2024 Dmitry Belyavskiy - 9.6p1-1.13 - rebuilt From 31a40d987fdaac1910eefd18acb25bf2b6a2b8f5 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Wed, 3 Jul 2024 10:47:20 -0700 Subject: [PATCH 25/80] Temporary fix for https://pagure.io/releng/issue/12187 --- tests/pam_ssh_agent_auth/runtest.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/pam_ssh_agent_auth/runtest.sh b/tests/pam_ssh_agent_auth/runtest.sh index 297be39..5e80a70 100755 --- a/tests/pam_ssh_agent_auth/runtest.sh +++ b/tests/pam_ssh_agent_auth/runtest.sh @@ -48,6 +48,8 @@ rlJournalStart rlAssertRpm pam_ssh_agent_auth rlImport distribution/fips rlServiceStart sshd + # The following line is a temporary fix for https://pagure.io/releng/issue/12187 + rlRun "rpm --restore filesystem" rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory" rlRun "cp ${PAM_MODULE}.c $TmpDir/" rlRun "pushd $TmpDir" From f8918df60fa7c2918729118cbe71e4b151e39cfa Mon Sep 17 00:00:00 2001 From: Cristian Le Date: Tue, 2 Jul 2024 09:42:19 +0200 Subject: [PATCH 26/80] Migrate sti tests to tmt --- .fmf/version | 1 + plans/main.fmf | 6 ++++++ tests/main.fmf | 11 +++++++++++ tests/pam_ssh_agent_auth/Makefile | 2 +- tests/pam_ssh_agent_auth/PURPOSE | 7 ------- tests/pam_ssh_agent_auth/main.fmf | 11 +++++++++++ tests/port-forwarding/Makefile | 2 +- tests/port-forwarding/PURPOSE | 3 --- tests/port-forwarding/main.fmf | 4 ++++ tests/tests.yml | 31 ------------------------------- 10 files changed, 35 insertions(+), 43 deletions(-) create mode 100644 .fmf/version create mode 100644 plans/main.fmf create mode 100644 tests/main.fmf delete mode 100644 tests/pam_ssh_agent_auth/PURPOSE create mode 100644 tests/pam_ssh_agent_auth/main.fmf delete mode 100644 tests/port-forwarding/PURPOSE create mode 100644 tests/port-forwarding/main.fmf delete mode 100644 tests/tests.yml diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000..d00491f --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/plans/main.fmf b/plans/main.fmf new file mode 100644 index 0000000..ae0c305 --- /dev/null +++ b/plans/main.fmf @@ -0,0 +1,6 @@ +summary: Run all tests +execute: + how: tmt +discover: + how: fmf + diff --git a/tests/main.fmf b/tests/main.fmf new file mode 100644 index 0000000..339889b --- /dev/null +++ b/tests/main.fmf @@ -0,0 +1,11 @@ +test: ./runtest.sh +framework: beakerlib +require: + - iproute # needs ip command + - procps-ng # needs ps and pgrep commands + - initscripts # needs service command + - openssh-clients # needs ssh command + - findutils # needs find command + - net-tools # needs netstat command + - libselinux-utils # needs selinuxenabled command + - nmap-ncat # needs nc command diff --git a/tests/pam_ssh_agent_auth/Makefile b/tests/pam_ssh_agent_auth/Makefile index f77eb4d..7b75039 100644 --- a/tests/pam_ssh_agent_auth/Makefile +++ b/tests/pam_ssh_agent_auth/Makefile @@ -28,7 +28,7 @@ export TESTVERSION=1.0 BUILT_FILES= -FILES=$(METADATA) runtest.sh Makefile PURPOSE pam_save_ssh_var.c +FILES=$(METADATA) runtest.sh Makefile pam_save_ssh_var.c .PHONY: all install download clean diff --git a/tests/pam_ssh_agent_auth/PURPOSE b/tests/pam_ssh_agent_auth/PURPOSE deleted file mode 100644 index 59557de..0000000 --- a/tests/pam_ssh_agent_auth/PURPOSE +++ /dev/null @@ -1,7 +0,0 @@ -PURPOSE of /CoreOS/openssh/Sanity/pam_ssh_agent_auth -Description: This is basic sanity test for pam_ssh_agent_auth -Author: Jakub Jelen - -Created as a response to rhbz#1251777 and previous one rhbz#1225106. -The code of pam module is outdated and compiled with current openssh -version which went through quite enough refactoring. diff --git a/tests/pam_ssh_agent_auth/main.fmf b/tests/pam_ssh_agent_auth/main.fmf new file mode 100644 index 0000000..5820055 --- /dev/null +++ b/tests/pam_ssh_agent_auth/main.fmf @@ -0,0 +1,11 @@ +summary: Basic sanity test for pam_ssh_agent_auth +description: | + Created as a response to rhbz#1251777 and previous one rhbz#1225106. + The code of pam module is outdated and compiled with current openssh + version which went through quite enough refactoring. +contact: Jakub Jelen +require+: + - pam_ssh_agent_auth + - gcc # needs to test pam_ssh_agent_auth + - pam-devel # needs to test pam_ssh_agent_auth + - expect # needs to test pam_ssh_agent_auth diff --git a/tests/port-forwarding/Makefile b/tests/port-forwarding/Makefile index d325bdd..d92f24d 100644 --- a/tests/port-forwarding/Makefile +++ b/tests/port-forwarding/Makefile @@ -28,7 +28,7 @@ export TESTVERSION=1.0 BUILT_FILES= -FILES=$(METADATA) runtest.sh Makefile PURPOSE +FILES=$(METADATA) runtest.sh Makefile .PHONY: all install download clean diff --git a/tests/port-forwarding/PURPOSE b/tests/port-forwarding/PURPOSE deleted file mode 100644 index 5a8bc87..0000000 --- a/tests/port-forwarding/PURPOSE +++ /dev/null @@ -1,3 +0,0 @@ -PURPOSE of /CoreOS/openssh/Sanity/port-forwarding -Description: Testing port forwarding (ideally all possibilities: -L, -R, -D) -Author: Stanislav Zidek diff --git a/tests/port-forwarding/main.fmf b/tests/port-forwarding/main.fmf new file mode 100644 index 0000000..8f29286 --- /dev/null +++ b/tests/port-forwarding/main.fmf @@ -0,0 +1,4 @@ +summary: Testing port forwarding +description: | + Testing port forwarding (ideally all possibilities: -L, -R, -D) +contact: Stanislav Zidek diff --git a/tests/tests.yml b/tests/tests.yml deleted file mode 100644 index 8086af2..0000000 --- a/tests/tests.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- -# Tests for docker container -- hosts: localhost - tags: - - container - # no compatible tests - -# Tests for classic environment and Atomic Host -- hosts: localhost - tags: - - all - - classic - - atomic - roles: - - role: standard-test-beakerlib - tests: - - port-forwarding - - pam_ssh_agent_auth - required_packages: - - iproute # needs ip command - - procps-ng # needs ps and pgrep commands - - initscripts # needs service command - - openssh-clients # needs ssh command - - findutils # needs find command - - net-tools # needs netstat command - - libselinux-utils # needs selinuxenabled command - - nmap-ncat # needs nc command - - pam_ssh_agent_auth - - gcc # needs to test pam_ssh_agent_auth - - pam-devel # needs to test pam_ssh_agent_auth - - expect # needs to test pam_ssh_agent_auth From 80da2c7159522de574c3babddaa7013d53c5aaf9 Mon Sep 17 00:00:00 2001 From: Cristian Le Date: Wed, 3 Jul 2024 10:46:07 +0200 Subject: [PATCH 27/80] Remove unused `rhts-environment.sh` Looking at the source, there doesn't seem to be any functions/variables used from there https://github.com/beaker-project/rhts/blob/master/bin/rhts-environment.sh Signed-off-by: Cristian Le --- tests/pam_ssh_agent_auth/runtest.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/pam_ssh_agent_auth/runtest.sh b/tests/pam_ssh_agent_auth/runtest.sh index 5e80a70..101a338 100755 --- a/tests/pam_ssh_agent_auth/runtest.sh +++ b/tests/pam_ssh_agent_auth/runtest.sh @@ -26,7 +26,6 @@ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Include Beaker environment -. /usr/bin/rhts-environment.sh || exit 1 . /usr/share/beakerlib/beakerlib.sh || exit 1 PACKAGE="openssh" From 787ce2c24dfaa04a6d4b13ce0a0580b08debd413 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Tue, 2 Jul 2024 15:15:49 -0700 Subject: [PATCH 28/80] Collect logs after sudo attempt in pam_ssh_agent_auth --- tests/pam_ssh_agent_auth/runtest.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/pam_ssh_agent_auth/runtest.sh b/tests/pam_ssh_agent_auth/runtest.sh index 101a338..2ca51ce 100755 --- a/tests/pam_ssh_agent_auth/runtest.sh +++ b/tests/pam_ssh_agent_auth/runtest.sh @@ -79,6 +79,9 @@ auth sufficient pam_ssh_agent_auth.so file=$AUTH_KEYS' $PAM_SUDO" rlRun "cat ~$USER/.ssh/my_id_${KEY}.pub >> $AUTH_KEYS" rlRun -s "su $USER -c 'eval \`ssh-agent\`; ssh-add ~/.ssh/my_id_$KEY; sudo id; ssh-agent -k'" rlAssertGrep "uid=0(root) gid=0(root)" $rlRun_LOG + # Collect journal data. If the test above fails, the log probably + # explains why, which may be difficult to determine without logs. + rlRun "journalctl -n 50" rlPhaseEnd done From 2d59c1dbf2d6b21bb1568f12dba1ead4c5b193d0 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Wed, 3 Jul 2024 22:46:52 -0700 Subject: [PATCH 29/80] Collect all logs after pam_ssh_agent_auth and port-forward tests --- tests/pam_ssh_agent_auth/runtest.sh | 6 +++--- tests/port-forwarding/runtest.sh | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/pam_ssh_agent_auth/runtest.sh b/tests/pam_ssh_agent_auth/runtest.sh index 2ca51ce..b1f500a 100755 --- a/tests/pam_ssh_agent_auth/runtest.sh +++ b/tests/pam_ssh_agent_auth/runtest.sh @@ -79,9 +79,6 @@ auth sufficient pam_ssh_agent_auth.so file=$AUTH_KEYS' $PAM_SUDO" rlRun "cat ~$USER/.ssh/my_id_${KEY}.pub >> $AUTH_KEYS" rlRun -s "su $USER -c 'eval \`ssh-agent\`; ssh-add ~/.ssh/my_id_$KEY; sudo id; ssh-agent -k'" rlAssertGrep "uid=0(root) gid=0(root)" $rlRun_LOG - # Collect journal data. If the test above fails, the log probably - # explains why, which may be difficult to determine without logs. - rlRun "journalctl -n 50" rlPhaseEnd done @@ -183,6 +180,9 @@ _EOF rlRun "userdel -fr $USER" rlFileRestore rlServiceRestore sshd + # Collect journal data. If the test fails, the log probably + # explains why, which may be difficult to determine without logs. + rlRun "journalctl -b 0 > '$TMT_TEST_DATA'/journalctl.txt" rlPhaseEnd rlJournalPrintText rlJournalEnd diff --git a/tests/port-forwarding/runtest.sh b/tests/port-forwarding/runtest.sh index f18f2ae..abb2edc 100755 --- a/tests/port-forwarding/runtest.sh +++ b/tests/port-forwarding/runtest.sh @@ -147,6 +147,9 @@ forwarding_test() { rlFileRestore rlServiceRestore sshd rlRun "rm -r $TmpDir" 0 "Removing tmp directory" + # Collect journal data. If the test fails, the log probably + # explains why, which may be difficult to determine without logs. + rlRun "journalctl -b 0 > '$TMT_TEST_DATA'/journalctl.txt" rlPhaseEnd rlJournalPrintText rlJournalEnd From b7ff2394182467ff97ffa63727e5e11175e9748f Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Thu, 4 Jul 2024 09:50:01 -0700 Subject: [PATCH 30/80] Rate limit service restarts to prevent intermittent test failures. --- tests/port-forwarding/runtest.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/port-forwarding/runtest.sh b/tests/port-forwarding/runtest.sh index abb2edc..d690270 100755 --- a/tests/port-forwarding/runtest.sh +++ b/tests/port-forwarding/runtest.sh @@ -44,6 +44,8 @@ rlJournalStart rlRun "su - $USER -c \"mkdir .ssh; chmod 700 .ssh; cd .ssh; ssh-keygen -N '' -f id_rsa; cat id_rsa.pub >authorized_keys; chmod 600 authorized_keys\"" rlRun "echo 'LogLevel DEBUG' >>/etc/ssh/sshd_config" rlServiceStart sshd + # Rate limit service restarts by sleeping + rlRun "sleep 3s" rlRun "IP=\$( ip a |grep 'scope global' |grep -w inet |cut -d'/' -f1 |awk '{ print \$2 }' |tail -1 )" rlRun "echo 'IP=$IP'" rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory" @@ -98,6 +100,8 @@ forwarding_test() { rlRun "echo 'PermitOpen any' >>/etc/ssh/sshd_config" rlRun "echo '$IP anyhost1 anyhost2' >>/etc/hosts" rlRun "service sshd restart" + # Rate limit service restarts by sleeping + rlRun "sleep 3s" for i in `seq 3`; do forwarding_test "success" $FORWARDED anyhost1 $LISTEN forwarding_test "success" $FORWARDED anyhost2 $LISTEN @@ -114,6 +118,8 @@ forwarding_test() { rlRun "echo 'PermitOpen wildportallow:*' >>/etc/ssh/sshd_config" rlRun "echo '$IP wildportallow wildportdeny' >>/etc/hosts" rlRun "service sshd restart" + # Rate limit service restarts by sleeping + rlRun "sleep 3s" forwarding_test "success" $FORWARDED wildportallow $LISTEN ((FORWARDED+=1)) ((LISTEN+=1)) @@ -122,6 +128,8 @@ forwarding_test() { ((LISTEN+=1)) rlFileRestore --namespace port_wildcard rlRun "service sshd restart" + # Rate limit service restarts by sleeping + rlRun "sleep 3s" rlPhaseEnd fi @@ -131,6 +139,8 @@ forwarding_test() { rlRun "echo 'PermitOpen *:$LISTEN' >>/etc/ssh/sshd_config" rlRun "echo '$IP wildhost1 wildhost2' >>/etc/hosts" rlRun "service sshd restart" + # Rate limit service restarts by sleeping + rlRun "sleep 3s" forwarding_test "success" $FORWARDED wildhost1 $LISTEN ((FORWARDED+=1)) forwarding_test "success" $FORWARDED wildhost2 $LISTEN From 1b1292d3a54e9525a77e3c4a83b304676b9a3de4 Mon Sep 17 00:00:00 2001 From: Gordon Messmer Date: Mon, 22 Jul 2024 13:43:22 -0700 Subject: [PATCH 31/80] DSA keys are no longer supported, due to the use of SHA1. --- tests/pam_ssh_agent_auth/runtest.sh | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/pam_ssh_agent_auth/runtest.sh b/tests/pam_ssh_agent_auth/runtest.sh index b1f500a..7587269 100755 --- a/tests/pam_ssh_agent_auth/runtest.sh +++ b/tests/pam_ssh_agent_auth/runtest.sh @@ -63,10 +63,6 @@ auth sufficient pam_ssh_agent_auth.so file=$AUTH_KEYS' $PAM_SUDO" rlRun "echo $PASS |passwd --stdin $USER" rlPhaseEnd - if ! fipsIsEnabled; then - KEYS+=("dsa") - fi - for KEY in "${KEYS[@]}"; do rlPhaseStartTest "Test with key type $KEY" rlRun "su $USER -c 'ssh-keygen -t $KEY -f ~/.ssh/my_id_$KEY -N \"\"'" 0 From b38789c6ac6eeb0ecb2269e7d96cf3defc4962e4 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 10 Jul 2024 18:19:23 +0200 Subject: [PATCH 32/80] Rebase to OpenSSH 9.8p1 --- .gitignore | 2 + CVE-2024-6387.patch | 18 -- openssh-6.6.1p1-log-in-chroot.patch | 8 +- openssh-6.6.1p1-selinux-contexts.patch | 6 +- openssh-6.6p1-GSSAPIEnablek5users.patch | 9 +- openssh-6.6p1-allow-ip-opts.patch | 4 +- openssh-6.6p1-keycat.patch | 6 +- openssh-6.6p1-kuserok.patch | 4 +- openssh-6.6p1-privsep-selinux.patch | 21 +- openssh-6.7p1-coverity.patch | 6 +- openssh-7.1p2-audit-race-condition.patch | 2 +- openssh-7.3p1-x11-max-displays.patch | 2 +- openssh-7.6p1-audit.patch | 158 +++++----- openssh-7.6p1-cleanup-selinux.patch | 29 +- openssh-7.7p1-fips.patch | 29 +- openssh-7.7p1-gssapi-new-unique.patch | 10 +- openssh-7.8p1-UsePAM-warning.patch | 14 +- openssh-7.8p1-role-mls.patch | 21 +- openssh-8.0p1-crypto-policies.patch | 32 ++- openssh-8.0p1-gssapi-keyex.patch | 287 +++++-------------- openssh-8.0p1-pkcs11-uri.patch | 2 +- openssh-8.7p1-minrsabits.patch | 2 +- openssh-8.7p1-negotiate-supported-algs.patch | 11 +- openssh-8.7p1-nohostsha1proof.patch | 56 +--- openssh-9.8p1-systemd.patch | 201 ------------- openssh.spec | 17 +- sources | 4 +- 27 files changed, 283 insertions(+), 678 deletions(-) delete mode 100644 CVE-2024-6387.patch delete mode 100644 openssh-9.8p1-systemd.patch diff --git a/.gitignore b/.gitignore index 6988bb2..f760b87 100644 --- a/.gitignore +++ b/.gitignore @@ -60,3 +60,5 @@ pam_ssh_agent_auth-0.9.2.tar.bz2 /openssh-9.3p1.tar.gz.asc /openssh-9.6p1.tar.gz /openssh-9.6p1.tar.gz.asc +/openssh-9.8p1.tar.gz +/openssh-9.8p1.tar.gz.asc diff --git a/CVE-2024-6387.patch b/CVE-2024-6387.patch deleted file mode 100644 index 0b976c0..0000000 --- a/CVE-2024-6387.patch +++ /dev/null @@ -1,18 +0,0 @@ -diff --git a/log.c b/log.c -index 9fc1a2e2e..191ff4a5a 100644 ---- a/log.c -+++ b/log.c -@@ -451,12 +451,14 @@ void - sshsigdie(const char *file, const char *func, int line, int showfunc, - LogLevel level, const char *suffix, const char *fmt, ...) - { -+#ifdef SYSLOG_R_SAFE_IN_SIGHAND - va_list args; - - va_start(args, fmt); - sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL, - suffix, fmt, args); - va_end(args); -+#endif - _exit(1); - } diff --git a/openssh-6.6.1p1-log-in-chroot.patch b/openssh-6.6.1p1-log-in-chroot.patch index 941c694..0f65279 100644 --- a/openssh-6.6.1p1-log-in-chroot.patch +++ b/openssh-6.6.1p1-log-in-chroot.patch @@ -237,11 +237,11 @@ diff -up openssh-8.6p1/sftp-server-main.c.log-in-chroot openssh-8.6p1/sftp-serve - return (sftp_server_main(argc, argv, user_pw)); + return (sftp_server_main(argc, argv, user_pw, 0)); } -diff -up openssh-8.6p1/sshd.c.log-in-chroot openssh-8.6p1/sshd.c ---- openssh-8.6p1/sshd.c.log-in-chroot 2021-04-19 14:43:08.543843426 +0200 -+++ openssh-8.6p1/sshd.c 2021-04-19 14:43:08.545843441 +0200 +diff -up openssh-8.6p1/sshd-session.c.log-in-chroot openssh-8.6p1/sshd-session.c +--- openssh-8.6p1/sshd-session.c.log-in-chroot 2021-04-19 14:43:08.543843426 +0200 ++++ openssh-8.6p1/sshd-session.c 2021-04-19 14:43:08.545843441 +0200 @@ -559,7 +559,7 @@ privsep_postauth(struct ssh *ssh, Authct - } + #endif /* New socket pair */ - monitor_reinit(pmonitor); diff --git a/openssh-6.6.1p1-selinux-contexts.patch b/openssh-6.6.1p1-selinux-contexts.patch index eab724a..96161cb 100644 --- a/openssh-6.6.1p1-selinux-contexts.patch +++ b/openssh-6.6.1p1-selinux-contexts.patch @@ -116,10 +116,10 @@ index cb51f99..8b7cda2 100644 #endif #ifdef LINUX_OOM_ADJUST -diff --git a/sshd.c b/sshd.c +diff --git a/sshd-session.c b/sshd-session.c index 2871fe9..39b9c08 100644 ---- a/sshd.c -+++ b/sshd.c +--- a/sshd-session.c ++++ b/sshd-session.c @@ -629,7 +629,7 @@ privsep_preauth_child(void) demote_sensitive_data(); diff --git a/openssh-6.6p1-GSSAPIEnablek5users.patch b/openssh-6.6p1-GSSAPIEnablek5users.patch index cccb3e0..7fef831 100644 --- a/openssh-6.6p1-GSSAPIEnablek5users.patch +++ b/openssh-6.6p1-GSSAPIEnablek5users.patch @@ -38,16 +38,16 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -418,7 +421,7 @@ typedef enum { - sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms, +@@ -578,7 +578,7 @@ typedef enum { sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, + sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, - sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, + sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor, sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, -@@ -497,14 +500,16 @@ static struct { +@@ -600,14 +600,16 @@ static struct { { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, @@ -129,3 +129,6 @@ diff -up openssh-7.4p1/sshd_config.GSSAPIEnablek5users openssh-7.4p1/sshd_config # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will +diff -up openssh-9.8p1/servconf.c.xxx openssh-9.8p1/servconf.c +--- openssh-9.8p1/servconf.c.xxx 2024-07-11 13:51:19.969960781 +0200 ++++ openssh-9.8p1/servconf.c 2024-07-11 13:51:30.938231250 +0200 diff --git a/openssh-6.6p1-allow-ip-opts.patch b/openssh-6.6p1-allow-ip-opts.patch index be8d340..d969b5c 100644 --- a/openssh-6.6p1-allow-ip-opts.patch +++ b/openssh-6.6p1-allow-ip-opts.patch @@ -1,6 +1,6 @@ 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 +--- openssh/sshd-session.c.ip-opts 2016-07-25 13:58:48.998507834 +0200 ++++ openssh/sshd-session.c 2016-07-25 14:01:28.346469878 +0200 @@ -1507,12 +1507,32 @@ check_ip_options(struct ssh *ssh) if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, diff --git a/openssh-6.6p1-keycat.patch b/openssh-6.6p1-keycat.patch index 529b508..7339185 100644 --- a/openssh-6.6p1-keycat.patch +++ b/openssh-6.6p1-keycat.patch @@ -39,9 +39,9 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign +SSH_KEYCAT=$(libexecdir)/ssh-keycat + SSHD_SESSION=$(libexecdir)/sshd-session SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper - PRIVSEP_PATH=@PRIVSEP_PATH@ @@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ @@ -54,8 +54,8 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in .SUFFIXES: .lo --TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) -+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT) +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT) XMSS_OBJS=\ ssh-xmss.o \ diff --git a/openssh-6.6p1-kuserok.patch b/openssh-6.6p1-kuserok.patch index eaf4453..e43128b 100644 --- a/openssh-6.6p1-kuserok.patch +++ b/openssh-6.6p1-kuserok.patch @@ -266,8 +266,8 @@ diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5 +The default is +.Cm yes . .It Cm KexAlgorithms - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. + Specifies the permitted KEX (Key Exchange) algorithms that the server will + offer to clients. @@ -1078,6 +1082,7 @@ Available keywords are .Cm IPQoS , .Cm KbdInteractiveAuthentication , diff --git a/openssh-6.6p1-privsep-selinux.patch b/openssh-6.6p1-privsep-selinux.patch index 8047fc3..023dd5c 100644 --- a/openssh-6.6p1-privsep-selinux.patch +++ b/openssh-6.6p1-privsep-selinux.patch @@ -96,8 +96,8 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c } diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c ---- openssh-7.4p1/sshd.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100 -+++ openssh-7.4p1/sshd.c 2016-12-23 18:59:13.808124269 +0100 +--- openssh-7.4p1/sshd-session.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100 ++++ openssh-7.4p1/sshd-session.c 2016-12-23 18:59:13.808124269 +0100 @@ -540,6 +540,10 @@ privsep_preauth_child(void) /* Demote the private keys to public keys. */ demote_sensitive_data(); @@ -109,13 +109,12 @@ diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c /* Demote the child */ if (privsep_chroot) { /* Change our root directory */ -@@ -633,6 +637,9 @@ privsep_postauth(Authctxt *authctxt) - { - #ifdef DISABLE_FD_PASSING - if (1) { -+#elif defined(WITH_SELINUX) -+ if (0) { -+ /* even root user can be confined by SELinux */ - #else - if (authctxt->pw->pw_uid == 0) { +@@ -403,7 +403,7 @@ privsep_postauth(struct ssh *ssh, Authct + * fd passing, as AFAIK PTY allocation on this platform doesn't require + * special privileges to begin with. + */ +-#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) ++#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) && !defined(WITH_SELINUX) + skip_privdrop = 1; #endif + diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index 01a061b..7cbdb2a 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -221,9 +221,9 @@ diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c return NULL; } /* validate also provider from URI */ -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 +diff -up openssh-7.4p1/sshd-session.c.coverity openssh-7.4p1/sshd-session.c +--- openssh-7.4p1/sshd-session.c.coverity 2016-12-23 16:40:26.897788690 +0100 ++++ openssh-7.4p1/sshd-session.c 2016-12-23 16:40:26.904788692 +0100 @@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt) privsep_preauth_child(ssh); diff --git a/openssh-7.1p2-audit-race-condition.patch b/openssh-7.1p2-audit-race-condition.patch index b5895f7..1d2bf3b 100644 --- a/openssh-7.1p2-audit-race-condition.patch +++ b/openssh-7.1p2-audit-race-condition.patch @@ -109,7 +109,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c @@ -717,6 +728,8 @@ do_exec(Session *s, const char *command) } if (s->command != NULL && s->ptyfd == -1) - s->command_handle = PRIVSEP(audit_run_command(ssh, s->command)); + s->command_handle = mm_audit_run_command(ssh, s->command); + if (pipe(paudit) < 0) + fatal("pipe: %s", strerror(errno)); #endif diff --git a/openssh-7.3p1-x11-max-displays.patch b/openssh-7.3p1-x11-max-displays.patch index 2b702d4..e28c62e 100644 --- a/openssh-7.3p1-x11-max-displays.patch +++ b/openssh-7.3p1-x11-max-displays.patch @@ -2,7 +2,7 @@ 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 "*" + #define NUM_SOCKS 10 /* -- X11 forwarding */ -/* Maximum number of fake X11 displays to try. */ diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index cec5b23..8d06a6d 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -733,7 +733,7 @@ diff -up openssh-8.6p1/auth2.c.audit openssh-8.6p1/auth2.c /* Invalid user, fake password information */ authctxt->pw = fakepw(); -#ifdef SSH_AUDIT_EVENTS -- PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); +- mm_audit_event(ssh, SSH_INVALID_USER); -#endif } #ifdef USE_PAM @@ -743,11 +743,11 @@ diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c +++ 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)) && -- PRIVSEP(sshkey_verify(key, sig, slen, -+ PRIVSEP(hostbased_key_verify(ssh, key, sig, slen, - sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0) + if (mm_hostbased_key_allowed(ssh, authctxt->pw, cuser, + chost, key) && +- mm_sshkey_verify(key, sig, slen, ++ mm_hostbased_key_verify(ssh, key, sig, slen, + sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL) == 0) authenticated = 1; @@ -175,6 +175,20 @@ done: @@ -777,12 +777,12 @@ diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c @@ -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)) && -- PRIVSEP(sshkey_verify(key, sig, slen, -+ PRIVSEP(user_key_verify(ssh, key, sig, slen, + if (mm_user_key_allowed(ssh, pw, key, 1, &authopts) && +- mm_sshkey_verify(key, sig, slen, ++ mm_user_key_verify(ssh, key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, - ssh->compat, &sig_details)) == 0) { + ssh->compat, &sig_details) == 0) { @@ -305,6 +305,20 @@ done: return authenticated; } @@ -828,7 +828,7 @@ diff -up openssh-8.6p1/auth.h.audit openssh-8.6p1/auth.h + 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 *); + int auth_activate_options(struct ssh *, struct sshauthopt *); @@ -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 *, @@ -915,8 +915,8 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c #include "xmalloc.h" +#include "audit.h" - #ifdef GSSAPI - #include "ssh-gss.h" + /* prototype */ + static int kex_choose_conf(struct ssh *, uint32_t seq); @@ -816,12 +817,16 @@ kex_start_rekex(struct ssh *ssh) } @@ -1536,9 +1536,9 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c } #endif /* SSH_AUDIT_EVENTS */ @@ -1095,3 +1137,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc + return &ci; } - #endif /* GSSAPI */ +#ifdef SSH_AUDIT_EVENTS +void +mm_audit_unsupported_body(struct ssh *ssh, int what) @@ -1632,7 +1632,7 @@ diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h +int mm_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 **); - #ifdef GSSAPI + void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); @@ -86,7 +88,12 @@ void mm_sshpam_free_ctx(void *); #ifdef SSH_AUDIT_EVENTS #include "audit.h" @@ -1843,18 +1843,18 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c + if (s->command != NULL || s->command_handle != -1) + fatal("do_exec: command already set"); if (command != NULL) -- PRIVSEP(audit_run_command(command)); +- mm_audit_run_command(command); + s->command = xstrdup(command); else if (s->ttyfd == -1) { char *shell = s->pw->pw_shell; if (shell[0] == '\0') /* empty shell means /bin/sh */ shell =_PATH_BSHELL; -- PRIVSEP(audit_run_command(shell)); +- mm_audit_run_command(shell); + s->command = xstrdup(shell); } + if (s->command != NULL && s->ptyfd == -1) -+ s->command_handle = PRIVSEP(audit_run_command(ssh, s->command)); ++ s->command_handle = mm_audit_run_command(ssh, s->command); #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); @@ -1981,7 +1981,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c @@ -2734,7 +2804,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au * or if running in monitor. */ - if (!use_privsep || mm_is_monitor()) + if (mm_is_monitor()) - session_destroy_all(ssh, session_pty_cleanup2); + session_destroy_all(ssh, do_cleanup_one_session); } @@ -2020,25 +2020,6 @@ diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h 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" -+#include "audit.h" - #include "ssh-sandbox.h" - #include "auth-options.h" - #include "version.h" -@@ -260,8 +261,8 @@ struct sshbuf *loginmsg; - struct passwd *privsep_pw = NULL; - - /* Prototypes for various functions defined later in this file. */ --void destroy_sensitive_data(void); --void demote_sensitive_data(void); -+void destroy_sensitive_data(struct ssh *, int); -+void demote_sensitive_data(struct ssh *); - static void do_ssh2_kex(struct ssh *); - - static char *listener_proctitle; @@ -279,6 +280,15 @@ close_listen_socks(void) num_listen_socks = 0; } @@ -2052,11 +2033,59 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c + return num_listen_socks > 0; +} + + /* Allocate and initialise the children array */ static void - close_startup_pipes(void) + child_alloc(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, + int log_stderr) { + struct pollfd *pfd = NULL; +@@ -1204,6 +1259,7 @@ server_accept_loop(int *sock_in, int *so + if (received_sigterm) { + logit("Received signal %d; terminating.", + (int) received_sigterm); ++ destroy_sensitive_data(ssh, 0); + close_listen_socks(); + if (options.pid_file != NULL) + unlink(options.pid_file); +@@ -2189,7 +2189,7 @@ + } + + /* Accept a connection and return in a forked child */ +- server_accept_loop(&sock_in, &sock_out, ++ server_accept_loop(ssh, &sock_in, &sock_out, + &newsock, config_s, log_stderr); + } + +diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c +--- openssh-8.6p1/sshd-session.c.audit 2021-04-19 16:47:35.727061907 +0200 ++++ openssh-8.6p1/sshd-session.c 2021-04-19 16:47:35.759062152 +0200 +@@ -122,6 +122,7 @@ + #include "ssh-gss.h" + #endif + #include "monitor_wrap.h" ++#include "audit.h" + #include "ssh-sandbox.h" + #include "auth-options.h" + #include "version.h" +@@ -260,8 +261,8 @@ struct sshbuf *loginmsg; + struct sshbuf *loginmsg; + + /* Prototypes for various functions defined later in this file. */ +-void destroy_sensitive_data(void); +-void demote_sensitive_data(void); ++void destroy_sensitive_data(struct ssh *, int); ++void demote_sensitive_data(struct ssh *); + static void do_ssh2_kex(struct ssh *); + + /* @@ -377,18 +387,45 @@ grace_alarm_handler(int sig) - ssh_remote_port(the_active_state)); + _exit(EXIT_LOGIN_GRACE); } -/* Destroy the host and server keys. They will no longer be needed. */ @@ -2163,9 +2192,9 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c #ifdef WITH_SELINUX sshd_selinux_change_privsep_preauth_context(); @@ -492,7 +547,7 @@ privsep_preauth(struct ssh *ssh) + pmonitor->m_pkex = &ssh->kex; - if (use_privsep == PRIVSEP_ON) - box = ssh_sandbox_init(pmonitor); + box = ssh_sandbox_init(pmonitor); - pid = fork(); + pmonitor->m_pid = pid = fork(); if (pid == -1) { @@ -2189,32 +2218,6 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c reseed_prngs(); -@@ -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; -@@ -1204,6 +1259,7 @@ server_accept_loop(int *sock_in, int *so - if (received_sigterm) { - logit("Received signal %d; terminating.", - (int) received_sigterm); -+ destroy_sensitive_data(ssh, 0); - close_listen_socks(); - if (options.pid_file != NULL) - unlink(options.pid_file); -@@ -2189,7 +2189,7 @@ - } - - /* Accept a connection and return in a forked child */ -- server_accept_loop(&sock_in, &sock_out, -+ server_accept_loop(ssh, &sock_in, &sock_out, - &newsock, config_s); - } - @@ -2333,6 +2389,9 @@ main(int ac, char **av) do_authenticated(ssh, authctxt); @@ -2238,24 +2241,17 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c + if (in_cleanup) + _exit(i); + in_cleanup = 1; + extern int auth_attempted; /* monitor.c */ + if (the_active_state != NULL && the_authctxt != NULL) { - do_cleanup(the_active_state, the_authctxt); - if (use_privsep && privsep_is_preauth && -@@ -2525,9 +2593,16 @@ cleanup_exit(int i) - } - } - } -+ is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0; -+ if (sensitive_data.host_keys != NULL && the_active_state != NULL) -+ destroy_sensitive_data(the_active_state, is_privsep_child); -+ if (the_active_state != NULL) -+ packet_destroy_all(the_active_state, 1, is_privsep_child); +@@ -2525,7 +2593,9 @@ cleanup_exit(int i) + _exit(EXIT_AUTH_ATTEMPTED); #ifdef SSH_AUDIT_EVENTS /* done after do_cleanup so it can cancel the PAM auth 'thread' */ -- if (the_active_state != NULL && (!use_privsep || mm_is_monitor())) +- if (the_active_state != NULL && mm_is_monitor()) + if (the_active_state != NULL && + (the_authctxt == NULL || !the_authctxt->authenticated) && -+ (!use_privsep || mm_is_monitor())) ++ mm_is_monitor()) audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif _exit(i); diff --git a/openssh-7.6p1-cleanup-selinux.patch b/openssh-7.6p1-cleanup-selinux.patch index f7cd50f..5b8aaca 100644 --- a/openssh-7.6p1-cleanup-selinux.patch +++ b/openssh-7.6p1-cleanup-selinux.patch @@ -8,9 +8,9 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c +extern int inetd_flag; +extern int rexeced_flag; +extern Authctxt *the_authctxt; + extern struct authmethod_cfg methodcfg_pubkey; static char * - format_key(const struct sshkey *key) @@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh if ((pid = subprocess("AuthorizedPrincipalsCommand", command, ac, av, &f, @@ -217,15 +217,15 @@ diff -up openssh/platform.c.refactor openssh/platform.c --- openssh/platform.c.refactor 2019-04-04 13:19:12.204821389 +0200 +++ openssh/platform.c 2019-04-04 13:19:12.277822088 +0200 @@ -32,6 +32,9 @@ + #include "openbsd-compat/openbsd-compat.h" - extern int use_privsep; extern ServerOptions options; +extern int inetd_flag; +extern int rexeced_flag; +extern Authctxt *the_authctxt; - void - platform_pre_listen(void) + /* return 1 if we are running with privilege to swap UIDs, 0 otherwise */ + int @@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru } #endif /* HAVE_SETPCRED */ @@ -237,27 +237,18 @@ diff -up openssh/platform.c.refactor openssh/platform.c #endif } -diff -up openssh/sshd.c.refactor openssh/sshd.c ---- openssh/sshd.c.refactor 2019-04-04 13:19:12.275822068 +0200 -+++ openssh/sshd.c 2019-04-04 13:19:51.270195262 +0200 +diff -up openssh/sshd-session.c.refactor openssh/sshd-session.c +--- openssh/sshd-session.c.refactor 2019-04-04 13:19:12.275822068 +0200 ++++ openssh/sshd-session.c 2019-04-04 13:19:51.270195262 +0200 @@ -158,7 +158,7 @@ int debug_flag = 0; - static int test_flag = 0; + int debug_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ -static int inetd_flag = 0; +int inetd_flag = 0; - /* Flag indicating that sshd should not detach and become a daemon. */ - static int no_daemon_flag = 0; -@@ -171,7 +171,7 @@ static char **saved_argv; - static int saved_argc; - - /* re-exec */ --static int rexeced_flag = 0; -+int rexeced_flag = 0; - static int rexec_flag = 1; - static int rexec_argc = 0; - static char **rexec_argv; + /* debug goes to stderr unless inetd_flag is set */ + static int log_stderr = 0; @@ -2192,7 +2192,9 @@ main(int ac, char **av) } #endif diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index b1007b2..80a68d9 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -72,17 +72,17 @@ diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h u_int dh_estimate(int); void dh_set_moduli_file(const char *); -diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c ---- openssh-8.6p1/kex.c.fips 2021-05-06 12:08:36.489926807 +0200 -+++ openssh-8.6p1/kex.c 2021-05-06 12:08:36.498926877 +0200 +diff -up openssh-8.6p1/kex-names.c.fips openssh-8.6p1/kex-names.c +--- openssh-8.6p1/kex-names.c.fips 2021-05-06 12:08:36.489926807 +0200 ++++ openssh-8.6p1/kex-names.c 2021-05-06 12:08:36.498926877 +0200 @@ -39,6 +39,7 @@ #ifdef WITH_OPENSSL #include +#include - #include - # ifdef HAVE_EVP_KDF_CTX_NEW - # include + #include + #endif + @@ -203,7 +203,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { @@ -361,8 +361,8 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c #include #include @@ -77,6 +78,7 @@ - #include - #include + #ifdef WITH_OPENSSL + #include #include +#include #include "openbsd-compat/openssl-compat.h" @@ -393,7 +393,18 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c /* * Chdir to the root directory so that the current disk can be * unmounted if desired. -@@ -2494,10 +2501,14 @@ do_ssh2_kex(struct ssh *ssh) +diff -up openssh-8.6p1/sshd-session.c.fips openssh-8.6p1/sshd-session.c +--- a/sshd-session.c.fips 2021-05-06 12:08:36.493926838 +0200 ++++ b/sshd-session.c 2021-05-06 12:13:56.501492639 +0200 +@@ -78,6 +79,7 @@ + #include + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + #endif + +@@ -2506,10 +2513,14 @@ do_ssh2_kex(struct ssh *ssh) if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) orig = NULL; diff --git a/openssh-7.7p1-gssapi-new-unique.patch b/openssh-7.7p1-gssapi-new-unique.patch index 544932b..1f70be2 100644 --- a/openssh-7.7p1-gssapi-new-unique.patch +++ b/openssh-7.7p1-gssapi-new-unique.patch @@ -579,9 +579,9 @@ diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c child_set_env(&env, &envsize, "KRB5CCNAME", s->authctxt->krb5_ccname); #endif -diff -up openssh-8.6p1/sshd.c.ccache_name openssh-8.6p1/sshd.c ---- openssh-8.6p1/sshd.c.ccache_name 2021-04-19 14:05:10.849744540 +0200 -+++ openssh-8.6p1/sshd.c 2021-04-19 14:05:10.855744584 +0200 +diff -up openssh-8.6p1/sshd-session.c.ccache_name openssh-8.6p1/sshd-session.c +--- openssh-8.6p1/sshd-session.c.ccache_name 2021-04-19 14:05:10.849744540 +0200 ++++ openssh-8.6p1/sshd-session.c 2021-04-19 14:05:10.855744584 +0200 @@ -2284,7 +2284,7 @@ main(int ac, char **av) #ifdef GSSAPI if (options.gss_authentication) { @@ -607,8 +607,8 @@ diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5 +can lead to overwriting previous tickets by subseqent connections to the same +user account. .It Cm KexAlgorithms - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. + Specifies the permitted KEX (Key Exchange) algorithms that the server will + offer to clients. diff -up openssh-8.6p1/ssh-gss.h.ccache_name openssh-8.6p1/ssh-gss.h --- openssh-8.6p1/ssh-gss.h.ccache_name 2021-04-19 14:05:10.852744562 +0200 +++ openssh-8.6p1/ssh-gss.h 2021-04-19 14:05:10.855744584 +0200 diff --git a/openssh-7.8p1-UsePAM-warning.patch b/openssh-7.8p1-UsePAM-warning.patch index a94419e..f8d7042 100644 --- a/openssh-7.8p1-UsePAM-warning.patch +++ b/openssh-7.8p1-UsePAM-warning.patch @@ -1,13 +1,13 @@ 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 +--- openssh-8.6p1/sshd-session.c.log-usepam-no 2021-04-19 14:00:45.099735129 +0200 ++++ openssh-8.6p1/sshd-session.c 2021-04-19 14:03:21.140920974 +0200 @@ -1749,6 +1749,10 @@ main(int ac, char **av) - parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, - cfg, &includes, NULL, rexeced_flag); + "enabled authentication methods"); + } -+ /* 'UsePAM no' is not supported in Fedora */ ++ /* 'UsePAM no' is not supported in our builds */ + if (! options.use_pam) -+ logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems."); ++ logit("WARNING: 'UsePAM no' is not supported in this build and may cause several problems."); + #ifdef WITH_OPENSSL if (options.moduli_file != NULL) @@ -19,7 +19,7 @@ diff -up openssh-8.6p1/sshd_config.log-usepam-no openssh-8.6p1/sshd_config # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and KbdInteractiveAuthentication to 'no'. -+# WARNING: 'UsePAM no' is not supported in Fedora and may cause several ++# WARNING: 'UsePAM no' is not supported in this build and may cause several +# problems. #UsePAM no diff --git a/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch index 347766d..e2a3fa2 100644 --- a/openssh-7.8p1-role-mls.patch +++ b/openssh-7.8p1-role-mls.patch @@ -23,20 +23,17 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c if ((style = strchr(user, ':')) != NULL) *style++ = 0; -@@ -314,8 +314,15 @@ input_userauth_request(int type, u_int32 - use_privsep ? " [net]" : ""); +@@ -314,7 +314,13 @@ input_userauth_request(int type, u_int32 + setproctitle("%s [net]", authctxt->valid ? user : "unknown"); authctxt->service = xstrdup(service); authctxt->style = style ? xstrdup(style) : NULL; -- if (use_privsep) +#ifdef WITH_SELINUX + authctxt->role = role ? xstrdup(role) : NULL; +#endif -+ if (use_privsep) { - mm_inform_authserv(service, style); + mm_inform_authserv(service, style); +#ifdef WITH_SELINUX + mm_inform_authrole(role); +#endif -+ } userauth_banner(ssh); if ((r = kex_server_update_ext_info(ssh)) != 0) fatal_fr(r, "kex_server_update_ext_info failed"); @@ -50,7 +47,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c + char *micuser; struct sshbuf *b; gss_buffer_desc mic, gssbuf; - const char *displayname; + u_char *p; @@ -298,7 +299,13 @@ input_gssapi_mic(int type, u_int32_t ple fatal_f("sshbuf_new failed"); mic.value = p; @@ -74,7 +71,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c + free(micuser); free(mic.value); - if ((!use_privsep || mm_is_monitor()) && + authctxt->postponed = 0; diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c --- openssh/auth2-hostbased.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/auth2-hostbased.c 2018-08-22 11:14:56.816430924 +0200 @@ -147,7 +144,7 @@ diff -up openssh/auth-pam.h.role-mls openssh/auth-pam.h +++ openssh/auth-pam.h 2018-08-22 11:14:56.817430932 +0200 @@ -33,7 +33,7 @@ u_int do_pam_account(void); void do_pam_session(struct ssh *); - void do_pam_setcred(int ); + void do_pam_setcred(void); void do_pam_chauthtok(void); -int do_pam_putenv(char *, char *); +int do_pam_putenv(char *, const char *); @@ -853,8 +850,8 @@ diff -up openssh/platform.c.role-mls openssh/platform.c } diff -up openssh/sshd.c.role-mls openssh/sshd.c ---- openssh/sshd.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/sshd.c 2018-08-22 11:14:56.820430957 +0200 +--- openssh/sshd-session.c.role-mls 2018-08-20 07:57:29.000000000 +0200 ++++ openssh/sshd-session.c 2018-08-22 11:14:56.820430957 +0200 @@ -2186,6 +2186,9 @@ main(int ac, char **av) restore_uid(); } @@ -864,4 +861,4 @@ diff -up openssh/sshd.c.role-mls openssh/sshd.c +#endif #ifdef USE_PAM if (options.use_pam) { - do_pam_setcred(1); + do_pam_setcred(); diff --git a/openssh-8.0p1-crypto-policies.patch b/openssh-8.0p1-crypto-policies.patch index 86c08db..fd1e59d 100644 --- a/openssh-8.0p1-crypto-policies.patch +++ b/openssh-8.0p1-crypto-policies.patch @@ -155,7 +155,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .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 @@ +@@ -1330,6 +1330,11 @@ it may be zero or more of: and .Cm pam . .It Cm KexAlgorithms @@ -164,8 +164,11 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x +Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. + Specifies the permitted KEX (Key Exchange) algorithms that will be used and + their preference order. + The selected algorithm will the the first algorithm in this list that +@@ -1338,28 +1343,17 @@ Multiple algorithms must be comma-separa + .Pp If the specified list begins with a .Sq + -character, then the specified algorithms will be appended to the default set @@ -181,6 +184,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Sq ^ character, then the specified algorithms will be placed at the head of the -default set. +-.Pp -The default is: -.Bd -literal -offset indent -sntrup761x25519-sha512@openssh.com, @@ -191,10 +195,11 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x -diffie-hellman-group18-sha512, -diffie-hellman-group14-sha256 -.Ed -+built-in openssh default set. .Pp - The list of available key exchange algorithms may also be obtained using ++built-in openssh default set. + The list of supported key exchange algorithms may also be obtained using .Qq ssh -Q kex . + .It Cm KnownHostsCommand @@ -1365,37 +1357,33 @@ file. This option is intended for debugging and no overrides are enabled by default. @@ -479,7 +484,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts -@@ -1044,20 +1017,25 @@ +@@ -1025,6 +1025,11 @@ Specifies whether to look at .k5login fi The default is .Cm yes . .It Cm KexAlgorithms @@ -488,9 +493,12 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x +Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page +.Xr update-crypto-policies 8 . +.Pp - Specifies the available KEX (Key Exchange) algorithms. - Multiple algorithms must be comma-separated. - Alternately if the specified list begins with a + Specifies the permitted KEX (Key Exchange) algorithms that the server will + offer to clients. + The ordering of this list is not important, as the client specifies the +@@ -1033,16 +1038,16 @@ Multiple algorithms must be comma-separa + .Pp + If the specified list begins with a .Sq + -character, then the specified algorithms will be appended to the default set -instead of replacing them. @@ -506,10 +514,10 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x character, then the specified algorithms will be placed at the head of the -default set. +built-in openssh default set. + .Pp The supported algorithms are: .Pp - .Bl -item -compact -offset indent -@@ -1089,16 +1067,6 @@ +@@ -1075,16 +1080,6 @@ ecdh-sha2-nistp521 sntrup761x25519-sha512@openssh.com .El .Pp @@ -523,7 +531,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x -diffie-hellman-group14-sha256 -.Ed -.Pp - The list of available key exchange algorithms may also be obtained using + The list of supported key exchange algorithms may also be obtained using .Qq ssh -Q KexAlgorithms . .It Cm ListenAddress @@ -1184,21 +1152,26 @@ diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index 3e5ccec..821ea49 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -3,7 +3,7 @@ index e7549470..b68c1710 100644 --- a/Makefile.in +++ b/Makefile.in @@ -109,6 +109,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ kexsntrup761x25519.o sntrup761.o kexgen.o \ + kexgssc.o \ @@ -11,14 +11,14 @@ index e7549470..b68c1710 100644 sshbuf-io.o @@ -125,7 +126,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ + auth2-chall.o groupaccess.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 \ -- auth2-gss.o gss-serv.o gss-serv-krb5.o \ -+ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \ +- monitor.o monitor_wrap.o auth-krb5.o \ ++ monitor.o monitor_wrap.o auth-krb5.o kexgsss.o \ + auth2-gss.o gss-serv.o gss-serv-krb5.o \ 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 \ + sftp-server.o sftp-common.o \ @@ -523,7 +523,7 @@ regress-prep: ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile @@ -41,117 +41,10 @@ diff -up a/auth.c.gsskex b/auth.c return 1; break; case PERMIT_FORCED_ONLY: -@@ -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. -- * This function does additional checks on the hostname to mitigate some -- * attacks on based on conflation of hostnames and IP addresses. -- */ -- --static char * --remote_hostname(struct ssh *ssh) --{ -- struct sockaddr_storage from; -- socklen_t fromlen; -- struct addrinfo hints, *ai, *aitop; -- char name[NI_MAXHOST], ntop2[NI_MAXHOST]; -- const char *ntop = ssh_remote_ipaddr(ssh); -- -- /* Get IP address of client. */ -- fromlen = sizeof(from); -- memset(&from, 0, sizeof(from)); -- if (getpeername(ssh_packet_get_connection_in(ssh), -- (struct sockaddr *)&from, &fromlen) == -1) { -- debug("getpeername failed: %.100s", strerror(errno)); -- return xstrdup(ntop); -- } -- -- ipv64_normalise_mapped(&from, &fromlen); -- if (from.ss_family == AF_INET6) -- fromlen = sizeof(struct sockaddr_in6); -- -- debug3("Trying to reverse map address %.100s.", ntop); -- /* Map the IP address to a host name. */ -- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), -- NULL, 0, NI_NAMEREQD) != 0) { -- /* Host name not found. Use ip address. */ -- return xstrdup(ntop); -- } -- -- /* -- * if reverse lookup result looks like a numeric hostname, -- * someone is trying to trick us by PTR record like following: -- * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 -- */ -- memset(&hints, 0, sizeof(hints)); -- hints.ai_socktype = SOCK_DGRAM; /*dummy*/ -- hints.ai_flags = AI_NUMERICHOST; -- if (getaddrinfo(name, NULL, &hints, &ai) == 0) { -- logit("Nasty PTR record \"%s\" is set up for %s, ignoring", -- name, ntop); -- freeaddrinfo(ai); -- return xstrdup(ntop); -- } -- -- /* Names are stored in lowercase. */ -- lowercase(name); -- -- /* -- * Map it back to an IP address and check that the given -- * address actually is an address of this host. This is -- * necessary because anyone with access to a name server can -- * define arbitrary names for an IP address. Mapping from -- * name to IP address can be trusted better (but can still be -- * fooled if the intruder has access to the name server of -- * the domain). -- */ -- memset(&hints, 0, sizeof(hints)); -- hints.ai_family = from.ss_family; -- hints.ai_socktype = SOCK_STREAM; -- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { -- logit("reverse mapping checking getaddrinfo for %.700s " -- "[%s] failed.", name, ntop); -- return xstrdup(ntop); -- } -- /* Look for the address from the list of addresses. */ -- for (ai = aitop; ai; ai = ai->ai_next) { -- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, -- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && -- (strcmp(ntop, ntop2) == 0)) -- break; -- } -- freeaddrinfo(aitop); -- /* If we reached the end of the list, the address was not there. */ -- if (ai == NULL) { -- /* Address not found for the host name. */ -- logit("Address %.100s maps to %.600s, but this does not " -- "map back to the address.", ntop, name); -- return xstrdup(ntop); -- } -- 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 9351e042..d6446c0c 100644 --- a/auth2-gss.c +++ b/auth2-gss.c -@@ -1,7 +1,7 @@ - /* $OpenBSD: auth2-gss.c,v 1.34 2023/03/31 04:22:27 djm Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions @@ -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 *); @@ -201,23 +94,21 @@ index 9351e042..d6446c0c 100644 /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) -@@ -260,7 +302,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) +@@ -260,7 +302,7 @@ 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"); -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw, 1)); +- authenticated = mm_ssh_gssapi_userok(authctxt->user); ++ authenticated = mm_ssh_gssapi_userok(authctxt->user, authctxt->pw, 1); - if ((!use_privsep || mm_is_monitor()) && - (displayname = ssh_gssapi_displayname()) != NULL) -@@ -306,7 +349,8 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) + authctxt->postponed = 0; + ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); +@@ -306,7 +349,7 @@ 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)))) -- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw, 0)); + if (!GSS_ERROR(mm_ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))) +- authenticated = mm_ssh_gssapi_userok(authctxt->user); ++ authenticated = mm_ssh_gssapi_userok(authctxt->user, authctxt->pw, 0); else logit("GSSAPI MIC check failed"); @@ -233,8 +124,8 @@ index 9351e042..d6446c0c 100644 +}; + Authmethod method_gssapi = { - "gssapi-with-mic", - NULL, + &methodcfg_gssapi, + userauth_gssapi, diff --git a/auth2.c b/auth2.c index 0e776224..1c217268 100644 --- a/auth2.c @@ -442,15 +333,6 @@ diff --git a/gss-genr.c b/gss-genr.c index d56257b4..763a63ff 100644 --- a/gss-genr.c +++ b/gss-genr.c -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-genr.c,v 1.28 2021/01/27 10:05:28 djm Exp $ */ - - /* -- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions @@ -41,9 +41,33 @@ #include "sshbuf.h" #include "log.h" @@ -735,8 +617,8 @@ index d56257b4..763a63ff 100644 + ctx = &intctx; /* RFC 4462 says we MUST NOT do SPNEGO */ - if (oid->length == spnego_oid.length && -@@ -287,6 +519,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) + if (oid->length == spnego_oid.length && +@@ -500,6 +500,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); @@ -745,13 +627,13 @@ index d56257b4..763a63ff 100644 + major = ssh_gssapi_client_identity(*ctx, client); + if (!GSS_ERROR(major)) { - major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, + major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); -@@ -296,10 +532,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +@@ -527,10 +527,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx GSS_C_NO_BUFFER); } -- if (GSS_ERROR(major)) +- if (GSS_ERROR(major)) + if (GSS_ERROR(major) || intctx != NULL) ssh_gssapi_delete_ctx(ctx); @@ -1256,20 +1138,34 @@ index ab3a15f0..6ce56e92 100644 /* Privileged */ diff --git a/kex.c b/kex.c -index ce85f043..574c7609 100644 +index a5ae6ac0..fe714141 100644 --- a/kex.c +++ b/kex.c +@@ -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); + free(kex->failed_choice); +diff --git a/kex-names.c b/kex-names.c +index ce85f043..574c7609 100644 +--- a/kex-names.c ++++ b/kex-names.c @@ -57,6 +57,10 @@ - #include "digest.h" + #include "ssherr.h" #include "xmalloc.h" +#ifdef GSSAPI +#include "ssh-gss.h" +#endif + - /* prototype */ - static int kex_choose_conf(struct ssh *, uint32_t seq); - static int kex_input_newkeys(int, u_int32_t, struct ssh *); + struct kexalg { + char *name; + u_int type; @@ -115,15 +120,28 @@ static const struct kexalg kexalgs[] = { #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ { NULL, 0, -1, -1}, @@ -1332,10 +1228,11 @@ index ce85f043..574c7609 100644 return NULL; } -@@ -315,6 +349,29 @@ kex_assemble_names(char **listp, const char *def, const char *all) +@@ -315,3 +349,26 @@ kex_assemble_names(char **listp, const char *def, const char *all) + free(ret); return r; } - ++ +/* Validate GSS KEX method name list */ +int +kex_gss_names_valid(const char *names) @@ -1358,20 +1255,6 @@ index ce85f043..574c7609 100644 + free(s); + return 1; +} -+ - /* - * 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); - free(kex->failed_choice); diff --git a/kex.h b/kex.h index a5ae6ac0..fe714141 100644 --- a/kex.h @@ -1406,16 +1289,16 @@ index a5ae6ac0..fe714141 100644 int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); @@ -174,8 +189,10 @@ struct kex { - + int kex_nid_from_name(const char *); int kex_names_valid(const char *); char *kex_alg_list(char); +char *kex_gss_alg_list(char); char *kex_names_cat(const char *, const char *); - int kex_assemble_names(char **, const char *, const char *); + int kex_has_any_alg(const char *, const char *); +int kex_gss_names_valid(const char *); + int kex_assemble_names(char **, const char *, const char *); 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 *); @@ -2873,7 +2756,7 @@ index 001a8fa1..6edb509a 100644 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, -@@ -1012,4 +1014,57 @@ mm_ssh_gssapi_userok(char *user) +@@ -1012,6 +1014,59 @@ mm_ssh_gssapi_userok(char *user) debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } @@ -2931,6 +2814,8 @@ index 001a8fa1..6edb509a 100644 +} + #endif /* GSSAPI */ + + /* diff --git a/monitor_wrap.h b/monitor_wrap.h index 23ab096a..485590c1 100644 --- a/monitor_wrap.h @@ -3107,8 +2992,8 @@ diff -up a/servconf.c.gsskex b/servconf.c #include "digest.h" +#include "ssh-gss.h" - static void add_listen_addr(ServerOptions *, const char *, - const char *, int); + #if !defined(SSHD_PAM_SERVICE) + # define SSHD_PAM_SERVICE "sshd" @@ -136,8 +137,11 @@ initialize_server_options(ServerOptions options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; @@ -3141,7 +3026,7 @@ diff -up a/servconf.c.gsskex b/servconf.c options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) @@ -506,6 +518,7 @@ typedef enum { - sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, + sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, + sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, @@ -3262,14 +3147,6 @@ diff --git a/ssh-gss.h b/ssh-gss.h index 36180d07..70dd3665 100644 --- a/ssh-gss.h +++ b/ssh-gss.h -@@ -1,6 +1,6 @@ - /* $OpenBSD: ssh-gss.h,v 1.15 2021/01/27 10:05:28 djm Exp $ */ - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions @@ -61,10 +61,34 @@ #define SSH_GSS_OIDTYPE 0x06 @@ -3523,17 +3400,8 @@ diff --git a/sshconnect2.c b/sshconnect2.c index af00fb30..03bc87eb 100644 --- a/sshconnect2.c +++ b/sshconnect2.c -@@ -80,8 +80,6 @@ - #endif - - /* import */ --extern char *client_version_string; --extern char *server_version_string; - extern Options options; - - /* @@ -163,6 +161,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) - char *s, *all_key, *hkalgs = NULL; + char *all_key, *hkalgs = NULL; int r, use_known_hosts_order = 0; +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3545,8 +3413,8 @@ index af00fb30..03bc87eb 100644 xxx_hostaddr = hostaddr; xxx_conn_info = cinfo; @@ -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), + options.kex_algorithms, options.ciphers, options.macs, + compression_alg_list(options.compression), hkalgs ? hkalgs : options.hostkeyalgorithms); + +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3587,7 +3455,7 @@ index af00fb30..03bc87eb 100644 free(hkalgs); -@@ -224,17 +256,47 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) +@@ -224,14 +256,44 @@ 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 @@ -3618,11 +3486,8 @@ index af00fb30..03bc87eb 100644 +#endif + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); + kex_proposal_free_entries(myproposal); - /* 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) + /* repair myproposal after it was crumpled by the */ + /* ext-info removal above */ @@ -3633,9 +3498,9 @@ index af00fb30..03bc87eb 100644 + free(gss); + } +#endif - if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) - fatal_r(r, "kex_prop2buf"); - + #ifdef DEBUG_KEXDH + /* send 1st encrypted/maced/compressed message */ + if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || @@ -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 *); @@ -3767,6 +3632,20 @@ diff --git a/sshd.c b/sshd.c index 60b2aaf7..d92f03aa 100644 --- a/sshd.c +++ b/sshd.c +@@ -1852,7 +1852,8 @@ main(int ac, char **av) + free(fp); + } + accumulate_host_timing_secret(cfg, NULL); +- if (!sensitive_data.have_ssh2_key) { ++ /* The GSSAPI key exchange can run without a host key */ ++ if (!sensitive_data.have_ssh2_key && !options.gss_keyex) { + logit("sshd: no hostkeys available -- exiting."); + exit(1); + } +diff --git a/sshd-session.c b/sshd-session.c +index 60b2aaf7..d92f03aa 100644 +--- a/sshd-session.c ++++ b/sshd-session.c @@ -817,8 +817,8 @@ notify_hostkeys(struct ssh *ssh) } debug3_f("sent %u hostkeys", nkeys); @@ -3778,16 +3657,6 @@ index 60b2aaf7..d92f03aa 100644 sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } -@@ -1852,7 +1852,8 @@ main(int ac, char **av) - free(fp); - } - accumulate_host_timing_secret(cfg, NULL); -- if (!sensitive_data.have_ssh2_key) { -+ /* The GSSAPI key exchange can run without a host key */ -+ if (!sensitive_data.have_ssh2_key && !options.gss_keyex) { - logit("sshd: no hostkeys available -- exiting."); - exit(1); - } @@ -2347,6 +2348,48 @@ do_ssh2_kex(struct ssh *ssh) free(hkalgs); @@ -3838,9 +3707,9 @@ index 60b2aaf7..d92f03aa 100644 if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); @@ -2362,7 +2405,18 @@ do_ssh2_kex(struct ssh *ssh) - # ifdef OPENSSL_HAS_ECC + #ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; - # endif + #endif -#endif +# ifdef GSSAPI + if (options.gss_keyex) { @@ -4036,9 +3905,9 @@ diff --git a/packet.h b/packet.h int ssh_packet_read(struct ssh *); +int ssh_packet_read_expect(struct ssh *, u_int type); - int ssh_packet_read_poll(struct ssh *); int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); + int ssh_packet_process_read(struct ssh *, int); diff --git a/packet.c b/packet.c --- a/packet.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) +++ b/packet.c (date 1703172586447) diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index 1e7940d..c3958cd 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -965,9 +965,9 @@ diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c --- openssh-9.6p1/ssh-agent.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 +++ openssh-9.6p1/ssh-agent.c 2024-01-12 14:25:25.234942360 +0100 @@ -1549,10 +1549,72 @@ add_p11_identity(struct sshkey *key, cha + idtab->nentries++; } - #ifdef ENABLE_PKCS11 +static char * +sanitize_pkcs11_provider(const char *provider) +{ diff --git a/openssh-8.7p1-minrsabits.patch b/openssh-8.7p1-minrsabits.patch index 479b55d..d8577d2 100644 --- a/openssh-8.7p1-minrsabits.patch +++ b/openssh-8.7p1-minrsabits.patch @@ -19,4 +19,4 @@ diff --git a/servconf.c b/servconf.c + { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */ { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, - { NULL, sBadOption, 0 } + { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, diff --git a/openssh-8.7p1-negotiate-supported-algs.patch b/openssh-8.7p1-negotiate-supported-algs.patch index ee3637f..c4d86e7 100644 --- a/openssh-8.7p1-negotiate-supported-algs.patch +++ b/openssh-8.7p1-negotiate-supported-algs.patch @@ -79,12 +79,12 @@ diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c 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; +- char *all_key, *hkalgs = NULL; ++ char *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 +@@ -260,10 +260,22 @@ ssh_kex2(struct ssh *ssh, char *host, st if (use_known_hosts_order) hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo); @@ -100,8 +100,9 @@ diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c + options.hostkeyalgorithms, options.pubkey_accepted_algos); + } + - kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers, - options.macs, compression_alg_list(options.compression), + kex_proposal_populate_entries(ssh, myproposal, + options.kex_algorithms, options.ciphers, options.macs, + compression_alg_list(options.compression), - hkalgs ? hkalgs : options.hostkeyalgorithms); + filtered_algs); diff --git a/openssh-8.7p1-nohostsha1proof.patch b/openssh-8.7p1-nohostsha1proof.patch index 6a6b63d..d23e3e6 100644 --- a/openssh-8.7p1-nohostsha1proof.patch +++ b/openssh-8.7p1-nohostsha1proof.patch @@ -148,15 +148,6 @@ diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p ASSERT_PTR_NE(keyname, NULL); kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); -@@ -180,7 +181,7 @@ do_kex(char *kex) - { - #ifdef WITH_OPENSSL - do_kex_with_key(kex, KEY_RSA, 2048); -- do_kex_with_key(kex, KEY_DSA, 1024); -+ /* do_kex_with_key(kex, KEY_DSA, 1024); */ - #ifdef OPENSSL_HAS_ECC - do_kex_with_key(kex, KEY_ECDSA, 256); - #endif /* OPENSSL_HAS_ECC */ diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_file.c --- openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck 2023-01-26 12:04:55.946343408 +0100 +++ openssh-8.7p1/regress/unittests/sshkey/test_file.c 2023-01-26 12:06:35.235164432 +0100 @@ -196,22 +187,6 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh- TEST_START("fuzz RSA SHA256 sig"); buf = load_file("rsa_1"); -@@ -357,6 +358,7 @@ sshkey_fuzz_tests(void) - sshkey_free(k1); - TEST_DONE(); - -+ /* Skip this test, SHA1 signatures are not supported - TEST_START("fuzz DSA sig"); - buf = load_file("dsa_1"); - ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); -@@ -364,6 +366,7 @@ sshkey_fuzz_tests(void) - sig_fuzz(k1, NULL); - sshkey_free(k1); - TEST_DONE(); -+ */ - - #ifdef OPENSSL_HAS_ECC - TEST_START("fuzz ECDSA sig"); diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c --- openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck 2023-01-26 11:02:52.339413463 +0100 +++ openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c 2023-01-26 11:58:42.324253896 +0100 @@ -277,21 +252,6 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4), SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); ASSERT_PTR_EQ(k4, NULL); -diff -up openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck openssh-8.7p1/regress/unittests/sshsig/tests.c ---- openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck 2023-01-26 12:19:23.659513651 +0100 -+++ openssh-8.7p1/regress/unittests/sshsig/tests.c 2023-01-26 12:20:28.021044803 +0100 -@@ -102,9 +102,11 @@ tests(void) - check_sig("rsa.pub", "rsa.sig", msg, namespace); - TEST_DONE(); - -+ /* Skip this test, SHA1 signatures are not supported - TEST_START("check DSA signature"); - check_sig("dsa.pub", "dsa.sig", msg, namespace); - TEST_DONE(); -+ */ - - #ifdef OPENSSL_HAS_ECC - TEST_START("check ECDSA signature"); diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c --- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100 +++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100 @@ -336,13 +296,13 @@ diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c --- openssh-8.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100 +++ openssh-8.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100 @@ -1640,6 +1651,7 @@ main(int ac, char **av) - Authctxt *authctxt; - struct connection_info *connection_info = NULL; + struct sshkey *pubkey; + struct connection_info connection_info; sigset_t sigmask; + int forbid_ssh_rsa = 0; + memset(&connection_info, 0, sizeof(connection_info)); #ifdef HAVE_SECUREWARE - (void)set_auth_parameters(ac, av); @@ -1938,6 +1950,33 @@ main(int ac, char **av) key = NULL; continue; @@ -377,16 +337,6 @@ diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c if (sshkey_is_sk(key) && key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { debug("host key %s requires user presence, ignoring", -@@ -2275,6 +2306,9 @@ main(int ac, char **av) - - check_ip_options(ssh); - -+ if (forbid_ssh_rsa) -+ ssh->compat |= SSH_RH_RSASIGSHA; -+ - /* Prepare the channels layer */ - channel_init_channels(ssh); - channel_set_af(ssh, options.address_family); diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c --- openssh-8.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100 +++ openssh-8.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100 diff --git a/openssh-9.8p1-systemd.patch b/openssh-9.8p1-systemd.patch deleted file mode 100644 index b20624e..0000000 --- a/openssh-9.8p1-systemd.patch +++ /dev/null @@ -1,201 +0,0 @@ -diff --git a/configure.ac b/configure.ac -index 379cd746b..15e2ecdb7 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -907,6 +907,7 @@ int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) - AC_DEFINE([_PATH_BTMP], ["/var/log/btmp"], [log for bad login attempts]) - AC_DEFINE([USE_BTMP]) - AC_DEFINE([LINUX_OOM_ADJUST], [1], [Adjust Linux out-of-memory killer]) -+ AC_DEFINE([SYSTEMD_NOTIFY], [1], [Have sshd notify systemd on start/reload]) - inet6_default_4in6=yes - case `uname -r` in - 1.*|2.0.*) -diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c -index 0457e28d0..df7290246 100644 ---- a/openbsd-compat/port-linux.c -+++ b/openbsd-compat/port-linux.c -@@ -21,16 +21,23 @@ - - #include "includes.h" - --#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) -+#if defined(WITH_SELINUX) || defined(LINUX_OOM_ADJUST) || \ -+ defined(SYSTEMD_NOTIFY) -+#include -+#include -+ - #include -+#include - #include - #include - #include - #include -+#include - - #include "log.h" - #include "xmalloc.h" - #include "port-linux.h" -+#include "misc.h" - - #ifdef WITH_SELINUX - #include -@@ -310,4 +317,90 @@ oom_adjust_restore(void) - return; - } - #endif /* LINUX_OOM_ADJUST */ --#endif /* WITH_SELINUX || LINUX_OOM_ADJUST */ -+ -+#ifdef SYSTEMD_NOTIFY -+ -+static void ssh_systemd_notify(const char *, ...) -+ __attribute__((__format__ (printf, 1, 2))) __attribute__((__nonnull__ (1))); -+ -+static void -+ssh_systemd_notify(const char *fmt, ...) -+{ -+ char *s = NULL; -+ const char *path; -+ struct stat sb; -+ struct sockaddr_un addr; -+ int fd = -1; -+ va_list ap; -+ -+ if ((path = getenv("NOTIFY_SOCKET")) == NULL || strlen(path) == 0) -+ return; -+ -+ va_start(ap, fmt); -+ xvasprintf(&s, fmt, ap); -+ va_end(ap); -+ -+ /* Only AF_UNIX is supported, with path or abstract sockets */ -+ if (path[0] != '/' && path[0] != '@') { -+ error_f("socket \"%s\" is not compatible with AF_UNIX", path); -+ goto out; -+ } -+ -+ if (path[0] == '/' && stat(path, &sb) != 0) { -+ error_f("socket \"%s\" stat: %s", path, strerror(errno)); -+ goto out; -+ } -+ -+ memset(&addr, 0, sizeof(addr)); -+ addr.sun_family = AF_UNIX; -+ if (strlcpy(addr.sun_path, path, -+ sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) { -+ error_f("socket path \"%s\" too long", path); -+ goto out; -+ } -+ /* Support for abstract socket */ -+ if (addr.sun_path[0] == '@') -+ addr.sun_path[0] = 0; -+ if ((fd = socket(PF_UNIX, SOCK_DGRAM, 0)) == -1) { -+ error_f("socket \"%s\": %s", path, strerror(errno)); -+ goto out; -+ } -+ if (connect(fd, &addr, sizeof(addr)) != 0) { -+ error_f("socket \"%s\" connect: %s", path, strerror(errno)); -+ goto out; -+ } -+ if (write(fd, s, strlen(s)) != (ssize_t)strlen(s)) { -+ error_f("socket \"%s\" write: %s", path, strerror(errno)); -+ goto out; -+ } -+ debug_f("socket \"%s\" notified %s", path, s); -+ out: -+ if (fd != -1) -+ close(fd); -+ free(s); -+} -+ -+void -+ssh_systemd_notify_ready(void) -+{ -+ ssh_systemd_notify("READY=1"); -+} -+ -+void -+ssh_systemd_notify_reload(void) -+{ -+ struct timespec now; -+ -+ monotime_ts(&now); -+ if (now.tv_sec < 0 || now.tv_nsec < 0) { -+ error_f("monotime returned negative value"); -+ ssh_systemd_notify("RELOADING=1"); -+ } else { -+ ssh_systemd_notify("RELOADING=1\nMONOTONIC_USEC=%llu", -+ ((uint64_t)now.tv_sec * 1000000ULL) + -+ ((uint64_t)now.tv_nsec / 1000ULL)); -+ } -+} -+#endif /* SYSTEMD_NOTIFY */ -+ -+#endif /* WITH_SELINUX || LINUX_OOM_ADJUST || SYSTEMD_NOTIFY */ -diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h -index 3c22a854d..14064f87d 100644 ---- a/openbsd-compat/port-linux.h -+++ b/openbsd-compat/port-linux.h -@@ -30,4 +30,9 @@ void oom_adjust_restore(void); - void oom_adjust_setup(void); - #endif - -+#ifdef SYSTEMD_NOTIFY -+void ssh_systemd_notify_ready(void); -+void ssh_systemd_notify_reload(void); -+#endif -+ - #endif /* ! _PORT_LINUX_H */ -diff --git a/platform.c b/platform.c -index 4fe8744ee..9cf818153 100644 ---- a/platform.c -+++ b/platform.c -@@ -44,6 +44,14 @@ platform_pre_listen(void) - #endif - } - -+void -+platform_post_listen(void) -+{ -+#ifdef SYSTEMD_NOTIFY -+ ssh_systemd_notify_ready(); -+#endif -+} -+ - void - platform_pre_fork(void) - { -@@ -55,6 +63,9 @@ platform_pre_fork(void) - void - platform_pre_restart(void) - { -+#ifdef SYSTEMD_NOTIFY -+ ssh_systemd_notify_reload(); -+#endif - #ifdef LINUX_OOM_ADJUST - oom_adjust_restore(); - #endif -diff --git a/platform.h b/platform.h -index 7fef8c983..5dec23276 100644 ---- a/platform.h -+++ b/platform.h -@@ -21,6 +21,7 @@ - void platform_pre_listen(void); - void platform_pre_fork(void); - void platform_pre_restart(void); -+void platform_post_listen(void); - void platform_post_fork_parent(pid_t child_pid); - void platform_post_fork_child(void); - int platform_privileged_uidswap(void); -diff --git a/sshd.c b/sshd.c -index 9cbe92293..3c3f2dd6b 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -2077,6 +2077,8 @@ main(int ac, char **av) - ssh_signal(SIGTERM, sigterm_handler); - ssh_signal(SIGQUIT, sigterm_handler); - -+ platform_post_listen(); -+ - /* - * Write out the pid file after the sigterm handler - * is setup and the listen sockets are bound diff --git a/openssh.spec b/openssh.spec index fc82b78..c158d1b 100644 --- a/openssh.spec +++ b/openssh.spec @@ -46,15 +46,15 @@ %{?static_openssl:%global static_libcrypto 1} # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%global openssh_ver 9.6p1 +%global openssh_ver 9.8p1 %global openssh_rel 1 %global pam_ssh_agent_ver 0.10.4 -%global pam_ssh_agent_rel 9 +%global pam_ssh_agent_rel 10 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.14 +Release: %{openssh_rel}%{?dist} URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -177,8 +177,6 @@ Patch926: openssh-6.7p1-sftp-force-permission.patch Patch939: openssh-7.2p2-s390-closefrom.patch # Move MAX_DISPLAYS to a configuration option (#1341302) Patch944: openssh-7.3p1-x11-max-displays.patch -# Help systemd to track the running service -Patch948: openssh-9.8p1-systemd.patch # Pass inetd flags for SELinux down to openbsd compat level Patch949: openssh-7.6p1-cleanup-selinux.patch # Sandbox adjustments for s390 and audit @@ -236,8 +234,6 @@ Patch1014: openssh-8.7p1-nohostsha1proof.patch Patch1015: openssh-9.6p1-pam-rhost.patch -Patch1016: CVE-2024-6387.patch - License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -312,7 +308,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.14 +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist} License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -409,7 +405,6 @@ popd %patch -P 926 -p1 -b .sftp-force-mode %patch -P 939 -p1 -b .s390-dev %patch -P 944 -p1 -b .x11max -%patch -P 948 -p1 -b .systemd %patch -P 949 -p1 -b .refactor %patch -P 950 -p1 -b .sandbox %patch -P 951 -p1 -b .pkcs11-uri @@ -442,7 +437,6 @@ popd %patch -P 1013 -p1 -b .evp-fips-ecdh %patch -P 1014 -p1 -b .nosha1hostproof %patch -P 1015 -p1 -b .pam-rhost -%patch -P 1016 -p1 -b .cve-2024-6387 %patch -P 100 -p1 -b .coverity @@ -751,6 +745,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Mon Jul 22 2024 Dmitry Belyavskiy - 9.8p1-1 +- Update to OpenSSH 9.8p1 + * Thu Jul 18 2024 Fedora Release Engineering - 9.6p1-1.14 - Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild diff --git a/sources b/sources index 62f22c0..dc4d818 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (openssh-9.6p1.tar.gz) = 0ebf81e39914c3a90d7777a001ec7376a94b37e6024baf3e972c58f0982b7ddef942315f5e01d56c00ff95603b4a20ee561ab918ecc55511df007ac138160509 -SHA512 (openssh-9.6p1.tar.gz.asc) = aec5a5bd6ce480a8e5b5879dc55f8186aec90fe61f085aa92ad7d07f324574aa781be09c83b7443a32848d091fd44fb12c1842d49cee77afc351e550ffcc096d +SHA512 (openssh-9.8p1.tar.gz) = 95dec2f18e58eb47994f3de4430253e0665e185564b65088ca5f4108870e05feddef8cda8d3c0a4b75f18b98cc2c024df0e27de53b48c1a16da8da483cb8292a +SHA512 (openssh-9.8p1.tar.gz.asc) = 4df1f1be2c6ab7f3aebaedd0a773b0e8c8929abb30cd3415873ad55d012cfa113f792e888e5e772dd468c394aeb7e35d62893a514dbc0ab1a03acd79918657f7 SHA512 (pam_ssh_agent_auth-0.10.4.tar.gz) = caccf72174d15e43f4c86a459ac6448682e62116557cf1e1e828955f3d1731595b238df42adec57860e7f341e92daf5d8285020bcb5018f3b8a5145aa32ee1c2 SHA512 (gpgkey-736060BA.gpg) = df44f3fdbcd1d596705348c7f5aed3f738c5f626a55955e0642f7c6c082995cf36a1b1891bb41b8715cb2aff34fef1c877e0eff0d3507dd00a055ba695757a21 From cae81de8e8085d43bcd3be695b6e71c5495aa8e8 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 12 Jul 2024 13:20:45 +0200 Subject: [PATCH 33/80] Eliminating PRIVSEP because of OpenSSH architecture changes --- openssh-6.6p1-privsep-selinux.patch | 2 +- openssh-7.1p2-audit-race-condition.patch | 11 +++-- openssh-7.6p1-audit.patch | 51 +++++++----------------- openssh-7.7p1-gssapi-new-unique.patch | 2 +- openssh-8.0p1-gssapi-keyex.patch | 37 ++++++++--------- openssh-9.6p1-gsskex-new-api.patch | 32 +++++++-------- 6 files changed, 53 insertions(+), 82 deletions(-) diff --git a/openssh-6.6p1-privsep-selinux.patch b/openssh-6.6p1-privsep-selinux.patch index 023dd5c..16d98cd 100644 --- a/openssh-6.6p1-privsep-selinux.patch +++ b/openssh-6.6p1-privsep-selinux.patch @@ -49,7 +49,7 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c platform_setusercontext(pw); - if (platform_privileged_uidswap()) { -+ if (platform_privileged_uidswap() && (!is_child || !use_privsep)) { ++ if (platform_privileged_uidswap() && !is_child) { #ifdef HAVE_LOGIN_CAP if (setusercontext(lc, pw, pw->pw_uid, (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { diff --git a/openssh-7.1p2-audit-race-condition.patch b/openssh-7.1p2-audit-race-condition.patch index 1d2bf3b..57ad148 100644 --- a/openssh-7.1p2-audit-race-condition.patch +++ b/openssh-7.1p2-audit-race-condition.patch @@ -121,7 +121,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c +#ifdef SSH_AUDIT_EVENTS + close(paudit[1]); -+ if (use_privsep && ret == 0) { ++ if (ret == 0) { + /* + * Read the audit messages from forked child and send them + * back to monitor. We don't want to communicate directly, @@ -136,7 +136,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c return ret; } -@@ -1538,6 +1565,34 @@ child_close_fds(void) +@@ -1538,6 +1565,33 @@ child_close_fds(void) log_redirect_stderr_to(NULL); } @@ -147,12 +147,11 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c + int pparent = paudit[1]; + close(paudit[0]); + /* Hack the monitor pipe to avoid race condition with parent */ -+ if (use_privsep) -+ mm_set_monitor_pipe(pparent); ++ mm_set_monitor_pipe(pparent); +#endif + + /* remove hostkey from the child's memory */ -+ destroy_sensitive_data(ssh, use_privsep); ++ destroy_sensitive_data(ssh); + /* + * We can audit this, because we hacked the pipe to direct the + * messages over postauth child. But this message requires answer @@ -176,7 +175,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); - /* remove hostkey from the child's memory */ -- destroy_sensitive_data(ssh, 1); +- destroy_sensitive_data(ssh); - ssh_packet_clear_keys(ssh); - /* Don't audit this - both us and the parent would be talking to the - monitor over a single socket, with no synchronization. */ diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index 8d06a6d..de21407 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -129,19 +129,19 @@ diff -up openssh-8.6p1/audit.c.audit openssh-8.6p1/audit.c +void +audit_unsupported(struct ssh *ssh, int what) +{ -+ PRIVSEP(audit_unsupported_body(ssh, what)); ++ mm_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())); ++ mm_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())); ++ mm_audit_session_key_free_body(ssh, ctos, getpid(), getuid()); +} + # ifndef CUSTOM_SSH_AUDIT_EVENTS @@ -1108,7 +1108,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ -+extern void destroy_sensitive_data(struct ssh *, int); ++extern void destroy_sensitive_data(struct ssh *); + /* State exported from the child */ static struct sshbuf *child_state; @@ -1241,7 +1241,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c sshpam_cleanup(); #endif -+ destroy_sensitive_data(ssh, 0); ++ destroy_sensitive_data(ssh); + while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) @@ -1817,7 +1817,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c extern u_int utmp_len; extern int startup_pipe; -extern void destroy_sensitive_data(void); -+extern void destroy_sensitive_data(struct ssh *, int); ++extern void destroy_sensitive_data(struct ssh *); extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; extern char *tun_fwd_ifnames; /* serverloop.c */ @@ -1863,7 +1863,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c /* remove hostkey from the child's memory */ - destroy_sensitive_data(); -+ destroy_sensitive_data(ssh, 1); ++ destroy_sensitive_data(ssh); ssh_packet_clear_keys(ssh); + /* Don't audit this - both us and the parent would be talking to the + monitor over a single socket, with no synchronization. */ @@ -1923,7 +1923,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c +{ + if (s->command != NULL) { + if (s->command_handle != -1) -+ PRIVSEP(audit_end_command(ssh, s->command_handle, s->command)); ++ mm_audit_end_command(ssh, s->command_handle, s->command); + free(s->command); + s->command = NULL; + s->command_handle = -1; @@ -2036,32 +2036,14 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c /* Allocate and initialise the children array */ static void child_alloc(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, - int log_stderr) - { - struct pollfd *pfd = NULL; @@ -1204,6 +1259,7 @@ server_accept_loop(int *sock_in, int *so if (received_sigterm) { logit("Received signal %d; terminating.", (int) received_sigterm); -+ destroy_sensitive_data(ssh, 0); ++ /* destroy_sensitive_data(ssh, 0); FIXME */ close_listen_socks(); if (options.pid_file != NULL) unlink(options.pid_file); -@@ -2189,7 +2189,7 @@ - } - - /* Accept a connection and return in a forked child */ -- server_accept_loop(&sock_in, &sock_out, -+ server_accept_loop(ssh, &sock_in, &sock_out, - &newsock, config_s, log_stderr); - } - diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c --- openssh-8.6p1/sshd-session.c.audit 2021-04-19 16:47:35.727061907 +0200 +++ openssh-8.6p1/sshd-session.c 2021-04-19 16:47:35.759062152 +0200 @@ -2079,12 +2061,12 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c /* Prototypes for various functions defined later in this file. */ -void destroy_sensitive_data(void); -void demote_sensitive_data(void); -+void destroy_sensitive_data(struct ssh *, int); ++void destroy_sensitive_data(struct ssh *); +void demote_sensitive_data(struct ssh *); static void do_ssh2_kex(struct ssh *); /* -@@ -377,18 +387,45 @@ grace_alarm_handler(int sig) +@@ -377,18 +387,40 @@ grace_alarm_handler(int sig) _exit(EXIT_LOGIN_GRACE); } @@ -2095,7 +2077,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c + */ void -destroy_sensitive_data(void) -+destroy_sensitive_data(struct ssh *ssh, int privsep) ++destroy_sensitive_data(struct ssh *ssh) { u_int i; +#ifdef SSH_AUDIT_EVENTS @@ -2117,12 +2099,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c sensitive_data.host_keys[i] = NULL; + if (fp != NULL) { +#ifdef SSH_AUDIT_EVENTS -+ if (privsep) -+ PRIVSEP(audit_destroy_sensitive_data(ssh, fp, -+ pid, uid)); -+ else -+ audit_destroy_sensitive_data(ssh, fp, -+ pid, uid); ++ audit_destroy_sensitive_data(ssh, fp, pid, uid); +#endif + free(fp); + } @@ -2223,7 +2200,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c /* The connection has been terminated. */ + packet_destroy_all(ssh, 1, 1); -+ destroy_sensitive_data(ssh, 1); ++ destroy_sensitive_data(ssh); + ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", diff --git a/openssh-7.7p1-gssapi-new-unique.patch b/openssh-7.7p1-gssapi-new-unique.patch index 1f70be2..0b8ab02 100644 --- a/openssh-7.7p1-gssapi-new-unique.patch +++ b/openssh-7.7p1-gssapi-new-unique.patch @@ -368,7 +368,7 @@ diff -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c + if (gssapi_client.store.envval == NULL) return; - ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); + ok = mm_ssh_gssapi_update_creds(&gssapi_client.store); diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c --- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-04-19 14:05:10.852744562 +0200 +++ openssh-8.6p1/gss-serv-krb5.c 2021-04-19 14:05:10.854744577 +0200 diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index 821ea49..b3832c3 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -80,10 +80,10 @@ index 9351e042..d6446c0c 100644 + gssbuf.length = sshbuf_len(b); + + /* gss_kex_context is NULL with privsep, so we can't check it here */ -+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, -+ &gssbuf, &mic)))) -+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw, 1)); ++ if (!GSS_ERROR(mm_ssh_gssapi_checkmic(gss_kex_context, ++ &gssbuf, &mic))) ++ authenticated = mm_ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 1); + + sshbuf_free(b); + free(mic.value); @@ -894,7 +894,7 @@ index ab3a15f0..6ce56e92 100644 + Gssctxt *ctx = NULL; + int res; + -+ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); ++ res = !GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctx, oid)); + ssh_gssapi_delete_ctx(&ctx); + + return (res); @@ -1040,7 +1040,7 @@ index ab3a15f0..6ce56e92 100644 /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); -@@ -382,14 +471,90 @@ ssh_gssapi_userok(char *user) +@@ -382,14 +471,85 @@ ssh_gssapi_userok(char *user) return (0); } @@ -1083,7 +1083,7 @@ index ab3a15f0..6ce56e92 100644 + gssapi_client.store.envvar == NULL) + return; + -+ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); ++ ok = mm_ssh_gssapi_update_creds(&gssapi_client.store); + + if (!ok) + return; @@ -1095,11 +1095,6 @@ index ab3a15f0..6ce56e92 100644 + * for rekeying. So, use our own :) + */ +#ifdef USE_PAM -+ if (!use_privsep) { -+ debug("Not even going to try and do PAM with privsep disabled"); -+ return; -+ } -+ + ret = pam_start("sshd-rekey", gssapi_client.store.owner->pw_name, + &pamconv, &pamh); + if (ret) @@ -2088,7 +2083,7 @@ index 00000000..60bc02de + + debug2_f("Acquiring credentials"); + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) + fatal("Unable to acquire credentials for the server"); + + do { @@ -2165,8 +2160,8 @@ index 00000000..60bc02de + type); + } + -+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags)); ++ maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags); + + gss_release_buffer(&min_status, &recv_tok); + @@ -2202,7 +2197,7 @@ index 00000000..60bc02de + if (!(ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || @@ -2292,7 +2287,7 @@ index 00000000..60bc02de + + debug2_f("Acquiring credentials"); + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) + fatal("Unable to acquire credentials for the server"); + + /* 5. S generates an ephemeral key pair (do the allocations early) */ @@ -2314,7 +2309,7 @@ index 00000000..60bc02de + if (max < min || nbits < min || max < nbits) + fatal("GSS_GEX, bad parameters: %d !< %d !< %d", + min, nbits, max); -+ kex->dh = PRIVSEP(choose_dh(min, nbits, max)); ++ kex->dh = mm_choose_dh(min, nbits, max); + if (kex->dh == NULL) { + sshpkt_disconnect(ssh, "Protocol error: no matching group found"); + fatal("Protocol error: no matching group found"); @@ -2361,8 +2356,8 @@ index 00000000..60bc02de + type); + } + -+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags)); ++ maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags); + + gss_release_buffer(&min_status, &recv_tok); + @@ -2427,7 +2422,7 @@ index 00000000..60bc02de + gssbuf.value = hash; + gssbuf.length = hashlen; + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || diff --git a/openssh-9.6p1-gsskex-new-api.patch b/openssh-9.6p1-gsskex-new-api.patch index ed09319..6a536fc 100644 --- a/openssh-9.6p1-gsskex-new-api.patch +++ b/openssh-9.6p1-gsskex-new-api.patch @@ -1163,8 +1163,8 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c debug2_f("Acquiring credentials"); -- if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&kex->gss, oid)))) +- if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&kex->gss, oid))) fatal("Unable to acquire credentials for the server"); - do { @@ -1258,9 +1258,9 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + Gssctxt *gss = ssh->kex->gss; + int r; -- maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -- &send_tok, &ret_flags)); -+ gss->major = PRIVSEP(ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags)); +- maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, +- &send_tok, &ret_flags); ++ gss->major = mm_ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags); + gss_release_buffer(&gss->minor, recv_tok); - gss_release_buffer(&min_status, &recv_tok); @@ -1327,8 +1327,8 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + if (!(*ret_flags & GSS_C_INTEG_FLAG)) fatal("Integrity flag wasn't set"); -- if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(gss, &gss->buf, &msg_tok)))) +- if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(gss, &gss->buf, &msg_tok))) fatal("Couldn't get MIC"); if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || @@ -1537,8 +1537,8 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c debug2_f("Acquiring credentials"); -- if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&kex->gss, oid)))) +- if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&kex->gss, oid))) fatal("Unable to acquire credentials for the server"); - /* 5. S generates an ephemeral key pair (do the allocations early) */ @@ -1560,7 +1560,7 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c - if (max < min || nbits < min || max < nbits) - fatal("GSS_GEX, bad parameters: %d !< %d !< %d", - min, nbits, max); -- kex->dh = PRIVSEP(choose_dh(min, nbits, max)); +- kex->dh = mm_choose_dh(min, nbits, max); - if (kex->dh == NULL) { - sshpkt_disconnect(ssh, "Protocol error: no matching group found"); - fatal("Protocol error: no matching group found"); @@ -1621,11 +1621,11 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c - "Protocol error: didn't expect packet type %d", - type); - } -+ gss->major = PRIVSEP(ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags)); ++ gss->major = mm_ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags); + gss_release_buffer(&gss->minor, recv_tok); -- maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -- &send_tok, &ret_flags)); +- maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, +- &send_tok, &ret_flags); + if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) + fatal("Zero length token output when incomplete"); @@ -1744,8 +1744,8 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + gss->buf.value = hash; + gss->buf.length = hashlen; -- if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(gss, &gss->buf, &msg_tok)))) +- if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(gss, &gss->buf, &msg_tok))) fatal("Couldn't get MIC"); if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || @@ -1833,7 +1833,7 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + if (max < min || nbits < min || max < nbits) + fatal("GSS_GEX, bad parameters: %d !< %d !< %d", min, nbits, max); + -+ kex->dh = PRIVSEP(choose_dh(min, nbits, max)); ++ kex->dh = mm_choose_dh(min, nbits, max); + if (kex->dh == NULL) { + sshpkt_disconnect(ssh, "Protocol error: no matching group found"); + fatal("Protocol error: no matching group found"); From 1f22cfd0ddf000e11d4b306c69b7a50f19fa0313 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 12 Jul 2024 13:38:48 +0200 Subject: [PATCH 34/80] Eliminate reexec_flag --- openssh-6.6p1-keycat.patch | 4 ++-- openssh-7.6p1-cleanup-selinux.patch | 21 +++++++++------------ openssh-7.8p1-role-mls.patch | 7 +++---- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/openssh-6.6p1-keycat.patch b/openssh-6.6p1-keycat.patch index 7339185..4eb0998 100644 --- a/openssh-6.6p1-keycat.patch +++ b/openssh-6.6p1-keycat.patch @@ -95,8 +95,8 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ --- openssh/openbsd-compat/port-linux-sshd.c.keycat 2015-06-24 10:57:50.150849626 +0200 +++ openssh/openbsd-compat/port-linux-sshd.c 2015-06-24 10:57:50.159849603 +0200 @@ -54,6 +54,20 @@ extern Authctxt *the_authctxt; + extern Authctxt *the_authctxt; extern int inetd_flag; - extern int rexeced_flag; +/* Wrapper around is_selinux_enabled() to log its return value once only */ +int @@ -131,7 +131,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ - rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); + rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); - if (inetd_flag && !rexeced_flag) { + if (inetd_flag) { use_current = "1"; } else { use_current = ""; diff --git a/openssh-7.6p1-cleanup-selinux.patch b/openssh-7.6p1-cleanup-selinux.patch index 5b8aaca..cfe11ad 100644 --- a/openssh-7.6p1-cleanup-selinux.patch +++ b/openssh-7.6p1-cleanup-selinux.patch @@ -1,12 +1,11 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c --- openssh/auth2-pubkey.c.refactor 2019-04-04 13:19:12.188821236 +0200 +++ openssh/auth2-pubkey.c 2019-04-04 13:19:12.276822078 +0200 -@@ -72,6 +72,9 @@ +@@ -72,6 +72,8 @@ /* import */ extern ServerOptions options; +extern int inetd_flag; -+extern int rexeced_flag; +extern Authctxt *the_authctxt; extern struct authmethod_cfg methodcfg_pubkey; @@ -17,7 +16,7 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, - runas_pw, temporarily_use_uid, restore_uid)) == 0) + runas_pw, temporarily_use_uid, restore_uid, -+ (inetd_flag && !rexeced_flag), the_authctxt)) == 0) ++ inetd_flag, the_authctxt)) == 0) goto out; uid_swapped = 1; @@ -27,7 +26,7 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, - runas_pw, temporarily_use_uid, restore_uid)) == 0) + runas_pw, temporarily_use_uid, restore_uid, -+ (inetd_flag && !rexeced_flag), the_authctxt)) == 0) ++ inetd_flag, the_authctxt)) == 0) goto out; uid_swapped = 1; @@ -82,14 +81,13 @@ diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/por diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c --- openssh/openbsd-compat/port-linux-sshd.c.refactor 2019-04-04 13:19:12.256821887 +0200 +++ openssh/openbsd-compat/port-linux-sshd.c 2019-04-04 13:19:12.276822078 +0200 -@@ -49,11 +49,6 @@ +@@ -49,10 +49,6 @@ #include #endif -extern ServerOptions options; -extern Authctxt *the_authctxt; -extern int inetd_flag; --extern int rexeced_flag; - /* Wrapper around is_selinux_enabled() to log its return value once only */ int @@ -128,7 +126,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa if (r == 0) { /* If launched from xinetd, we must use current level */ -- if (inetd_flag && !rexeced_flag) { +- if (inetd_flag) { + if (inetd) { security_context_t sshdsc=NULL; @@ -152,7 +150,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : ""); -- if (inetd_flag && !rexeced_flag) { +- if (inetd_flag) { + if (inetd) { use_current = "1"; } else { @@ -216,12 +214,11 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa diff -up openssh/platform.c.refactor openssh/platform.c --- openssh/platform.c.refactor 2019-04-04 13:19:12.204821389 +0200 +++ openssh/platform.c 2019-04-04 13:19:12.277822088 +0200 -@@ -32,6 +32,9 @@ +@@ -32,6 +32,8 @@ #include "openbsd-compat/openbsd-compat.h" extern ServerOptions options; +extern int inetd_flag; -+extern int rexeced_flag; +extern Authctxt *the_authctxt; /* return 1 if we are running with privilege to swap UIDs, 0 otherwise */ @@ -232,7 +229,7 @@ diff -up openssh/platform.c.refactor openssh/platform.c #ifdef WITH_SELINUX - sshd_selinux_setup_exec_context(pw->pw_name); + sshd_selinux_setup_exec_context(pw->pw_name, -+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt, ++ inetd_flag, do_pam_putenv, the_authctxt, + options.use_pam); #endif } @@ -255,7 +252,7 @@ diff -up openssh/sshd-session.c.refactor openssh/sshd-session.c #ifdef WITH_SELINUX - sshd_selinux_setup_exec_context(authctxt->pw->pw_name); + sshd_selinux_setup_exec_context(authctxt->pw->pw_name, -+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt, ++ inetd_flag, do_pam_putenv, the_authctxt, + options.use_pam); #endif #ifdef USE_PAM diff --git a/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch index e2a3fa2..7c6d0ca 100644 --- a/openssh-7.8p1-role-mls.patch +++ b/openssh-7.8p1-role-mls.patch @@ -415,7 +415,7 @@ diff -up openssh/openbsd-compat/port-linux.h.role-mls openssh/openbsd-compat/por diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compat/port-linux-sshd.c --- openssh/openbsd-compat/port-linux-sshd.c.role-mls 2018-08-22 11:14:56.819430949 +0200 +++ openssh/openbsd-compat/port-linux-sshd.c 2018-08-22 11:14:56.819430949 +0200 -@@ -0,0 +1,421 @@ +@@ -0,0 +1,420 @@ +/* + * Copyright (c) 2005 Daniel Walsh + * Copyright (c) 2014 Petr Lautrbach @@ -469,7 +469,6 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa +extern ServerOptions options; +extern Authctxt *the_authctxt; +extern int inetd_flag; -+extern int rexeced_flag; + +/* Send audit message */ +static int @@ -675,7 +674,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + + if (r == 0) { + /* If launched from xinetd, we must use current level */ -+ if (inetd_flag && !rexeced_flag) { ++ if (inetd_flag) { + security_context_t sshdsc=NULL; + + if (getcon_raw(&sshdsc) < 0) @@ -749,7 +748,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa + + rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : ""); + -+ if (inetd_flag && !rexeced_flag) { ++ if (inetd_flag) { + use_current = "1"; + } else { + use_current = ""; From b46d13eb96c22d44c5bb6327e5fe5a8e8cae414b Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 12 Jul 2024 15:16:09 +0200 Subject: [PATCH 35/80] listening_for_clients - comment out --- openssh-7.6p1-audit.patch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index de21407..c1d8dde 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -661,7 +661,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c + } + audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, + buf, NULL, -+ listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh), ++ ssh_remote_ipaddr(ssh), /*FIXME 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 */ From 207f4964a4066fd2a8dfb6c73d090e3eff1c0324 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 22 Jul 2024 17:36:13 +0200 Subject: [PATCH 36/80] proper struct for gss_keyex authmethod --- openssh-8.0p1-gssapi-keyex.patch | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index b3832c3..c609a00 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -112,16 +112,20 @@ index 9351e042..d6446c0c 100644 else logit("GSSAPI MIC check failed"); -@@ -326,6 +370,13 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) +@@ -326,6 +370,17 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) return 0; } -+Authmethod method_gsskeyex = { ++struct authmethod_cfg methodcfg_gsskeyex = { + "gssapi-keyex", + NULL, -+ userauth_gsskeyex, + &options.gss_authentication +}; ++ ++Authmethod method_gsskeyex = { ++ &methodcfg_gsskeyex, ++ userauth_gsskeyex, ++}; + Authmethod method_gssapi = { &methodcfg_gssapi, From ff8756ae7bd75e3117a5d51a6f1bb3054dc5b616 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Tue, 23 Jul 2024 16:20:17 +0200 Subject: [PATCH 37/80] Make test pass again --- openssh-8.7p1-nohostsha1proof.patch | 76 ++++++++++++----------------- openssh.spec | 1 + 2 files changed, 32 insertions(+), 45 deletions(-) diff --git a/openssh-8.7p1-nohostsha1proof.patch b/openssh-8.7p1-nohostsha1proof.patch index d23e3e6..abc6aa4 100644 --- a/openssh-8.7p1-nohostsha1proof.patch +++ b/openssh-8.7p1-nohostsha1proof.patch @@ -292,51 +292,6 @@ diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c goto out; } -diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c ---- openssh-8.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100 -+++ openssh-8.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100 -@@ -1640,6 +1651,7 @@ main(int ac, char **av) - struct sshkey *pubkey; - struct connection_info connection_info; - sigset_t sigmask; -+ int forbid_ssh_rsa = 0; - - memset(&connection_info, 0, sizeof(connection_info)); - #ifdef HAVE_SECUREWARE -@@ -1938,6 +1950,33 @@ main(int ac, char **av) - key = NULL; - continue; - } -+ if (key && (sshkey_type_plain(key->type) == KEY_RSA || sshkey_type_plain(key->type) == KEY_RSA_CERT)) { -+ size_t sign_size = 0; -+ u_char *tmp = NULL; -+ u_char data[] = "Test SHA1 vector"; -+ int res; -+ -+ res = sshkey_sign(key, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0); -+ free(tmp); -+ if (res == SSH_ERR_LIBCRYPTO_ERROR) { -+ verbose_f("sshd: SHA1 in signatures is disabled for RSA keys"); -+ forbid_ssh_rsa = 1; -+ } -+ } -+ if (key && (sshkey_type_plain(key->type) == KEY_DSA || sshkey_type_plain(key->type) == KEY_DSA_CERT)) { -+ size_t sign_size = 0; -+ u_char *tmp = NULL; -+ u_char data[] = "Test SHA1 vector"; -+ int res; -+ -+ res = sshkey_sign(key, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0); -+ free(tmp); -+ if (res == SSH_ERR_LIBCRYPTO_ERROR) { -+ logit_f("sshd: ssh-dss is disabled, skipping key file %s", options.host_key_files[i]); -+ key = NULL; -+ continue; -+ } -+ } - if (sshkey_is_sk(key) && - key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { - debug("host key %s requires user presence, ignoring", diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c --- openssh-8.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100 +++ openssh-8.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100 @@ -350,3 +305,34 @@ diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c ret = SSH_ERR_SIGNATURE_INVALID; goto out; } +diff -up openssh-9.8p1/sshd-session.c.xxx openssh-9.8p1/sshd-session.c +--- openssh-9.8p1/sshd-session.c.xxx 2024-07-23 15:08:14.794350818 +0200 ++++ openssh-9.8p1/sshd-session.c 2024-07-23 15:40:21.658456636 +0200 +@@ -1305,6 +1305,27 @@ main(int ac, char **av) + + check_ip_options(ssh); + ++ { ++ struct sshkey *rsakey = NULL; ++ rsakey = get_hostkey_private_by_type(KEY_RSA, 0, ssh); ++ if (rsakey == NULL) ++ rsakey = get_hostkey_private_by_type(KEY_RSA_CERT, 0, ssh); ++ ++ if (rsakey != NULL) { ++ size_t sign_size = 0; ++ u_char *tmp = NULL; ++ u_char data[] = "Test SHA1 vector"; ++ int res; ++ ++ res = sshkey_sign(rsakey, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0); ++ free(tmp); ++ if (res == SSH_ERR_LIBCRYPTO_ERROR) { ++ verbose_f("SHA1 in signatures is disabled for RSA keys"); ++ ssh->compat |= SSH_RH_RSASIGSHA; ++ } ++ } ++ } ++ + /* Prepare the channels layer */ + channel_init_channels(ssh); + channel_set_af(ssh, options.address_family); diff --git a/openssh.spec b/openssh.spec index c158d1b..53b4f75 100644 --- a/openssh.spec +++ b/openssh.spec @@ -700,6 +700,7 @@ test -f %{sysconfig_anaconda} && \ %files server %dir %attr(0711,root,root) %{_datadir}/empty.sshd %attr(0755,root,root) %{_sbindir}/sshd +%attr(0755,root,root) %{_libexecdir}/openssh/sshd-session %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server %attr(0755,root,root) %{_libexecdir}/openssh/sshd-keygen %attr(0644,root,root) %{_mandir}/man5/sshd_config.5* From 0943a793b6ed55b49f460a3ebf8b7c1f3a3a64c4 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 24 Jul 2024 14:31:43 +0200 Subject: [PATCH 38/80] Minor stuff --- openssh-6.7p1-coverity.patch | 2 +- openssh-7.2p2-x11.patch | 4 ++-- openssh-7.6p1-audit.patch | 10 +++++----- openssh-7.7p1-fips.patch | 18 +++++++++--------- openssh-9.0p1-evp-fips-dh.patch | 2 +- openssh-9.6p1-gsskex-new-api.patch | 2 +- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index 7cbdb2a..d98da28 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -27,7 +27,7 @@ diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c - +#pragma GCC diagnostic ignored "-Wstringop-overflow" cp = strncpy(s, kex, strlen(kex)); -+#pragma pop ++#pragma GCC diagnostic pop for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (sshbuf_len(buf) != 0 && diff --git a/openssh-7.2p2-x11.patch b/openssh-7.2p2-x11.patch index b27d7c4..6db16be 100644 --- a/openssh-7.2p2-x11.patch +++ b/openssh-7.2p2-x11.patch @@ -11,8 +11,8 @@ diff --git a/channels.c b/channels.c int sock; struct sockaddr_un addr; -+ if (len <= 0) -+ return -1; ++ if (len <= 0) ++ return -1; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock == -1) { error("socket: %.100s", strerror(errno)); diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index c1d8dde..c884292 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -446,7 +446,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c /* Below is the sshd audit API code */ void -@@ -76,49 +176,210 @@ audit_connection_from(const char *host, +@@ -76,49 +176,211 @@ audit_connection_from(const char *host, /* not implemented */ } @@ -525,6 +525,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c case SSH_AUTH_FAIL_PASSWD: + if (options.use_pam) + break; ++ /* Fallthrough */ + case SSH_LOGIN_EXCEED_MAXTRIES: case SSH_AUTH_FAIL_KBDINT: case SSH_AUTH_FAIL_PUBKEY: @@ -564,7 +565,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c +{ +#ifdef AUDIT_CRYPTO_SESSION + char buf[AUDIT_LOG_SIZE]; -+ const static char *name[] = { "cipher", "mac", "comp" }; ++ static const char *name[] = { "cipher", "mac", "comp" }; + char *s; + int audit_fd; + @@ -582,7 +583,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c +#endif +} + -+const static char *direction[] = { "from-server", "from-client", "both" }; ++static const char *direction[] = { "from-server", "from-client", "both" }; + +void +audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, @@ -2205,12 +2206,11 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); -@@ -2513,6 +2572,15 @@ do_ssh2_kex(struct ssh *ssh) +@@ -2513,6 +2572,14 @@ do_ssh2_kex(struct ssh *ssh) void cleanup_exit(int i) { + static int in_cleanup = 0; -+ int is_privsep_child; + + /* cleanup_exit can be called at the very least from the privsep + wrappers used for auditing. Make sure we don't recurse diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index 80a68d9..e44fef2 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -486,11 +486,11 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c *lenp = 0; if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; -+ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) { -+ logit_f("Ed25519 keys are not allowed in FIPS mode"); -+ return SSH_ERR_INVALID_ARGUMENT; -+ } -+ /* Fallthrough */ ++ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ /* Fallthrough */ if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if ((r = sshkey_unshield_private(key)) != 0) @@ -498,10 +498,10 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c *detailsp = NULL; if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; -+ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) { -+ logit_f("Ed25519 keys are not allowed in FIPS mode"); -+ return SSH_ERR_INVALID_ARGUMENT; -+ } ++ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; return impl->funcs->verify(key, sig, siglen, data, dlen, diff --git a/openssh-9.0p1-evp-fips-dh.patch b/openssh-9.0p1-evp-fips-dh.patch index d0470d9..8c70197 100644 --- a/openssh-9.0p1-evp-fips-dh.patch +++ b/openssh-9.0p1-evp-fips-dh.patch @@ -200,7 +200,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x u_char *kbuf = NULL; size_t klen = 0; - int kout, r; -+ int kout, r = 0; ++ int r = 0; #ifdef DEBUG_KEXDH fprintf(stderr, "dh_pub= "); diff --git a/openssh-9.6p1-gsskex-new-api.patch b/openssh-9.6p1-gsskex-new-api.patch index 6a536fc..0f2eabb 100644 --- a/openssh-9.6p1-gsskex-new-api.patch +++ b/openssh-9.6p1-gsskex-new-api.patch @@ -811,7 +811,7 @@ diff --color -ruNp a/kexgssc.c b/kexgssc.c + const BIGNUM *pub_key, *dh_p, *dh_g; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t hashlen; -+ int r; ++ int r = SSH_ERR_INTERNAL_ERROR; /* * We _must_ have received a COMPLETE message in reply from the From dd27043411008bdbde436d62caa0545db3c5ebe0 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 26 Jul 2024 17:01:14 +0200 Subject: [PATCH 39/80] Change default key type in FIPS mode --- openssh-7.7p1-fips.patch | 26 ++++++++++++++++++++++++++ openssh.spec | 7 ++++--- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index e44fef2..6a14cb3 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -516,6 +516,14 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c #include #include "openbsd-compat/openssl-compat.h" #endif +@@ -69,6 +69,7 @@ + #include "cipher.h" + + #define DEFAULT_KEY_TYPE_NAME "ed25519" ++#define FIPS_DEFAULT_KEY_TYPE_NAME "rsa" + + /* + * Default number of bits in the RSA, DSA and ECDSA keys. These value can be @@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na #endif } @@ -529,6 +537,15 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c switch (type) { case KEY_DSA: if (*bitsp != 1024) +@@ -266,7 +267,7 @@ ask_filename(struct passwd *pw, const ch + char *name = NULL; + + if (key_type_name == NULL) +- name = _PATH_SSH_CLIENT_ID_ED25519; ++ name = FIPS_mode() ? _PATH_SSH_CLIENT_ID_RSA : _PATH_SSH_CLIENT_ID_ED25519; + else { + switch (sshkey_type_from_name(key_type_name)) { + #ifdef WITH_DSA @@ -1098,9 +1104,17 @@ do_gen_all_hostkeys(struct passwd *pw) first = 1; printf("%s: generating new host keys: ", __progname); @@ -548,6 +565,15 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c if ((fd = mkstemp(prv_tmp)) == -1) { error("Could not save your private key in %s: %s", prv_tmp, strerror(errno)); +@@ -3830,7 +3831,7 @@ main(int argc, char **argv) + } + + if (key_type_name == NULL) +- key_type_name = DEFAULT_KEY_TYPE_NAME; ++ key_type_name = FIPS_mode() ? FIPS_DEFAULT_KEY_TYPE_NAME : DEFAULT_KEY_TYPE_NAME; + + type = sshkey_type_from_name(key_type_name); + type_bits_valid(type, key_type_name, &bits); diff -up openssh-9.3p1/ssh-rsa.c.evpgenrsa openssh-9.3p1/ssh-rsa.c --- openssh-9.3p1/ssh-rsa.c.evpgenrsa 2022-06-30 15:14:58.200518353 +0200 +++ openssh-9.3p1/ssh-rsa.c 2022-06-30 15:24:31.499641196 +0200 diff --git a/openssh.spec b/openssh.spec index 53b4f75..02731b6 100644 --- a/openssh.spec +++ b/openssh.spec @@ -47,7 +47,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 9.8p1 -%global openssh_rel 1 +%global openssh_rel 2 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 10 @@ -488,7 +488,6 @@ fi --with-privsep-path=%{_datadir}/empty.sshd \ --disable-strip \ --without-zlib-version-check \ - --with-ssl-engine \ --with-ipaddr-display \ --with-pie=no \ --without-hardening `# The hardening flags are configured by system` \ @@ -496,7 +495,6 @@ fi --with-default-pkcs11-provider=yes \ --with-security-key-builtin=yes \ --with-pam \ - --without-ssl-engine \ %if %{WITH_SELINUX} --with-selinux --with-audit=linux \ --with-sandbox=seccomp_filter \ @@ -746,6 +744,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Fri Jul 26 2024 Dmitry Belyavskiy - 9.8p1-2 +- Change default key type in FIPS mode + * Mon Jul 22 2024 Dmitry Belyavskiy - 9.8p1-1 - Update to OpenSSH 9.8p1 From 28a28238b30bc27766ea431dd93f5419b2d4a9c9 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 5 Aug 2024 12:49:38 +0200 Subject: [PATCH 40/80] Sshd now proposes to enter password again when a non-existing user is specified --- openssh-8.0p1-preserve-pam-errors.patch | 7 +++---- openssh.spec | 5 ++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/openssh-8.0p1-preserve-pam-errors.patch b/openssh-8.0p1-preserve-pam-errors.patch index dbdbe93..b7ab965 100644 --- a/openssh-8.0p1-preserve-pam-errors.patch +++ b/openssh-8.0p1-preserve-pam-errors.patch @@ -27,16 +27,15 @@ diff -up openssh-8.0p1/auth-pam.c.preserve-pam-errors openssh-8.0p1/auth-pam.c else if (sshpam_maxtries_reached) ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer); else -@@ -856,10 +862,12 @@ sshpam_query(void *ctx, char **name, cha - plen++; +@@ -856,9 +862,11 @@ sshpam_query(void *ctx, char **name, cha free(msg); break; -+ case PAM_USER_UNKNOWN: -+ case PAM_PERM_DENIED: case PAM_ACCT_EXPIRED: + sshpam_account_status = 0; + /* FALLTHROUGH */ case PAM_MAXTRIES: ++ case PAM_USER_UNKNOWN: ++ case PAM_PERM_DENIED: - if (type == PAM_ACCT_EXPIRED) - sshpam_account_status = 0; if (type == PAM_MAXTRIES) diff --git a/openssh.spec b/openssh.spec index 02731b6..bd36728 100644 --- a/openssh.spec +++ b/openssh.spec @@ -47,7 +47,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 9.8p1 -%global openssh_rel 2 +%global openssh_rel 3 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 10 @@ -744,6 +744,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Mon Aug 05 2024 Dmitry Belyavskiy - 9.8p1-3 +- Sshd now proposes to enter password again when a non-existing user is specified + * Fri Jul 26 2024 Dmitry Belyavskiy - 9.8p1-2 - Change default key type in FIPS mode From adab98c5ba270c1886a15c4b672f1508adf3e3a3 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Tue, 3 Sep 2024 16:12:58 +0200 Subject: [PATCH 41/80] Synchronize patches from Red Hat --- openssh-8.0p1-gssapi-keyex.patch | 1725 ++++++++++--------- openssh-8.0p1-pkcs11-uri.patch | 4 +- openssh-9.3p1-openssl-compat.patch | 40 - openssh-9.3p1-upstream-cve-2023-38408.patch | 130 -- openssh.spec | 5 +- 5 files changed, 891 insertions(+), 1013 deletions(-) delete mode 100644 openssh-9.3p1-openssl-compat.patch delete mode 100644 openssh-9.3p1-upstream-cve-2023-38408.patch diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-8.0p1-gssapi-keyex.patch index c609a00..82b2bfe 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -1,55 +1,37 @@ -diff --git a/Makefile.in b/Makefile.in -index e7549470..b68c1710 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -109,6 +109,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexgexc.o kexgexs.o \ - kexsntrup761x25519.o sntrup761.o kexgen.o \ -+ kexgssc.o \ - sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ - sshbuf-io.o +diff --color -ruNp a/auth2.c b/auth2.c +--- a/auth2.c 2024-08-28 12:35:01.189659493 +0200 ++++ b/auth2.c 2024-08-28 12:35:41.246432045 +0200 +@@ -71,6 +71,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif -@@ -125,7 +126,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ - auth2-chall.o groupaccess.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 \ -+ monitor.o monitor_wrap.o auth-krb5.o kexgsss.o \ - auth2-gss.o gss-serv.o gss-serv-krb5.o \ - loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ - sftp-server.o sftp-common.o \ -@@ -523,7 +523,7 @@ regress-prep: - ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile +@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + &method_passwd, +diff --color -ruNp a/auth2-gss.c b/auth2-gss.c +--- a/auth2-gss.c 2024-08-28 12:35:01.189659493 +0200 ++++ b/auth2-gss.c 2024-08-28 12:35:41.265432411 +0200 +@@ -51,6 +51,7 @@ + #define SSH_GSSAPI_MAX_MECHS 2048 - REGRESSLIBS=libssh.a $(LIBCOMPAT) --TESTLIBS=$(LIBS) $(CHANNELLIBS) -+TESTLIBS=$(LIBS) $(CHANNELLIBS) $(GSSLIBS) + extern ServerOptions options; ++extern struct authmethod_cfg methodcfg_gsskeyex; + extern struct authmethod_cfg methodcfg_gssapi; - 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 || -- strcmp(method, "gssapi-with-mic") == 0) -+ strcmp(method, "gssapi-with-mic") == 0 || -+ strcmp(method, "gssapi-keyex") == 0) - return 1; - break; - case PERMIT_FORCED_ONLY: -diff --git a/auth2-gss.c b/auth2-gss.c -index 9351e042..d6446c0c 100644 ---- a/auth2-gss.c -+++ b/auth2-gss.c -@@ -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_token(int type, u_int32_t plen, struct ssh *ssh); +@@ -59,6 +60,48 @@ static int input_gssapi_exchange_complet static int input_gssapi_errtok(int, u_int32_t, struct ssh *); -+/* + /* + * The 'gssapi_keyex' userauth mechanism. + */ +static int @@ -91,10 +73,11 @@ index 9351e042..d6446c0c 100644 + return (authenticated); +} + - /* ++/* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) -@@ -260,7 +302,7 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) + */ +@@ -267,7 +310,7 @@ input_gssapi_exchange_complete(int type, if ((r = sshpkt_get_end(ssh)) != 0) fatal_fr(r, "parse packet"); @@ -103,7 +86,7 @@ index 9351e042..d6446c0c 100644 authctxt->postponed = 0; ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); -@@ -306,7 +349,7 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) +@@ -315,7 +358,7 @@ input_gssapi_mic(int type, u_int32_t ple gssbuf.length = sshbuf_len(b); if (!GSS_ERROR(mm_ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))) @@ -112,16 +95,10 @@ index 9351e042..d6446c0c 100644 else logit("GSSAPI MIC check failed"); -@@ -326,6 +370,17 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) +@@ -333,6 +376,11 @@ input_gssapi_mic(int type, u_int32_t ple return 0; } -+struct authmethod_cfg methodcfg_gsskeyex = { -+ "gssapi-keyex", -+ NULL, -+ &options.gss_authentication -+}; -+ +Authmethod method_gsskeyex = { + &methodcfg_gsskeyex, + userauth_gsskeyex, @@ -130,30 +107,45 @@ index 9351e042..d6446c0c 100644 Authmethod method_gssapi = { &methodcfg_gssapi, userauth_gssapi, -diff --git a/auth2.c b/auth2.c -index 0e776224..1c217268 100644 ---- a/auth2.c -+++ b/auth2.c -@@ -73,6 +73,7 @@ extern Authmethod method_passwd; - extern Authmethod method_kbdint; - extern Authmethod method_hostbased; +diff --color -ruNp a/auth2-methods.c b/auth2-methods.c +--- a/auth2-methods.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/auth2-methods.c 2024-08-28 12:35:41.265432411 +0200 +@@ -50,6 +50,11 @@ struct authmethod_cfg methodcfg_pubkey = + &options.pubkey_authentication + }; #ifdef GSSAPI -+extern Authmethod method_gsskeyex; - extern Authmethod method_gssapi; - #endif - -@@ -80,6 +81,7 @@ Authmethod *authmethods[] = { - &method_none, - &method_pubkey, ++struct authmethod_cfg methodcfg_gsskeyex = { ++ "gssapi-keyex", ++ NULL, ++ &options.gss_authentication ++}; + struct authmethod_cfg methodcfg_gssapi = { + "gssapi-with-mic", + NULL, +@@ -76,6 +81,7 @@ static struct authmethod_cfg *authmethod + &methodcfg_none, + &methodcfg_pubkey, #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, ++ &methodcfg_gsskeyex, + &methodcfg_gssapi, #endif - &method_passwd, -diff --git a/canohost.c b/canohost.c -index abea9c6e..8e81b519 100644 ---- a/canohost.c -+++ b/canohost.c + &methodcfg_passwd, +diff --color -ruNp a/auth.c b/auth.c +--- a/auth.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/auth.c 2024-08-28 12:35:41.245432026 +0200 +@@ -356,7 +356,8 @@ auth_root_allowed(struct ssh *ssh, const + case PERMIT_NO_PASSWD: + if (strcmp(method, "publickey") == 0 || + strcmp(method, "hostbased") == 0 || +- strcmp(method, "gssapi-with-mic") == 0) ++ strcmp(method, "gssapi-with-mic") == 0 || ++ strcmp(method, "gssapi-keyex") == 0) + return 1; + break; + case PERMIT_FORCED_ONLY: +diff --color -ruNp a/canohost.c b/canohost.c +--- a/canohost.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/canohost.c 2024-08-28 12:35:41.246432045 +0200 @@ -35,6 +35,99 @@ #include "canohost.h" #include "misc.h" @@ -254,10 +246,9 @@ index abea9c6e..8e81b519 100644 void ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) { -diff --git a/canohost.h b/canohost.h -index 26d62855..0cadc9f1 100644 ---- a/canohost.h -+++ b/canohost.h +diff --color -ruNp a/canohost.h b/canohost.h +--- a/canohost.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/canohost.h 2024-08-28 12:35:41.246432045 +0200 @@ -15,6 +15,9 @@ #ifndef _CANOHOST_H #define _CANOHOST_H @@ -268,11 +259,10 @@ index 26d62855..0cadc9f1 100644 char *get_peer_ipaddr(int); int get_peer_port(int); char *get_local_ipaddr(int); -diff --git a/clientloop.c b/clientloop.c -index ebd0dbca..1bdac6a4 100644 ---- a/clientloop.c -+++ b/clientloop.c -@@ -112,6 +112,10 @@ +diff --color -ruNp a/clientloop.c b/clientloop.c +--- a/clientloop.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/clientloop.c 2024-08-28 12:35:41.246432045 +0200 +@@ -115,6 +115,10 @@ #include "ssherr.h" #include "hostfile.h" @@ -283,7 +273,7 @@ index ebd0dbca..1bdac6a4 100644 /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" -@@ -1379,6 +1383,14 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, +@@ -1590,6 +1594,14 @@ client_loop(struct ssh *ssh, int have_pt /* Do channel operations. */ channel_after_poll(ssh, pfd, npfd_active); @@ -298,11 +288,10 @@ index ebd0dbca..1bdac6a4 100644 /* Buffer input from the connection. */ if (conn_in_ready) client_process_net_input(ssh); -diff --git a/configure.ac b/configure.ac -index b689db4b..efafb6bd 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -674,6 +674,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) +diff --color -ruNp a/configure.ac b/configure.ac +--- a/configure.ac 2024-08-28 12:35:01.202659743 +0200 ++++ b/configure.ac 2024-08-28 12:35:41.247432064 +0200 +@@ -774,6 +774,30 @@ int main(void) { if (NSVersionOfRunTimeL [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) @@ -333,11 +322,10 @@ index b689db4b..efafb6bd 100644 m4_pattern_allow([AU_IPv]) 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 d56257b4..763a63ff 100644 ---- a/gss-genr.c -+++ b/gss-genr.c -@@ -41,9 +41,33 @@ +diff --color -ruNp a/gss-genr.c b/gss-genr.c +--- a/gss-genr.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/gss-genr.c 2024-08-28 12:35:41.248432084 +0200 +@@ -42,9 +42,33 @@ #include "sshbuf.h" #include "log.h" #include "ssh2.h" @@ -371,7 +359,7 @@ index d56257b4..763a63ff 100644 /* sshbuf_get for gss_buffer_desc */ int 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) +@@ -60,6 +84,159 @@ ssh_gssapi_get_buffer_desc(struct sshbuf return 0; } @@ -531,7 +519,7 @@ index d56257b4..763a63ff 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) -@@ -218,7 +398,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, +@@ -216,7 +393,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de } ctx->major = gss_init_sec_context(&ctx->minor, @@ -540,11 +528,10 @@ index d56257b4..763a63ff 100644 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -247,9 +427,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) - return (ctx->major); +@@ -246,8 +423,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con } -+OM_uint32 + OM_uint32 +ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) +{ + gss_buffer_desc gssbuf; @@ -575,7 +562,7 @@ index d56257b4..763a63ff 100644 + return(ctx->major); +} + - OM_uint32 ++OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { + if (ctx == NULL) @@ -584,7 +571,7 @@ index d56257b4..763a63ff 100644 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); -@@ -257,6 +471,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) +@@ -255,6 +466,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer return (ctx->major); } @@ -604,7 +591,7 @@ index d56257b4..763a63ff 100644 void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, const char *context, const struct sshbuf *session_id) -@@ -273,11 +500,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, +@@ -271,11 +495,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, co } int @@ -622,7 +609,7 @@ index d56257b4..763a63ff 100644 /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && -@@ -500,6 +500,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +@@ -285,6 +514,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); @@ -633,7 +620,7 @@ index d56257b4..763a63ff 100644 if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); -@@ -527,10 +527,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx +@@ -294,10 +527,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx GSS_C_NO_BUFFER); } @@ -701,150 +688,9 @@ index d56257b4..763a63ff 100644 +} + #endif /* GSSAPI */ -diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index a151bc1e..8d2b677f 100644 ---- a/gss-serv-krb5.c -+++ b/gss-serv-krb5.c -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ - - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - krb5_error_code problem; - krb5_principal princ; - OM_uint32 maj_status, min_status; -- int len; -+ const char *new_ccname, *new_cctype; - const char *errmsg; - - if (client->creds == NULL) { -@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - return; - } - -- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); -+ new_cctype = krb5_cc_get_type(krb_context, ccache); -+ new_ccname = krb5_cc_get_name(krb_context, ccache); -+ - client->store.envvar = "KRB5CCNAME"; -- len = strlen(client->store.filename) + 6; -- client->store.envval = xmalloc(len); -- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); -+#ifdef USE_CCAPI -+ xasprintf(&client->store.envval, "API:%s", new_ccname); -+ client->store.filename = NULL; -+#else -+ if (new_ccname[0] == ':') -+ new_ccname++; -+ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); -+ if (strcmp(new_cctype, "DIR") == 0) { -+ char *p; -+ p = strrchr(client->store.envval, '/'); -+ if (p) -+ *p = '\0'; -+ } -+ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) -+ client->store.filename = xstrdup(new_ccname); -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - - krb5_cc_close(krb_context, ccache); - -+ client->store.data = krb_context; -+ - return; - } - -+int -+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, -+ ssh_gssapi_client *client) -+{ -+ krb5_ccache ccache = NULL; -+ krb5_principal principal = NULL; -+ char *name = NULL; -+ krb5_error_code problem; -+ OM_uint32 maj_status, min_status; -+ -+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { -+ logit("krb5_cc_resolve(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ return 0; -+ } -+ -+ /* Find out who the principal in this cache is */ -+ if ((problem = krb5_cc_get_principal(krb_context, ccache, -+ &principal))) { -+ logit("krb5_cc_get_principal(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { -+ logit("krb5_unparse_name(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ -+ if (strcmp(name,client->exportedname.value)!=0) { -+ debug("Name in local credentials cache differs. Not storing"); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ krb5_free_unparsed_name(krb_context, name); -+ return 0; -+ } -+ krb5_free_unparsed_name(krb_context, name); -+ -+ /* Name matches, so lets get on with it! */ -+ -+ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { -+ logit("krb5_cc_initialize(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ krb5_free_principal(krb_context, principal); -+ -+ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, -+ ccache))) { -+ logit("gss_krb5_copy_ccache() failed. Sorry!"); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ return 1; -+} -+ - ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", -@@ -203,7 +285,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { - NULL, - &ssh_gssapi_krb5_userok, - NULL, -- &ssh_gssapi_krb5_storecreds -+ &ssh_gssapi_krb5_storecreds, -+ &ssh_gssapi_krb5_updatecreds - }; - - #endif /* KRB5 */ -diff --git a/gss-serv.c b/gss-serv.c -index ab3a15f0..6ce56e92 100644 ---- a/gss-serv.c -+++ b/gss-serv.c +diff --color -ruNp a/gss-serv.c b/gss-serv.c +--- a/gss-serv.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/gss-serv.c 2024-08-28 12:35:41.248432084 +0200 @@ -1,7 +1,7 @@ /* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ @@ -877,11 +723,10 @@ index ab3a15f0..6ce56e92 100644 #ifdef KRB5 extern ssh_gssapi_mech gssapi_kerberos_mech; -@@ -140,6 +142,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) - return (ssh_gssapi_acquire_cred(*ctx)); +@@ -141,6 +143,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss } -+/* Unprivileged */ + /* Unprivileged */ +char * +ssh_gssapi_server_mechanisms(void) { + if (supported_oids == NULL) @@ -904,10 +749,11 @@ index ab3a15f0..6ce56e92 100644 + return (res); +} + - /* Unprivileged */ ++/* Unprivileged */ void ssh_gssapi_supported_oids(gss_OID_set *oidset) -@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset) + { +@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); @@ -933,15 +779,15 @@ index ab3a15f0..6ce56e92 100644 + debug("Rekeyed credentials have different mechanism"); + return GSS_S_COMPLETE; + } -+ + +- gss_buffer_desc ename; + if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, + ctx->client_creds, ctx->oid, &new_name, + NULL, NULL, NULL))) { + ssh_gssapi_error(ctx); + return (ctx->major); + } - -- gss_buffer_desc ename; ++ + ctx->major = gss_compare_name(&ctx->minor, client->name, + new_name, &equal); + @@ -968,7 +814,7 @@ index ab3a15f0..6ce56e92 100644 client->mech = NULL; -@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) +@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g if (client->mech == NULL) return GSS_S_FAILURE; @@ -982,7 +828,7 @@ index ab3a15f0..6ce56e92 100644 if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); -@@ -309,6 +383,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) +@@ -309,6 +383,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g return (ctx->major); } @@ -991,7 +837,7 @@ index ab3a15f0..6ce56e92 100644 /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; -@@ -319,11 +395,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) +@@ -319,11 +395,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g void ssh_gssapi_cleanup_creds(void) { @@ -1017,7 +863,7 @@ index ab3a15f0..6ce56e92 100644 } } -@@ -356,19 +441,23 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep) +@@ -356,19 +441,23 @@ ssh_gssapi_do_child(char ***envp, u_int /* Privileged */ int @@ -1136,11 +982,193 @@ index ab3a15f0..6ce56e92 100644 } /* Privileged */ -diff --git a/kex.c b/kex.c -index a5ae6ac0..fe714141 100644 ---- a/kex.c -+++ b/kex.c -@@ -698,6 +755,9 @@ kex_free(struct kex *kex) +diff --color -ruNp a/gss-serv-krb5.c b/gss-serv-krb5.c +--- a/gss-serv-krb5.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/gss-serv-krb5.c 2024-08-28 12:35:41.248432084 +0200 +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + krb5_error_code problem; + krb5_principal princ; + OM_uint32 maj_status, min_status; +- int len; ++ const char *new_ccname, *new_cctype; + const char *errmsg; + + if (client->creds == NULL) { +@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + return; + } + +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_cctype = krb5_cc_get_type(krb_context, ccache); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ if (new_ccname[0] == ':') ++ new_ccname++; ++ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); ++ if (strcmp(new_cctype, "DIR") == 0) { ++ char *p; ++ p = strrchr(client->store.envval, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl + + krb5_cc_close(krb_context, ccache); + ++ client->store.data = krb_context; ++ + return; + } + ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -203,7 +285,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +diff --color -ruNp a/kex.c b/kex.c +--- a/kex.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/kex.c 2024-08-28 12:35:41.249432103 +0200 +@@ -303,17 +303,37 @@ static int + kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m) + { + int r; ++ int have_key = 0; ++ int ext_count = 2; ++ ++#ifdef GSSAPI ++ /* ++ * Currently GSS KEX don't provide host keys as optional message, so ++ * no reasons to announce the publickey-hostbound extension ++ */ ++ if (ssh->kex->gss == NULL) ++ have_key = 1; ++#endif ++ ext_count += have_key; ++ + + if (ssh->kex->server_sig_algs == NULL && + (ssh->kex->server_sig_algs = sshkey_alg_list(0, 1, 1, ',')) == NULL) + return SSH_ERR_ALLOC_FAIL; +- if ((r = sshbuf_put_u32(m, 3)) != 0 || ++ if ((r = sshbuf_put_u32(m, ext_count)) != 0 || + (r = sshbuf_put_cstring(m, "server-sig-algs")) != 0 || +- (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0 || +- (r = sshbuf_put_cstring(m, +- "publickey-hostbound@openssh.com")) != 0 || +- (r = sshbuf_put_cstring(m, "0")) != 0 || +- (r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 || ++ (r = sshbuf_put_cstring(m, ssh->kex->server_sig_algs)) != 0) { ++ error_fr(r, "compose"); ++ return r; ++ } ++ if (have_key) { ++ if ((r = sshbuf_put_cstring(m, "publickey-hostbound@openssh.com")) != 0 || ++ (r = sshbuf_put_cstring(m, "0")) != 0) { ++ error_fr(r, "compose"); ++ return r; ++ } ++ } ++ if ((r = sshbuf_put_cstring(m, "ping@openssh.com")) != 0 || + (r = sshbuf_put_cstring(m, "0")) != 0) { + error_fr(r, "compose"); + return r; +@@ -737,6 +737,9 @@ kex_free(struct kex *kex) sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); sshbuf_free(kex->session_id); @@ -1150,185 +1178,10 @@ index a5ae6ac0..fe714141 100644 sshbuf_free(kex->initial_sig); sshkey_free(kex->initial_hostkey); free(kex->failed_choice); -diff --git a/kex-names.c b/kex-names.c -index ce85f043..574c7609 100644 ---- a/kex-names.c -+++ b/kex-names.c -@@ -57,6 +57,10 @@ - #include "ssherr.h" - #include "xmalloc.h" - -+#ifdef GSSAPI -+#include "ssh-gss.h" -+#endif -+ - struct kexalg { - char *name; - u_int type; -@@ -115,15 +120,28 @@ static const struct kexalg kexalgs[] = { - #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ - { NULL, 0, -1, -1}, - }; -+static const struct kexalg gss_kexalgs[] = { -+#ifdef GSSAPI -+ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, -+ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, -+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, -+#endif -+ { NULL, 0, -1, -1}, -+}; - --char * --kex_alg_list(char sep) -+static char * -+kex_alg_list_internal(char sep, const struct kexalg *algs) - { - char *ret = NULL, *tmp; - size_t nlen, rlen = 0; - const struct kexalg *k; - -- for (k = kexalgs; k->name != NULL; k++) { -+ for (k = algs; k->name != NULL; k++) { - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(k->name); -@@ -138,6 +156,18 @@ kex_alg_list(char sep) - return ret; - } - -+char * -+kex_alg_list(char sep) -+{ -+ return kex_alg_list_internal(sep, kexalgs); -+} -+ -+char * -+kex_gss_alg_list(char sep) -+{ -+ return kex_alg_list_internal(sep, gss_kexalgs); -+} -+ - static const struct kexalg * - 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; - } -+ for (k = gss_kexalgs; k->name != NULL; k++) { -+ if (strncmp(k->name, name, strlen(k->name)) == 0) -+ return k; -+ } - return NULL; - } - -@@ -315,3 +349,26 @@ kex_assemble_names(char **listp, const char *def, const char *all) - free(ret); - return r; - } -+ -+/* Validate GSS KEX method name list */ -+int -+kex_gss_names_valid(const char *names) -+{ -+ char *s, *cp, *p; -+ -+ if (names == NULL || *names == '\0') -+ return 0; -+ s = cp = xstrdup(names); -+ for ((p = strsep(&cp, ",")); p && *p != '\0'; -+ (p = strsep(&cp, ","))) { -+ if (strncmp(p, "gss-", 4) != 0 -+ || kex_alg_by_name(p) == NULL) { -+ error("Unsupported KEX algorithm \"%.100s\"", p); -+ free(s); -+ return 0; -+ } -+ } -+ debug3("gss kex names ok: [%s]", names); -+ free(s); -+ return 1; -+} -diff --git a/kex.h b/kex.h -index a5ae6ac0..fe714141 100644 ---- a/kex.h -+++ b/kex.h -@@ -102,6 +102,15 @@ enum kex_exchange { - KEX_ECDH_SHA2, - KEX_C25519_SHA256, - KEX_KEM_SNTRUP761X25519_SHA512, -+#ifdef GSSAPI -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GRP14_SHA256, -+ KEX_GSS_GRP16_SHA512, -+ KEX_GSS_GEX_SHA1, -+ KEX_GSS_NISTP256_SHA256, -+ KEX_GSS_C25519_SHA256, -+#endif - KEX_MAX - }; - -@@ -153,6 +162,12 @@ struct kex { - u_int flags; - int hash_alg; - int ec_nid; -+#ifdef GSSAPI -+ int gss_deleg_creds; -+ int gss_trust_dns; -+ char *gss_host; -+ char *gss_client; -+#endif - char *failed_choice; - int (*verify_host_key)(struct sshkey *, struct ssh *); - struct sshkey *(*load_host_public_key)(int, int, struct ssh *); -@@ -174,8 +189,10 @@ struct kex { - int kex_nid_from_name(const char *); - int kex_names_valid(const char *); - char *kex_alg_list(char); -+char *kex_gss_alg_list(char); - char *kex_names_cat(const char *, const char *); - int kex_has_any_alg(const char *, const char *); -+int kex_gss_names_valid(const char *); - int kex_assemble_names(char **, const char *, const char *); - void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], - const char *, const char *, const char *, const char *, const char *); -@@ -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 *); -+#if defined(GSSAPI) && defined(WITH_OPENSSL) -+int kexgssgex_client(struct ssh *); -+int kexgssgex_server(struct ssh *); -+int kexgss_client(struct ssh *); -+int kexgss_server(struct ssh *); -+#endif - - int kex_dh_keypair(struct kex *); - int kex_dh_enc(struct kex *, const struct sshbuf *, 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 *); - -+int kex_gen_hash(int hash_alg, const struct sshbuf *client_version, -+ const struct sshbuf *server_version, const struct sshbuf *client_kexinit, -+ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob, -+ const struct sshbuf *client_pub, const struct sshbuf *server_pub, -+ const struct sshbuf *shared_secret, u_char *hash, size_t *hashlen); -+ - void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) - __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -diff --git a/kexdh.c b/kexdh.c -index 67133e33..edaa4676 100644 ---- a/kexdh.c -+++ b/kexdh.c -@@ -48,13 +48,23 @@ kex_dh_keygen(struct kex *kex) +diff --color -ruNp a/kexdh.c b/kexdh.c +--- a/kexdh.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/kexdh.c 2024-08-28 12:35:41.249432103 +0200 +@@ -49,13 +49,23 @@ kex_dh_keygen(struct kex *kex) { switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: @@ -1352,10 +1205,9 @@ index 67133e33..edaa4676 100644 kex->dh = dh_new_group16(); break; case KEX_DH_GRP18_SHA512: -diff --git a/kexgen.c b/kexgen.c -index 69348b96..c0e8c2f4 100644 ---- a/kexgen.c -+++ b/kexgen.c +diff --color -ruNp a/kexgen.c b/kexgen.c +--- a/kexgen.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/kexgen.c 2024-08-28 12:35:41.249432103 +0200 @@ -44,7 +44,7 @@ static int input_kex_gen_init(int, u_int32_t, struct ssh *); static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh); @@ -1365,11 +1217,9 @@ index 69348b96..c0e8c2f4 100644 kex_gen_hash( int hash_alg, const struct sshbuf *client_version, -diff --git a/kexgssc.c b/kexgssc.c -new file mode 100644 -index 00000000..f6e1405e ---- /dev/null -+++ b/kexgssc.c +diff --color -ruNp a/kexgssc.c b/kexgssc.c +--- a/kexgssc.c 1970-01-01 01:00:00.000000000 +0100 ++++ b/kexgssc.c 2024-08-28 12:35:41.250432122 +0200 @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. @@ -1983,11 +1833,9 @@ index 00000000..f6e1405e +} + +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --git a/kexgsss.c b/kexgsss.c -new file mode 100644 -index 00000000..60bc02de ---- /dev/null -+++ b/kexgsss.c +diff --color -ruNp a/kexgsss.c b/kexgsss.c +--- a/kexgsss.c 1970-01-01 01:00:00.000000000 +0100 ++++ b/kexgsss.c 2024-08-28 12:35:41.250432122 +0200 @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. @@ -2471,11 +2319,211 @@ index 00000000..60bc02de + return r; +} +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --git a/monitor.c b/monitor.c -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 *); +diff --color -ruNp a/kex.h b/kex.h +--- a/kex.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/kex.h 2024-08-28 12:35:41.249432103 +0200 +@@ -102,6 +102,15 @@ enum kex_exchange { + KEX_ECDH_SHA2, + KEX_C25519_SHA256, + KEX_KEM_SNTRUP761X25519_SHA512, ++#ifdef GSSAPI ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GRP14_SHA256, ++ KEX_GSS_GRP16_SHA512, ++ KEX_GSS_GEX_SHA1, ++ KEX_GSS_NISTP256_SHA256, ++ KEX_GSS_C25519_SHA256, ++#endif + KEX_MAX + }; + +@@ -164,6 +173,12 @@ struct kex { + u_int flags; + int hash_alg; + int ec_nid; ++#ifdef GSSAPI ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *failed_choice; + int (*verify_host_key)(struct sshkey *, struct ssh *); + struct sshkey *(*load_host_public_key)(int, int, struct ssh *); +@@ -189,8 +204,10 @@ int kex_hash_from_name(const char *); + int kex_nid_from_name(const char *); + int kex_names_valid(const char *); + char *kex_alg_list(char); ++char *kex_gss_alg_list(char); + char *kex_names_cat(const char *, const char *); + int kex_has_any_alg(const char *, const char *); ++int kex_gss_names_valid(const char *); + int kex_assemble_names(char **, const char *, const char *); + void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], + const char *, const char *, const char *, const char *, const char *); +@@ -224,6 +241,12 @@ int kexgex_client(struct ssh *); + int kexgex_server(struct ssh *); + int kex_gen_client(struct ssh *); + int kex_gen_server(struct ssh *); ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++int kexgssgex_client(struct ssh *); ++int kexgssgex_server(struct ssh *); ++int kexgss_client(struct ssh *); ++int kexgss_server(struct ssh *); ++#endif + + int kex_dh_keypair(struct kex *); + int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, +@@ -256,6 +279,12 @@ int kexgex_hash(int, const struct sshbu + const BIGNUM *, const u_char *, size_t, + u_char *, size_t *); + ++int kex_gen_hash(int hash_alg, const struct sshbuf *client_version, ++ const struct sshbuf *server_version, const struct sshbuf *client_kexinit, ++ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob, ++ const struct sshbuf *client_pub, const struct sshbuf *server_pub, ++ const struct sshbuf *shared_secret, u_char *hash, size_t *hashlen); ++ + void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); +diff --color -ruNp a/kex-names.c b/kex-names.c +--- a/kex-names.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/kex-names.c 2024-08-28 12:35:41.249432103 +0200 +@@ -45,6 +45,10 @@ + #include "ssherr.h" + #include "xmalloc.h" + ++#ifdef GSSAPI ++#include "ssh-gss.h" ++#endif ++ + struct kexalg { + char *name; + u_int type; +@@ -83,15 +87,28 @@ static const struct kexalg kexalgs[] = { + #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ + { NULL, 0, -1, -1}, + }; ++static const struct kexalg gss_kexalgs[] = { ++#ifdef GSSAPI ++ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, ++ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, ++ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, ++#endif ++ { NULL, 0, -1, -1}, ++}; + +-char * +-kex_alg_list(char sep) ++static char * ++kex_alg_list_internal(char sep, const struct kexalg *algs) + { + char *ret = NULL, *tmp; + size_t nlen, rlen = 0; + const struct kexalg *k; + +- for (k = kexalgs; k->name != NULL; k++) { ++ for (k = algs; k->name != NULL; k++) { + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(k->name); +@@ -106,6 +123,18 @@ kex_alg_list(char sep) + return ret; + } + ++char * ++kex_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, kexalgs); ++} ++ ++char * ++kex_gss_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, gss_kexalgs); ++} ++ + static const struct kexalg * + kex_alg_by_name(const char *name) + { +@@ -115,6 +144,10 @@ kex_alg_by_name(const char *name) + if (strcmp(k->name, name) == 0) + return k; + } ++ for (k = gss_kexalgs; k->name != NULL; k++) { ++ if (strncmp(k->name, name, strlen(k->name)) == 0) ++ return k; ++ } + return NULL; + } + +@@ -328,3 +361,26 @@ kex_assemble_names(char **listp, const c + free(ret); + return r; + } ++ ++/* Validate GSS KEX method name list */ ++int ++kex_gss_names_valid(const char *names) ++{ ++ char *s, *cp, *p; ++ ++ if (names == NULL || *names == '\0') ++ return 0; ++ s = cp = xstrdup(names); ++ for ((p = strsep(&cp, ",")); p && *p != '\0'; ++ (p = strsep(&cp, ","))) { ++ if (strncmp(p, "gss-", 4) != 0 ++ || kex_alg_by_name(p) == NULL) { ++ error("Unsupported KEX algorithm \"%.100s\"", p); ++ free(s); ++ return 0; ++ } ++ } ++ debug3("gss kex names ok: [%s]", names); ++ free(s); ++ return 1; ++} +diff --color -ruNp a/Makefile.in b/Makefile.in +--- a/Makefile.in 2024-08-28 12:35:01.200659705 +0200 ++++ b/Makefile.in 2024-08-28 12:35:41.244432006 +0200 +@@ -114,6 +114,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexgexc.o kexgexs.o \ + kexsntrup761x25519.o sntrup761.o kexgen.o \ ++ kexgssc.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ + sshbuf-io.o + +@@ -135,7 +136,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rh + auth2-chall.o groupaccess.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 \ ++ monitor.o monitor_wrap.o auth-krb5.o kexgsss.o \ + auth2-gss.o gss-serv.o gss-serv-krb5.o \ + loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ + sftp-server.o sftp-common.o \ +@@ -529,7 +530,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 --color -ruNp a/monitor.c b/monitor.c +--- a/monitor.c 2024-08-28 12:35:01.192659551 +0200 ++++ b/monitor.c 2024-08-28 12:35:41.251432142 +0200 +@@ -143,6 +143,8 @@ int mm_answer_gss_setup_ctx(struct ssh * int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); @@ -2484,7 +2532,7 @@ index 2ce89fe9..ebf76c7f 100644 #endif #ifdef SSH_AUDIT_EVENTS -@@ -220,11 +222,18 @@ struct mon_table mon_dispatch_proto20[] = { +@@ -219,11 +221,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}, @@ -2503,7 +2551,7 @@ index 2ce89fe9..ebf76c7f 100644 #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, #endif -@@ -293,6 +302,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -292,6 +301,10 @@ monitor_child_preauth(struct ssh *ssh, s /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -2514,7 +2562,7 @@ index 2ce89fe9..ebf76c7f 100644 /* The first few requests do not require asynchronous access */ while (!authenticated) { -@@ -376,8 +376,15 @@ monitor_child_preauth(struct ssh *ssh, s +@@ -344,8 +357,15 @@ monitor_child_preauth(struct ssh *ssh, s if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { auth_log(ssh, authenticated, partial, auth_method, auth_submethod); @@ -2531,7 +2579,7 @@ index 2ce89fe9..ebf76c7f 100644 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) +@@ -413,6 +433,10 @@ monitor_child_postauth(struct ssh *ssh, monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); @@ -2542,7 +2590,7 @@ index 2ce89fe9..ebf76c7f 100644 if (auth_opts->permit_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); -@@ -1713,6 +1730,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1793,6 +1817,17 @@ monitor_apply_keystate(struct ssh *ssh, # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -2560,7 +2608,7 @@ index 2ce89fe9..ebf76c7f 100644 #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; -@@ -1806,8 +1834,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1885,8 +1920,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, u_char *p; int r; @@ -2571,7 +2619,7 @@ index 2ce89fe9..ebf76c7f 100644 if ((r = sshbuf_get_string(m, &p, &len)) != 0) fatal_fr(r, "parse"); -@@ -1839,8 +1867,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1918,8 +1953,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh OM_uint32 flags = 0; /* GSI needs this */ int r; @@ -2582,7 +2630,7 @@ index 2ce89fe9..ebf76c7f 100644 if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) fatal_fr(r, "ssh_gssapi_get_buffer_desc"); -@@ -1860,6 +1888,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1939,6 +1974,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); @@ -2590,7 +2638,7 @@ index 2ce89fe9..ebf76c7f 100644 } return (0); } -@@ -1871,8 +1900,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1950,8 +1986,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, OM_uint32 ret; int r; @@ -2601,7 +2649,7 @@ index 2ce89fe9..ebf76c7f 100644 if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) -@@ -1898,13 +1927,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1977,13 +2013,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -2623,7 +2671,7 @@ index 2ce89fe9..ebf76c7f 100644 sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) -@@ -1913,7 +1946,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1992,7 +2032,11 @@ mm_answer_gss_userok(struct ssh *ssh, in debug3_f("sending result %d", authenticated); mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); @@ -2636,7 +2684,7 @@ index 2ce89fe9..ebf76c7f 100644 if ((displayname = ssh_gssapi_displayname()) != NULL) auth2_record_info(authctxt, "%s", displayname); -@@ -1921,5 +1958,84 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -2000,5 +2044,84 @@ mm_answer_gss_userok(struct ssh *ssh, in /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -2721,11 +2769,10 @@ index 2ce89fe9..ebf76c7f 100644 + #endif /* GSSAPI */ -diff --git a/monitor.h b/monitor.h -index 683e5e07..2b1a2d59 100644 ---- a/monitor.h -+++ b/monitor.h -@@ -63,6 +63,8 @@ enum monitor_reqtype { +diff --color -ruNp a/monitor.h b/monitor.h +--- a/monitor.h 2024-08-28 12:35:01.192659551 +0200 ++++ b/monitor.h 2024-08-28 12:35:41.251432142 +0200 +@@ -67,6 +67,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, @@ -2734,11 +2781,10 @@ index 683e5e07..2b1a2d59 100644 }; struct ssh; -diff --git a/monitor_wrap.c b/monitor_wrap.c -index 001a8fa1..6edb509a 100644 ---- a/monitor_wrap.c -+++ b/monitor_wrap.c -@@ -993,13 +993,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +diff --color -ruNp a/monitor_wrap.c b/monitor_wrap.c +--- a/monitor_wrap.c 2024-08-28 12:35:01.192659551 +0200 ++++ b/monitor_wrap.c 2024-08-28 12:35:41.251432142 +0200 +@@ -1075,13 +1075,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss } int @@ -2755,7 +2801,7 @@ index 001a8fa1..6edb509a 100644 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, -@@ -1012,6 +1014,59 @@ mm_ssh_gssapi_userok(char *user) +@@ -1094,6 +1096,59 @@ mm_ssh_gssapi_userok(char *user) debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } @@ -2815,11 +2861,10 @@ index 001a8fa1..6edb509a 100644 #endif /* GSSAPI */ /* -diff --git a/monitor_wrap.h b/monitor_wrap.h -index 23ab096a..485590c1 100644 ---- a/monitor_wrap.h -+++ b/monitor_wrap.h -@@ -64,8 +64,10 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, +diff --color -ruNp a/monitor_wrap.h b/monitor_wrap.h +--- a/monitor_wrap.h 2024-08-28 12:35:01.193659570 +0200 ++++ b/monitor_wrap.h 2024-08-28 12:35:41.251432142 +0200 +@@ -67,8 +67,10 @@ void mm_decode_activate_server_options(s 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 *); @@ -2831,10 +2876,54 @@ index 23ab096a..485590c1 100644 #endif #ifdef USE_PAM -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 @@ +diff --color -ruNp a/packet.c b/packet.c +--- a/packet.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/packet.c 2024-08-28 12:35:41.260432315 +0200 +@@ -1517,6 +1517,29 @@ ssh_packet_read(struct ssh *ssh) + return type; + } + ++/* ++ * Waits until a packet has been received, verifies that its type matches ++ * that given, and gives a fatal error and exits if there is a mismatch. ++ */ ++ ++int ++ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) ++{ ++ int r; ++ u_char type; ++ ++ if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) ++ return r; ++ if (type != expected_type) { ++ if ((r = sshpkt_disconnect(ssh, ++ "Protocol error: expected packet type %d, got %d", ++ expected_type, type)) != 0) ++ return r; ++ return SSH_ERR_PROTOCOL_ERROR; ++ } ++ return 0; ++} ++ + static int + ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + { +diff --color -ruNp a/packet.h b/packet.h +--- a/packet.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/packet.h 2024-08-28 12:35:41.260432315 +0200 +@@ -124,6 +124,7 @@ int ssh_packet_send2_wrapped(struct ssh + int ssh_packet_send2(struct ssh *); + + int ssh_packet_read(struct ssh *); ++int ssh_packet_read_expect(struct ssh *, u_int type); + int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); + int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); + int ssh_packet_process_read(struct ssh *, int); +diff --color -ruNp a/readconf.c b/readconf.c +--- a/readconf.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/readconf.c 2024-08-28 12:35:41.253432180 +0200 +@@ -70,6 +70,7 @@ #include "uidswap.h" #include "myproposal.h" #include "digest.h" @@ -2842,7 +2931,7 @@ diff -up a/readconf.c.gsskex b/readconf.c /* Format of the configuration file: -@@ -161,6 +162,8 @@ typedef enum { +@@ -164,6 +165,8 @@ typedef enum { oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, @@ -2851,7 +2940,7 @@ diff -up a/readconf.c.gsskex b/readconf.c oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, -@@ -206,10 +209,22 @@ static struct { +@@ -210,10 +213,22 @@ static struct { /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, @@ -2874,7 +2963,7 @@ diff -up a/readconf.c.gsskex b/readconf.c #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, -@@ -1113,10 +1128,42 @@ parse_time: +@@ -1227,10 +1242,42 @@ parse_time: intptr = &options->gss_authentication; goto parse_flag; @@ -2917,7 +3006,7 @@ diff -up a/readconf.c.gsskex b/readconf.c case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -2306,7 +2353,13 @@ initialize_options(Options * options) +@@ -2542,7 +2589,13 @@ initialize_options(Options * options) options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; options->gss_authentication = -1; @@ -2931,7 +3020,7 @@ diff -up a/readconf.c.gsskex b/readconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; -@@ -2463,8 +2516,18 @@ fill_default_options(Options * options) +@@ -2705,8 +2758,18 @@ fill_default_options(Options * options) options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -2950,7 +3039,7 @@ diff -up a/readconf.c.gsskex b/readconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -3246,7 +3309,14 @@ dump_client_config(Options *o, const cha +@@ -3533,7 +3596,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); @@ -2965,10 +3054,10 @@ diff -up a/readconf.c.gsskex b/readconf.c #endif /* GSSAPI */ dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); -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 { +diff --color -ruNp a/readconf.h b/readconf.h +--- a/readconf.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/readconf.h 2024-08-28 12:35:41.254432199 +0200 +@@ -40,7 +40,13 @@ typedef struct { int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ int gss_authentication; /* Try GSS authentication */ @@ -2982,10 +3071,10 @@ diff -up a/readconf.h.gsskex b/readconf.h int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -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 @@ +diff --color -ruNp a/servconf.c b/servconf.c +--- a/servconf.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/servconf.c 2024-08-28 12:35:41.255432218 +0200 +@@ -68,6 +68,7 @@ #include "auth.h" #include "myproposal.h" #include "digest.h" @@ -2993,7 +3082,7 @@ diff -up a/servconf.c.gsskex b/servconf.c #if !defined(SSHD_PAM_SERVICE) # define SSHD_PAM_SERVICE "sshd" -@@ -136,8 +137,11 @@ initialize_server_options(ServerOptions +@@ -137,8 +138,11 @@ initialize_server_options(ServerOptions options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; @@ -3005,7 +3094,7 @@ diff -up a/servconf.c.gsskex b/servconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; -@@ -356,10 +360,18 @@ fill_default_server_options(ServerOption +@@ -376,10 +380,18 @@ fill_default_server_options(ServerOption options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3024,7 +3113,7 @@ diff -up a/servconf.c.gsskex b/servconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -506,6 +518,7 @@ typedef enum { +@@ -558,6 +570,7 @@ typedef enum { sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, @@ -3032,7 +3121,7 @@ diff -up a/servconf.c.gsskex b/servconf.c sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -587,12 +600,22 @@ static struct { +@@ -643,12 +656,22 @@ static struct { #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, @@ -3055,7 +3144,7 @@ diff -up a/servconf.c.gsskex b/servconf.c { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ -@@ -1576,6 +1599,10 @@ process_server_config_line_depth(ServerO +@@ -1585,6 +1608,10 @@ process_server_config_line_depth(ServerO intptr = &options->gss_authentication; goto parse_flag; @@ -3066,7 +3155,7 @@ diff -up a/servconf.c.gsskex b/servconf.c case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1584,6 +1611,22 @@ process_server_config_line_depth(ServerO +@@ -1593,6 +1620,22 @@ process_server_config_line_depth(ServerO intptr = &options->gss_strict_acceptor; goto parse_flag; @@ -3089,7 +3178,7 @@ diff -up a/servconf.c.gsskex b/servconf.c case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -2892,6 +2935,10 @@ dump_config(ServerOptions *o) +@@ -3178,6 +3221,10 @@ dump_config(ServerOptions *o) #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); @@ -3100,11 +3189,10 @@ diff -up a/servconf.c.gsskex b/servconf.c #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, -diff --git a/servconf.h b/servconf.h -index 4202a2d0..3f47ea25 100644 ---- a/servconf.h -+++ b/servconf.h -@@ -132,8 +132,11 @@ typedef struct { +diff --color -ruNp a/servconf.h b/servconf.h +--- a/servconf.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/servconf.h 2024-08-28 12:35:41.255432218 +0200 +@@ -149,8 +149,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 */ @@ -3116,11 +3204,10 @@ index 4202a2d0..3f47ea25 100644 int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ -diff --git a/session.c b/session.c -index 8c0e54f7..06a33442 100644 ---- a/session.c -+++ b/session.c -@@ -2678,13 +2678,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +diff --color -ruNp a/session.c b/session.c +--- a/session.c 2024-08-28 12:35:01.197659647 +0200 ++++ b/session.c 2024-08-28 12:35:41.255432218 +0200 +@@ -2674,13 +2674,19 @@ do_cleanup(struct ssh *ssh, Authctxt *au #ifdef KRB5 if (options.kerberos_ticket_cleanup && @@ -3142,127 +3229,10 @@ index 8c0e54f7..06a33442 100644 #endif /* remove agent socket */ -diff --git a/ssh-gss.h b/ssh-gss.h -index 36180d07..70dd3665 100644 ---- a/ssh-gss.h -+++ b/ssh-gss.h -@@ -61,10 +61,34 @@ - - #define SSH_GSS_OIDTYPE 0x06 - -+#define SSH2_MSG_KEXGSS_INIT 30 -+#define SSH2_MSG_KEXGSS_CONTINUE 31 -+#define SSH2_MSG_KEXGSS_COMPLETE 32 -+#define SSH2_MSG_KEXGSS_HOSTKEY 33 -+#define SSH2_MSG_KEXGSS_ERROR 34 -+#define SSH2_MSG_KEXGSS_GROUPREQ 40 -+#define SSH2_MSG_KEXGSS_GROUP 41 -+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" -+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" -+#define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-" -+#define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-" -+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" -+#define KEX_GSS_NISTP256_SHA256_ID "gss-nistp256-sha256-" -+#define KEX_GSS_C25519_SHA256_ID "gss-curve25519-sha256-" -+ -+#define GSS_KEX_DEFAULT_KEX \ -+ KEX_GSS_GRP14_SHA256_ID "," \ -+ KEX_GSS_GRP16_SHA512_ID "," \ -+ KEX_GSS_NISTP256_SHA256_ID "," \ -+ KEX_GSS_C25519_SHA256_ID "," \ -+ KEX_GSS_GRP14_SHA1_ID "," \ -+ KEX_GSS_GEX_SHA1_ID -+ - typedef struct { - char *filename; - char *envvar; - char *envval; -+ struct passwd *owner; - void *data; - } ssh_gssapi_ccache; - -@@ -72,8 +92,11 @@ typedef struct { - gss_buffer_desc displayname; - gss_buffer_desc exportedname; - gss_cred_id_t creds; -+ gss_name_t name; - struct ssh_gssapi_mech_struct *mech; - ssh_gssapi_ccache store; -+ int used; -+ int updated; - } ssh_gssapi_client; - - 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 *); -+ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - - typedef struct { -@@ -94,10 +118,11 @@ typedef struct { - gss_OID oid; /* client */ - gss_cred_id_t creds; /* server */ - gss_name_t client; /* server */ -- gss_cred_id_t client_creds; /* server */ -+ gss_cred_id_t client_creds; /* both */ - } Gssctxt; - - extern ssh_gssapi_mech *supported_mechs[]; -+extern Gssctxt *gss_kex_context; - - int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); - void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -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 *); -+int ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *, gss_buffer_desc *); - - OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); - OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, -@@ -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 *); --int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); -+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); -+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); -+int ssh_gssapi_credentials_updated(Gssctxt *); - - /* In the server */ -+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, -+ const char *); -+char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *); -+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, -+ const char *, const char *); -+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); -+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, -+ const char *); - OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); --int ssh_gssapi_userok(char *name); -+int ssh_gssapi_userok(char *name, struct passwd *, int kex); - OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_do_child(char ***, u_int *); - void ssh_gssapi_cleanup_creds(void); - void ssh_gssapi_storecreds(void); - const char *ssh_gssapi_displayname(void); - -+char *ssh_gssapi_server_mechanisms(void); -+int ssh_gssapi_oid_table_ok(void); -+ -+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); -+void ssh_gssapi_rekey_creds(void); -+ - #endif /* GSSAPI */ - - #endif /* _SSH_GSS_H */ -diff --git a/ssh.1 b/ssh.1 -index 60de6087..db5c65bc 100644 ---- a/ssh.1 -+++ b/ssh.1 -@@ -503,7 +503,13 @@ For full details of the options listed below, and their possible values, see +diff --color -ruNp a/ssh.1 b/ssh.1 +--- a/ssh.1 2024-08-28 12:35:01.207659840 +0200 ++++ b/ssh.1 2024-08-28 12:35:41.256432238 +0200 +@@ -536,7 +536,13 @@ For full details of the options listed b .It GatewayPorts .It GlobalKnownHostsFile .It GSSAPIAuthentication @@ -3276,7 +3246,7 @@ index 60de6087..db5c65bc 100644 .It HashKnownHosts .It Host .It HostbasedAcceptedAlgorithms -@@ -624,6 +624,8 @@ +@@ -624,6 +630,8 @@ flag), (supported message integrity codes), .Ar kex (key exchange algorithms), @@ -3285,11 +3255,10 @@ index 60de6087..db5c65bc 100644 .Ar key (key types), .Ar key-ca-sign -diff --git a/ssh.c b/ssh.c -index 15aee569..110cf9c1 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -747,6 +747,8 @@ main(int ac, char **av) +diff --color -ruNp a/ssh.c b/ssh.c +--- a/ssh.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/ssh.c 2024-08-28 12:35:41.256432238 +0200 +@@ -827,6 +827,8 @@ main(int ac, char **av) else if (strcmp(optarg, "kex") == 0 || strcasecmp(optarg, "KexAlgorithms") == 0) cp = kex_alg_list('\n'); @@ -3298,7 +3267,7 @@ index 15aee569..110cf9c1 100644 else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); else if (strcmp(optarg, "key-cert") == 0) -@@ -772,8 +774,8 @@ main(int ac, char **av) +@@ -857,8 +859,8 @@ main(int ac, char **av) } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( "cipher\ncipher-auth\ncompression\nkex\n" @@ -3309,10 +3278,9 @@ index 15aee569..110cf9c1 100644 } if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); -diff --git a/ssh_config b/ssh_config -index 5e8ef548..1ff999b6 100644 ---- a/ssh_config -+++ b/ssh_config +diff --color -ruNp a/ssh_config b/ssh_config +--- a/ssh_config 2024-08-28 12:35:01.216660014 +0200 ++++ b/ssh_config 2024-08-28 12:35:41.256432238 +0200 @@ -24,6 +24,8 @@ # HostbasedAuthentication no # GSSAPIAuthentication no @@ -3322,11 +3290,10 @@ index 5e8ef548..1ff999b6 100644 # BatchMode no # CheckHostIP no # AddressFamily any -diff --git a/ssh_config.5 b/ssh_config.5 -index 06a32d31..3f490697 100644 ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -766,10 +766,68 @@ The default is +diff --color -ruNp a/ssh_config.5 b/ssh_config.5 +--- a/ssh_config.5 2024-07-01 06:36:28.000000000 +0200 ++++ b/ssh_config.5 2024-08-28 12:35:41.257432257 +0200 +@@ -938,10 +938,68 @@ The default is Specifies whether user authentication based on GSSAPI is allowed. The default is .Cm no . @@ -3395,11 +3362,10 @@ index 06a32d31..3f490697 100644 .It Cm HashKnownHosts Indicates that .Xr ssh 1 -diff --git a/sshconnect2.c b/sshconnect2.c -index af00fb30..03bc87eb 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -163,6 +161,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) +diff --color -ruNp a/sshconnect2.c b/sshconnect2.c +--- a/sshconnect2.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/sshconnect2.c 2024-08-28 12:35:41.258432276 +0200 +@@ -222,6 +222,11 @@ ssh_kex2(struct ssh *ssh, char *host, st char *all_key, *hkalgs = NULL; int r, use_known_hosts_order = 0; @@ -3411,11 +3377,10 @@ index af00fb30..03bc87eb 100644 xxx_host = host; xxx_hostaddr = hostaddr; xxx_conn_info = cinfo; -@@ -206,6 +209,42 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) - options.kex_algorithms, options.ciphers, options.macs, +@@ -255,6 +260,42 @@ ssh_kex2(struct ssh *ssh, char *host, st 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 @@ -3451,10 +3416,11 @@ index af00fb30..03bc87eb 100644 + } + } +#endif - ++ free(hkalgs); -@@ -224,14 +256,44 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + /* start key exchange */ +@@ -271,14 +312,44 @@ ssh_kex2(struct ssh *ssh, char *host, st # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif @@ -3500,7 +3466,7 @@ index af00fb30..03bc87eb 100644 #ifdef DEBUG_KEXDH /* send 1st encrypted/maced/compressed message */ if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || -@@ -330,6 +392,7 @@ static int input_gssapi_response(int type, u_int32_t, struct ssh *); +@@ -368,6 +439,7 @@ static int input_gssapi_response(int typ 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 *); @@ -3508,7 +3474,7 @@ index af00fb30..03bc87eb 100644 #endif void userauth(struct ssh *, char *); -@@ -346,6 +409,11 @@ static char *authmethods_get(void); +@@ -384,6 +456,11 @@ static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI @@ -3520,7 +3486,7 @@ index af00fb30..03bc87eb 100644 {"gssapi-with-mic", userauth_gssapi, userauth_gssapi_cleanup, -@@ -716,12 +784,32 @@ userauth_gssapi(struct ssh *ssh) +@@ -755,12 +832,32 @@ userauth_gssapi(struct ssh *ssh) OM_uint32 min; int r, ok = 0; gss_OID mech = NULL; @@ -3554,7 +3520,7 @@ index af00fb30..03bc87eb 100644 /* Check to see whether the mechanism is usable before we offer it */ while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && -@@ -730,13 +811,15 @@ userauth_gssapi(struct ssh *ssh) +@@ -769,13 +866,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, @@ -3571,7 +3537,7 @@ index af00fb30..03bc87eb 100644 if (!ok || mech == NULL) return 0; -@@ -976,6 +1059,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) +@@ -1009,6 +1108,55 @@ input_gssapi_error(int type, u_int32_t p free(lang); return r; } @@ -3627,11 +3593,10 @@ index af00fb30..03bc87eb 100644 #endif /* GSSAPI */ static int -diff --git a/sshd.c b/sshd.c -index 60b2aaf7..d92f03aa 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -1852,7 +1852,8 @@ main(int ac, char **av) +diff --color -ruNp a/sshd.c b/sshd.c +--- a/sshd.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/sshd.c 2024-08-28 12:35:41.258432276 +0200 +@@ -1551,7 +1551,8 @@ main(int ac, char **av) free(fp); } accumulate_host_timing_secret(cfg, NULL); @@ -3641,95 +3606,10 @@ index 60b2aaf7..d92f03aa 100644 logit("sshd: no hostkeys available -- exiting."); exit(1); } -diff --git a/sshd-session.c b/sshd-session.c -index 60b2aaf7..d92f03aa 100644 ---- a/sshd-session.c -+++ b/sshd-session.c -@@ -817,8 +817,8 @@ notify_hostkeys(struct ssh *ssh) - } - debug3_f("sent %u hostkeys", nkeys); - if (nkeys == 0) -- fatal_f("no hostkeys"); -- if ((r = sshpkt_send(ssh)) != 0) -+ debug3_f("no hostkeys"); -+ else if ((r = sshpkt_send(ssh)) != 0) - sshpkt_fatal(ssh, r, "%s: send", __func__); - sshbuf_free(buf); - } -@@ -2347,6 +2348,48 @@ do_ssh2_kex(struct ssh *ssh) - - free(hkalgs); - -+#if defined(GSSAPI) && defined(WITH_OPENSSL) -+ { -+ char *orig; -+ char *gss = NULL; -+ char *newstr = NULL; -+ 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 (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) -+ orig = NULL; -+ -+ if (options.gss_keyex) -+ gss = ssh_gssapi_server_mechanisms(); -+ else -+ gss = NULL; -+ -+ if (gss && orig) -+ xasprintf(&newstr, "%s,%s", gss, orig); -+ else if (gss) -+ newstr = gss; -+ else if (orig) -+ 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 (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; -+ -+ if (newstr) -+ myproposal[PROPOSAL_KEX_ALGS] = newstr; -+ else -+ fatal("No supported key exchange algorithms"); -+ } -+#endif -+ - /* start key exchange */ - if ((r = kex_setup(ssh, myproposal)) != 0) - fatal_r(r, "kex_setup"); -@@ -2362,7 +2405,18 @@ do_ssh2_kex(struct ssh *ssh) - #ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_gen_server; - #endif --#endif -+# ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; -+ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; -+ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; -+ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; -+ } -+# endif -+#endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kex_gen_server; - 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 19b7c91a..2c48105f 100644 ---- a/sshd_config -+++ b/sshd_config -@@ -69,6 +69,8 @@ AuthorizedKeysFile .ssh/authorized_keys +diff --color -ruNp a/sshd_config b/sshd_config +--- a/sshd_config 2024-08-28 12:35:01.221660110 +0200 ++++ b/sshd_config 2024-08-28 12:35:41.259432296 +0200 +@@ -77,6 +77,8 @@ AuthorizedKeysFile .ssh/authorized_keys # GSSAPI options #GSSAPIAuthentication no #GSSAPICleanupCredentials yes @@ -3738,11 +3618,10 @@ index 19b7c91a..2c48105f 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 70ccea44..f6b41a2f 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -646,6 +646,11 @@ Specifies whether to automatically destroy the user's credentials cache +diff --color -ruNp a/sshd_config.5 b/sshd_config.5 +--- a/sshd_config.5 2024-08-28 12:35:01.218660052 +0200 ++++ b/sshd_config.5 2024-08-28 12:35:41.259432296 +0200 +@@ -739,6 +739,11 @@ Specifies whether to automatically destr on logout. The default is .Cm yes . @@ -3754,7 +3633,7 @@ index 70ccea44..f6b41a2f 100644 .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. -@@ -660,6 +665,32 @@ machine's default store. +@@ -753,6 +758,32 @@ machine's default store. This facility is provided to assist with operation on multi homed machines. The default is .Cm yes . @@ -3787,15 +3666,223 @@ index 70ccea44..f6b41a2f 100644 .It Cm HostbasedAcceptedAlgorithms 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 57995ee6..fd5b7724 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -127,6 +127,75 @@ static const struct keytype keytypes[] = { - extern const struct sshkey_impl sshkey_xmss_impl; +diff --color -ruNp a/sshd-session.c b/sshd-session.c +--- a/sshd-session.c 2024-08-28 12:35:01.221660110 +0200 ++++ b/sshd-session.c 2024-08-28 12:35:41.263432373 +0200 +@@ -660,8 +660,8 @@ notify_hostkeys(struct ssh *ssh) + } + debug3_f("sent %u hostkeys", nkeys); + if (nkeys == 0) +- fatal_f("no hostkeys"); +- if ((r = sshpkt_send(ssh)) != 0) ++ debug3_f("no hostkeys"); ++ else if ((r = sshpkt_send(ssh)) != 0) + sshpkt_fatal(ssh, r, "%s: send", __func__); + sshbuf_free(buf); + } +@@ -1180,8 +1180,9 @@ main(int ac, char **av) + break; + } + } +- if (!have_key) +- fatal("internal error: monitor received no hostkeys"); ++ /* The GSSAPI key exchange can run without a host key */ ++ if (!have_key && !options.gss_keyex) ++ fatal("internal error: monitor received no hostkeys and GSS KEX is not configured"); + + /* Ensure that umask disallows at least group and world write */ + new_umask = umask(0077) | 0022; +@@ -1462,6 +1463,48 @@ do_ssh2_kex(struct ssh *ssh) + + free(hkalgs); + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ { ++ char *orig; ++ char *gss = NULL; ++ char *newstr = NULL; ++ 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 (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) ++ orig = NULL; ++ ++ if (options.gss_keyex) ++ gss = ssh_gssapi_server_mechanisms(); ++ else ++ gss = NULL; ++ ++ if (gss && orig) ++ xasprintf(&newstr, "%s,%s", gss, orig); ++ else if (gss) ++ xasprintf(&newstr, "%s,%s", gss, "kex-strict-s-v00@openssh.com"); ++ else if (orig) ++ 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 (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xstrdup("null"); ++ ++ if (newstr) ++ myproposal[PROPOSAL_KEX_ALGS] = newstr; ++ else ++ fatal("No supported key exchange algorithms"); ++ } ++#endif ++ + /* start key exchange */ + if ((r = kex_setup(ssh, myproposal)) != 0) + fatal_r(r, "kex_setup"); +@@ -1479,7 +1522,18 @@ do_ssh2_kex(struct ssh *ssh) + #ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; + #endif +-#endif ++# ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; ++ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; ++ } ++# endif ++#endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; + kex->load_host_public_key=&get_hostkey_public_by_type; +diff --color -ruNp a/ssh-gss.h b/ssh-gss.h +--- a/ssh-gss.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/ssh-gss.h 2024-08-28 12:35:41.256432238 +0200 +@@ -61,10 +61,34 @@ + + #define SSH_GSS_OIDTYPE 0x06 + ++#define SSH2_MSG_KEXGSS_INIT 30 ++#define SSH2_MSG_KEXGSS_CONTINUE 31 ++#define SSH2_MSG_KEXGSS_COMPLETE 32 ++#define SSH2_MSG_KEXGSS_HOSTKEY 33 ++#define SSH2_MSG_KEXGSS_ERROR 34 ++#define SSH2_MSG_KEXGSS_GROUPREQ 40 ++#define SSH2_MSG_KEXGSS_GROUP 41 ++#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" ++#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-" ++#define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++#define KEX_GSS_NISTP256_SHA256_ID "gss-nistp256-sha256-" ++#define KEX_GSS_C25519_SHA256_ID "gss-curve25519-sha256-" ++ ++#define GSS_KEX_DEFAULT_KEX \ ++ KEX_GSS_GRP14_SHA256_ID "," \ ++ KEX_GSS_GRP16_SHA512_ID "," \ ++ KEX_GSS_NISTP256_SHA256_ID "," \ ++ KEX_GSS_C25519_SHA256_ID "," \ ++ KEX_GSS_GRP14_SHA1_ID "," \ ++ KEX_GSS_GEX_SHA1_ID ++ + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + +@@ -72,8 +96,11 @@ typedef struct { + gss_buffer_desc displayname; + gss_buffer_desc exportedname; + gss_cred_id_t creds; ++ gss_name_t name; + struct ssh_gssapi_mech_struct *mech; + ssh_gssapi_ccache store; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +@@ -84,6 +111,7 @@ typedef struct ssh_gssapi_mech_struct { + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); + void (*storecreds) (ssh_gssapi_client *); ++ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + + typedef struct { +@@ -94,10 +122,11 @@ typedef struct { + gss_OID oid; /* client */ + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ +- gss_cred_id_t client_creds; /* server */ ++ gss_cred_id_t client_creds; /* both */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +@@ -108,6 +137,7 @@ OM_uint32 ssh_gssapi_test_oid_supported( + + struct sshbuf; + int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *); ++int ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *, gss_buffer_desc *); + + OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); + OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, +@@ -122,17 +152,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 *); +-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); ++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); ++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); ++int ssh_gssapi_credentials_updated(Gssctxt *); + + /* In the server */ ++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, ++ const char *); ++char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *); ++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, ++ const char *, const char *); ++gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); ++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, ++ const char *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +-int ssh_gssapi_userok(char *name); ++int ssh_gssapi_userok(char *name, struct passwd *, int kex); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); + void ssh_gssapi_storecreds(void); + const char *ssh_gssapi_displayname(void); + ++char *ssh_gssapi_server_mechanisms(void); ++int ssh_gssapi_oid_table_ok(void); ++ ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); ++void ssh_gssapi_rekey_creds(void); ++ + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ +diff --color -ruNp a/sshkey.c b/sshkey.c +--- a/sshkey.c 2024-07-01 06:36:28.000000000 +0200 ++++ b/sshkey.c 2024-08-28 12:35:41.260432315 +0200 +@@ -131,6 +131,75 @@ extern const struct sshkey_impl sshkey_x 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; @@ -3864,10 +3951,11 @@ index 57995ee6..fd5b7724 100644 + /* .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_ed25519_cert_impl, +@@ -169,6 +238,7 @@ const struct sshkey_impl * const keyimpl &sshkey_xmss_impl, &sshkey_xmss_cert_impl, #endif @@ -3875,7 +3963,7 @@ index 57995ee6..fd5b7724 100644 NULL }; -@@ -255,7 +256,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) +@@ -324,7 +394,7 @@ sshkey_alg_list(int certs_only, int plai for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; @@ -3884,11 +3972,10 @@ index 57995ee6..fd5b7724 100644 continue; if (!include_sigonly && impl->sigonly) continue; -diff --git a/sshkey.h b/sshkey.h -index 71a3fddc..37a43a67 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -69,6 +69,7 @@ enum sshkey_types { +diff --color -ruNp a/sshkey.h b/sshkey.h +--- a/sshkey.h 2024-07-01 06:36:28.000000000 +0200 ++++ b/sshkey.h 2024-08-28 12:35:41.260432315 +0200 +@@ -71,6 +71,7 @@ enum sshkey_types { KEY_ECDSA_SK_CERT, KEY_ED25519_SK, KEY_ED25519_SK_CERT, @@ -3896,47 +3983,3 @@ index 71a3fddc..37a43a67 100644 KEY_UNSPEC }; -diff --git a/packet.h b/packet.h ---- a/packet.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/packet.h (date 1703172586447) -@@ -124,6 +124,7 @@ - int ssh_packet_send2(struct ssh *); - - int ssh_packet_read(struct ssh *); -+int ssh_packet_read_expect(struct ssh *, u_int type); - int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); - int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); - int ssh_packet_process_read(struct ssh *, int); -diff --git a/packet.c b/packet.c ---- a/packet.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/packet.c (date 1703172586447) -@@ -1425,6 +1416,29 @@ - return type; - } - -+/* -+ * Waits until a packet has been received, verifies that its type matches -+ * that given, and gives a fatal error and exits if there is a mismatch. -+ */ -+ -+int -+ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) -+{ -+ int r; -+ u_char type; -+ -+ if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) -+ return r; -+ if (type != expected_type) { -+ if ((r = sshpkt_disconnect(ssh, -+ "Protocol error: expected packet type %d, got %d", -+ expected_type, type)) != 0) -+ return r; -+ return SSH_ERR_PROTOCOL_ERROR; -+ } -+ return 0; -+} -+ - static int - ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) - { diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index c3958cd..9931d92 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -964,7 +964,7 @@ diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c --- openssh-9.6p1/ssh-agent.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 +++ openssh-9.6p1/ssh-agent.c 2024-01-12 14:25:25.234942360 +0100 -@@ -1549,10 +1549,72 @@ add_p11_identity(struct sshkey *key, cha +@@ -1549,10 +1549,74 @@ add_p11_identity(struct sshkey *key, cha idtab->nentries++; } @@ -978,6 +978,8 @@ diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c + if (provider == NULL) + return NULL; + ++ memset(canonical_provider, 0, sizeof(canonical_provider)); ++ + if (strlen(provider) >= strlen(PKCS11_URI_SCHEME) && + strncmp(provider, PKCS11_URI_SCHEME, + strlen(PKCS11_URI_SCHEME)) == 0) { diff --git a/openssh-9.3p1-openssl-compat.patch b/openssh-9.3p1-openssl-compat.patch deleted file mode 100644 index cf512ef..0000000 --- a/openssh-9.3p1-openssl-compat.patch +++ /dev/null @@ -1,40 +0,0 @@ ---- openssh-9.3p1/openbsd-compat/openssl-compat.c 2023-03-15 22:28:19.000000000 +0100 -+++ /home/dbelyavs/work/upstream/openssh-portable/openbsd-compat/openssl-compat.c 2023-05-25 14:19:42.870841944 +0200 -@@ -33,10 +33,10 @@ - - /* - * OpenSSL version numbers: MNNFFPPS: major minor fix patch status -- * We match major, minor, fix and status (not patch) for <1.0.0. -- * After that, we acceptable compatible fix versions (so we -- * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed -- * within a patch series. -+ * Versions >=3 require only major versions to match. -+ * For versions <3, we accept compatible fix versions (so we allow 1.0.1 -+ * to work with 1.0.0). Going backwards is only allowed within a patch series. -+ * See https://www.openssl.org/policies/releasestrat.html - */ - - int -@@ -48,15 +48,17 @@ - if (headerver == libver) - return 1; - -- /* for versions < 1.0.0, major,minor,fix,status must match */ -- if (headerver < 0x1000000f) { -- mask = 0xfffff00fL; /* major,minor,fix,status */ -+ /* -+ * For versions >= 3.0, only the major and status must match. -+ */ -+ if (headerver >= 0x3000000f) { -+ mask = 0xf000000fL; /* major,status */ - return (headerver & mask) == (libver & mask); - } - - /* -- * For versions >= 1.0.0, major,minor,status must match and library -- * fix version must be equal to or newer than the header. -+ * For versions >= 1.0.0, but <3, major,minor,status must match and -+ * library fix version must be equal to or newer than the header. - */ - mask = 0xfff0000fL; /* major,minor,status */ - hfix = (headerver & 0x000ff000) >> 12; diff --git a/openssh-9.3p1-upstream-cve-2023-38408.patch b/openssh-9.3p1-upstream-cve-2023-38408.patch deleted file mode 100644 index e9ac2ae..0000000 --- a/openssh-9.3p1-upstream-cve-2023-38408.patch +++ /dev/null @@ -1,130 +0,0 @@ -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.spec b/openssh.spec index bd36728..a0c21c7 100644 --- a/openssh.spec +++ b/openssh.spec @@ -47,7 +47,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 9.8p1 -%global openssh_rel 3 +%global openssh_rel 4 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 10 @@ -744,6 +744,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Tue Sep 03 2024 Dmitry Belyavskiy - 9.8p1-4 +- Synchronize patches from Red Hat + * Mon Aug 05 2024 Dmitry Belyavskiy - 9.8p1-3 - Sshd now proposes to enter password again when a non-existing user is specified From 64631599fcf520461c6b858d6d58c41f9e7a5bb9 Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Mon, 16 Sep 2024 12:28:25 +0200 Subject: [PATCH 42/80] Merge gssapi-keyex patches Signed-off-by: Zoltan Fridrich --- ....patch => openssh-9.6p1-gssapi-keyex.patch | 1937 ++++++++-------- openssh-9.6p1-gsskex-new-api.patch | 1965 ----------------- openssh.spec | 5 +- 3 files changed, 1070 insertions(+), 2837 deletions(-) rename openssh-8.0p1-gssapi-keyex.patch => openssh-9.6p1-gssapi-keyex.patch (76%) delete mode 100644 openssh-9.6p1-gsskex-new-api.patch diff --git a/openssh-8.0p1-gssapi-keyex.patch b/openssh-9.6p1-gssapi-keyex.patch similarity index 76% rename from openssh-8.0p1-gssapi-keyex.patch rename to openssh-9.6p1-gssapi-keyex.patch index 82b2bfe..e63b258 100644 --- a/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh-9.6p1-gssapi-keyex.patch @@ -1,6 +1,6 @@ diff --color -ruNp a/auth2.c b/auth2.c ---- a/auth2.c 2024-08-28 12:35:01.189659493 +0200 -+++ b/auth2.c 2024-08-28 12:35:41.246432045 +0200 +--- a/auth2.c 2024-09-16 11:45:56.858133241 +0200 ++++ b/auth2.c 2024-09-16 11:46:34.688939755 +0200 @@ -71,6 +71,7 @@ extern Authmethod method_passwd; extern Authmethod method_kbdint; extern Authmethod method_hostbased; @@ -18,8 +18,8 @@ diff --color -ruNp a/auth2.c b/auth2.c #endif &method_passwd, diff --color -ruNp a/auth2-gss.c b/auth2-gss.c ---- a/auth2-gss.c 2024-08-28 12:35:01.189659493 +0200 -+++ b/auth2-gss.c 2024-08-28 12:35:41.265432411 +0200 +--- a/auth2-gss.c 2024-09-16 11:45:56.858133241 +0200 ++++ b/auth2-gss.c 2024-09-16 11:46:34.689939776 +0200 @@ -51,6 +51,7 @@ #define SSH_GSSAPI_MAX_MECHS 2048 @@ -109,7 +109,7 @@ diff --color -ruNp a/auth2-gss.c b/auth2-gss.c userauth_gssapi, diff --color -ruNp a/auth2-methods.c b/auth2-methods.c --- a/auth2-methods.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/auth2-methods.c 2024-08-28 12:35:41.265432411 +0200 ++++ b/auth2-methods.c 2024-09-16 11:46:34.689939776 +0200 @@ -50,6 +50,11 @@ struct authmethod_cfg methodcfg_pubkey = &options.pubkey_authentication }; @@ -132,7 +132,7 @@ diff --color -ruNp a/auth2-methods.c b/auth2-methods.c &methodcfg_passwd, diff --color -ruNp a/auth.c b/auth.c --- a/auth.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/auth.c 2024-08-28 12:35:41.245432026 +0200 ++++ b/auth.c 2024-09-16 11:46:34.690939798 +0200 @@ -356,7 +356,8 @@ auth_root_allowed(struct ssh *ssh, const case PERMIT_NO_PASSWD: if (strcmp(method, "publickey") == 0 || @@ -145,7 +145,7 @@ diff --color -ruNp a/auth.c b/auth.c case PERMIT_FORCED_ONLY: diff --color -ruNp a/canohost.c b/canohost.c --- a/canohost.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/canohost.c 2024-08-28 12:35:41.246432045 +0200 ++++ b/canohost.c 2024-09-16 11:46:34.690939798 +0200 @@ -35,6 +35,99 @@ #include "canohost.h" #include "misc.h" @@ -248,7 +248,7 @@ diff --color -ruNp a/canohost.c b/canohost.c { diff --color -ruNp a/canohost.h b/canohost.h --- a/canohost.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/canohost.h 2024-08-28 12:35:41.246432045 +0200 ++++ b/canohost.h 2024-09-16 11:46:34.690939798 +0200 @@ -15,6 +15,9 @@ #ifndef _CANOHOST_H #define _CANOHOST_H @@ -261,7 +261,7 @@ diff --color -ruNp a/canohost.h b/canohost.h char *get_local_ipaddr(int); diff --color -ruNp a/clientloop.c b/clientloop.c --- a/clientloop.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/clientloop.c 2024-08-28 12:35:41.246432045 +0200 ++++ b/clientloop.c 2024-09-16 11:46:34.690939798 +0200 @@ -115,6 +115,10 @@ #include "ssherr.h" #include "hostfile.h" @@ -289,8 +289,8 @@ diff --color -ruNp a/clientloop.c b/clientloop.c if (conn_in_ready) client_process_net_input(ssh); diff --color -ruNp a/configure.ac b/configure.ac ---- a/configure.ac 2024-08-28 12:35:01.202659743 +0200 -+++ b/configure.ac 2024-08-28 12:35:41.247432064 +0200 +--- a/configure.ac 2024-09-16 11:45:56.870133497 +0200 ++++ b/configure.ac 2024-09-16 11:46:34.691939819 +0200 @@ -774,6 +774,30 @@ int main(void) { if (NSVersionOfRunTimeL [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], @@ -324,7 +324,7 @@ diff --color -ruNp a/configure.ac b/configure.ac AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) diff --color -ruNp a/gss-genr.c b/gss-genr.c --- a/gss-genr.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/gss-genr.c 2024-08-28 12:35:41.248432084 +0200 ++++ b/gss-genr.c 2024-09-16 11:46:34.708940181 +0200 @@ -42,9 +42,33 @@ #include "sshbuf.h" #include "log.h" @@ -519,7 +519,28 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c /* 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 de +@@ -168,6 +345,7 @@ ssh_gssapi_build_ctx(Gssctxt **ctx) + (*ctx)->creds = GSS_C_NO_CREDENTIAL; + (*ctx)->client = GSS_C_NO_NAME; + (*ctx)->client_creds = GSS_C_NO_CREDENTIAL; ++ (*ctx)->first = 1; + } + + /* Delete our context, providing it has been built correctly */ +@@ -193,6 +371,12 @@ ssh_gssapi_delete_ctx(Gssctxt **ctx) + gss_release_name(&ms, &(*ctx)->client); + if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) + gss_release_cred(&ms, &(*ctx)->client_creds); ++ sshbuf_free((*ctx)->shared_secret); ++ sshbuf_free((*ctx)->server_pubkey); ++ sshbuf_free((*ctx)->server_host_key_blob); ++ sshbuf_free((*ctx)->server_blob); ++ explicit_bzero((*ctx)->hash, sizeof((*ctx)->hash)); ++ BN_clear_free((*ctx)->dh_client_pub); + + free(*ctx); + *ctx = NULL; +@@ -216,7 +400,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de } ctx->major = gss_init_sec_context(&ctx->minor, @@ -528,7 +549,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -246,8 +423,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con +@@ -246,8 +430,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con } OM_uint32 @@ -571,7 +592,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c 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 +@@ -255,6 +473,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer return (ctx->major); } @@ -591,7 +612,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c 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, co +@@ -271,11 +502,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, co } int @@ -609,7 +630,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && -@@ -285,6 +514,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx +@@ -285,6 +521,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); @@ -620,7 +641,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c 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 +@@ -294,10 +534,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx GSS_C_NO_BUFFER); } @@ -690,7 +711,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c #endif /* GSSAPI */ diff --color -ruNp a/gss-serv.c b/gss-serv.c --- a/gss-serv.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/gss-serv.c 2024-08-28 12:35:41.248432084 +0200 ++++ b/gss-serv.c 2024-09-16 11:46:34.692939840 +0200 @@ -1,7 +1,7 @@ /* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ @@ -984,7 +1005,7 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c /* Privileged */ diff --color -ruNp a/gss-serv-krb5.c b/gss-serv-krb5.c --- a/gss-serv-krb5.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/gss-serv-krb5.c 2024-08-28 12:35:41.248432084 +0200 ++++ b/gss-serv-krb5.c 2024-09-16 11:46:34.692939840 +0200 @@ -1,7 +1,7 @@ /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ @@ -1123,8 +1144,8 @@ diff --color -ruNp a/gss-serv-krb5.c b/gss-serv-krb5.c #endif /* KRB5 */ diff --color -ruNp a/kex.c b/kex.c --- a/kex.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/kex.c 2024-08-28 12:35:41.249432103 +0200 -@@ -303,17 +303,37 @@ static int ++++ b/kex.c 2024-09-16 11:46:34.692939840 +0200 +@@ -297,17 +297,37 @@ static int kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m) { int r; @@ -1168,7 +1189,7 @@ diff --color -ruNp a/kex.c b/kex.c (r = sshbuf_put_cstring(m, "0")) != 0) { error_fr(r, "compose"); return r; -@@ -737,6 +737,9 @@ kex_free(struct kex *kex) +@@ -737,6 +757,9 @@ kex_free(struct kex *kex) sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); sshbuf_free(kex->session_id); @@ -1180,7 +1201,7 @@ diff --color -ruNp a/kex.c b/kex.c free(kex->failed_choice); diff --color -ruNp a/kexdh.c b/kexdh.c --- a/kexdh.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/kexdh.c 2024-08-28 12:35:41.249432103 +0200 ++++ b/kexdh.c 2024-09-16 11:46:34.693939862 +0200 @@ -49,13 +49,23 @@ kex_dh_keygen(struct kex *kex) { switch (kex->kex_type) { @@ -1207,7 +1228,7 @@ diff --color -ruNp a/kexdh.c b/kexdh.c case KEX_DH_GRP18_SHA512: diff --color -ruNp a/kexgen.c b/kexgen.c --- a/kexgen.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/kexgen.c 2024-08-28 12:35:41.249432103 +0200 ++++ b/kexgen.c 2024-09-16 11:46:34.693939862 +0200 @@ -44,7 +44,7 @@ static int input_kex_gen_init(int, u_int32_t, struct ssh *); static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh); @@ -1219,8 +1240,8 @@ diff --color -ruNp a/kexgen.c b/kexgen.c const struct sshbuf *client_version, diff --color -ruNp a/kexgssc.c b/kexgssc.c --- a/kexgssc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/kexgssc.c 2024-08-28 12:35:41.250432122 +0200 -@@ -0,0 +1,612 @@ ++++ b/kexgssc.c 2024-09-16 11:46:34.709940203 +0200 +@@ -0,0 +1,704 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1270,38 +1291,206 @@ diff --color -ruNp a/kexgssc.c b/kexgssc.c + +#include "ssh-gss.h" + ++static int input_kexgss_hostkey(int, u_int32_t, struct ssh *); ++static int input_kexgss_continue(int, u_int32_t, struct ssh *); ++static int input_kexgss_complete(int, u_int32_t, struct ssh *); ++static int input_kexgss_error(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_group(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_continue(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_complete(int, u_int32_t, struct ssh *); ++ ++static int ++kexgss_final(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ struct sshbuf *empty = NULL; ++ struct sshbuf *shared_secret = NULL; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ int r; ++ ++ /* ++ * We _must_ have received a COMPLETE message in reply from the ++ * server, which will have set server_blob and msg_tok ++ */ ++ ++ /* compute shared secret */ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_dec(kex, gss->server_blob, &shared_secret); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ if (sshbuf_ptr(gss->server_blob)[sshbuf_len(gss->server_blob)] & 0x80) ++ fatal("The received key has MSB of last octet set!"); ++ r = kex_c25519_dec(kex, gss->server_blob, &shared_secret); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ if (sshbuf_len(gss->server_blob) != 65) ++ fatal("The received NIST-P256 key did not match " ++ "expected length (expected 65, got %zu)", ++ sshbuf_len(gss->server_blob)); ++ ++ if (sshbuf_ptr(gss->server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) ++ fatal("The received NIST-P256 key does not have first octet 0x04"); ++ ++ r = kex_ecdh_dec(kex, gss->server_blob, &shared_secret); ++ break; ++ default: ++ r = SSH_ERR_INVALID_ARGUMENT; ++ break; ++ } ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ goto out; ++ } ++ ++ if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ hashlen = sizeof(hash); ++ r = kex_gen_hash(kex->hash_alg, kex->client_version, ++ kex->server_version, kex->my, kex->peer, ++ (gss->server_host_key_blob ? gss->server_host_key_blob : empty), ++ kex->client_pub, gss->server_blob, shared_secret, ++ hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) ++ fatal_f("Unexpected KEX type %d", kex->kex_type); ++ ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; ++ ++ /* Verify that the hash matches the MIC we just got. */ ++ if (GSS_ERROR(ssh_gssapi_checkmic(gss, &gss->buf, &gss->msg_tok))) ++ sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); ++ ++ gss_release_buffer(&gss->minor, &gss->msg_tok); ++ ++ if (kex->gss_deleg_creds) ++ ssh_gssapi_credentials_updated(gss); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = gss; ++ else ++ ssh_gssapi_delete_ctx(&kex->gss); ++ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++ ++ if (kex->gss != NULL) { ++ sshbuf_free(gss->server_host_key_blob); ++ gss->server_host_key_blob = NULL; ++ sshbuf_free(gss->server_blob); ++ gss->server_blob = NULL; ++ } ++out: ++ explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); ++ explicit_bzero(hash, sizeof(hash)); ++ sshbuf_free(shared_secret); ++ sshbuf_free(kex->client_pub); ++ kex->client_pub = NULL; ++ return r; ++} ++ ++static int ++kexgss_init_ctx(struct ssh *ssh, ++ gss_buffer_desc *token_ptr) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags; ++ int r; ++ ++ debug("Calling gss_init_sec_context"); ++ ++ gss->major = ssh_gssapi_init_ctx(gss, kex->gss_deleg_creds, ++ token_ptr, &send_tok, &ret_flags); ++ ++ if (GSS_ERROR(gss->major)) { ++ /* XXX Useless code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&gss->minor, token_ptr); ++ ++ if (gss->major == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (gss->first) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ gss->first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("failed to send packet: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, &input_kexgss_hostkey); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgss_continue); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, &input_kexgss_complete); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, &input_kexgss_error); ++ return 0; ++ } ++ /* No data, and not complete */ ++ if (gss->major != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgss_init_ctx(ssh, token_ptr); ++ ++ return kexgss_final(ssh); ++} ++ +int +kexgss_client(struct ssh *ssh) +{ + struct kex *kex = ssh->kex; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, -+ recv_tok = GSS_C_EMPTY_BUFFER, -+ gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; -+ Gssctxt *ctxt; -+ OM_uint32 maj_status, min_status, ret_flags; -+ struct sshbuf *server_blob = NULL; -+ struct sshbuf *shared_secret = NULL; -+ struct sshbuf *server_host_key_blob = NULL; -+ struct sshbuf *empty = NULL; -+ u_char *msg; -+ int type = 0; -+ int first = 1; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; -+ u_char c; + int r; + + /* Initialise our GSSAPI world */ -+ ssh_gssapi_build_ctx(&ctxt); -+ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) -+ == GSS_C_NO_OID) ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (ssh_gssapi_id_kex(kex->gss, kex->name, kex->kex_type) == GSS_C_NO_OID) + fatal("Couldn't identify host exchange"); + -+ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ if (ssh_gssapi_import_name(kex->gss, kex->gss_host)) + fatal("Couldn't import hostname"); + + if (kex->gss_client && -+ ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ ssh_gssapi_client_identity(kex->gss, kex->gss_client)) + fatal("Couldn't acquire client credentials"); + + /* Step 1 */ @@ -1322,521 +1511,445 @@ diff --color -ruNp a/kexgssc.c b/kexgssc.c + fatal_f("Unexpected KEX type %d", kex->kex_type); + } + if (r != 0) { -+ ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + return r; + } ++ return kexgss_init_ctx(ssh, GSS_C_NO_BUFFER); ++} + -+ token_ptr = GSS_C_NO_BUFFER; ++static int ++input_kexgss_hostkey(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ u_char *tmp = NULL; ++ size_t tmp_len = 0; ++ int r; + -+ do { -+ debug("Calling gss_init_sec_context"); ++ debug("Received KEXGSS_HOSTKEY"); ++ if (gss->server_host_key_blob) ++ fatal("Server host key received more than once"); ++ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) ++ fatal("Failed to read server host key: %s", ssh_err(r)); ++ if ((gss->server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) ++ fatal("sshbuf_from failed"); ++ return 0; ++} + -+ maj_status = ssh_gssapi_init_ctx(ctxt, -+ kex->gss_deleg_creds, token_ptr, &send_tok, -+ &ret_flags); ++static int ++input_kexgss_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ int r; + -+ if (GSS_ERROR(maj_status)) { -+ /* XXX Useles code: Missing send? */ -+ if (send_tok.length != 0) { -+ if ((r = sshpkt_start(ssh, -+ SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, -+ send_tok.length)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ } -+ fatal("gss_init_context failed"); -+ } ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); + -+ /* If we've got an old receive buffer get rid of it */ -+ if (token_ptr != GSS_C_NO_BUFFER) -+ gss_release_buffer(&min_status, &recv_tok); ++ debug("Received GSSAPI_CONTINUE"); ++ if (gss->major == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ if (!(gss->major & GSS_S_CONTINUE_NEEDED)) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ return kexgss_init_ctx(ssh, &recv_tok); ++} + -+ if (maj_status == GSS_S_COMPLETE) { -+ /* If mutual state flag is not true, kex fails */ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual authentication failed"); ++static int ++input_kexgss_complete(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ u_char c; ++ int r; + -+ /* If integ avail flag is not true kex fails */ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity check failed"); -+ } ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); + -+ /* -+ * If we have data to send, then the last message that we -+ * received cannot have been a 'complete'. -+ */ -+ if (send_tok.length != 0) { -+ if (first) { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, -+ send_tok.length)) != 0 || -+ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) -+ fatal("failed to construct packet: %s", ssh_err(r)); -+ first = 0; -+ } else { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, -+ send_tok.length)) != 0) -+ fatal("failed to construct packet: %s", ssh_err(r)); -+ } -+ if ((r = sshpkt_send(ssh)) != 0) -+ fatal("failed to send packet: %s", ssh_err(r)); -+ gss_release_buffer(&min_status, &send_tok); ++ debug("Received GSSAPI_COMPLETE"); ++ if (gss->msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &gss->server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &gss->msg_tok)) != 0) ++ fatal("Failed to read message: %s", ssh_err(r)); + -+ /* If we've sent them data, they should reply */ -+ do { -+ type = ssh_packet_read(ssh); -+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -+ u_char *tmp = NULL; -+ size_t tmp_len = 0; ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (gss->major == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ if (gss->major != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ if ((r = sshpkt_get_end(ssh)) != 0) ++ fatal("Expecting end of packet."); + -+ debug("Received KEXGSS_HOSTKEY"); -+ if (server_host_key_blob) -+ fatal("Server host key received more than once"); -+ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) -+ fatal("Failed to read server host key: %s", ssh_err(r)); -+ if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) -+ fatal("sshbuf_from failed"); -+ } -+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgss_init_ctx(ssh, &recv_tok); + -+ switch (type) { -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ debug("Received GSSAPI_CONTINUE"); -+ if (maj_status == GSS_S_COMPLETE) -+ fatal("GSSAPI Continue received from server when complete"); -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -+ &recv_tok)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("Failed to read token: %s", ssh_err(r)); -+ break; -+ case SSH2_MSG_KEXGSS_COMPLETE: -+ debug("Received GSSAPI_COMPLETE"); -+ if (msg_tok.value != NULL) -+ fatal("Received GSSAPI_COMPLETE twice?"); -+ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || -+ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -+ &msg_tok)) != 0) -+ fatal("Failed to read message: %s", ssh_err(r)); ++ return kexgss_final(ssh); ++} + -+ /* Is there a token included? */ -+ if ((r = sshpkt_get_u8(ssh, &c)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ if (c) { -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc( -+ ssh, &recv_tok)) != 0) -+ fatal("Failed to read token: %s", ssh_err(r)); -+ /* If we're already complete - protocol error */ -+ if (maj_status == GSS_S_COMPLETE) -+ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); -+ } else { -+ /* No token included */ -+ if (maj_status != GSS_S_COMPLETE) -+ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); -+ } -+ if ((r = sshpkt_get_end(ssh)) != 0) { -+ fatal("Expecting end of packet."); -+ } -+ break; -+ case SSH2_MSG_KEXGSS_ERROR: -+ debug("Received Error"); -+ if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || -+ (r = sshpkt_get_u32(ssh, &min_status)) != 0 || -+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || -+ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt_get failed: %s", ssh_err(r)); -+ fatal("GSSAPI Error: \n%.400s", msg); -+ default: -+ sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", -+ type); -+ } -+ token_ptr = &recv_tok; -+ } else { -+ /* No data, and not complete */ -+ if (maj_status != GSS_S_COMPLETE) -+ fatal("Not complete, and no token output"); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++static int ++input_kexgss_error(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ u_char *msg; ++ int r; ++ ++ debug("Received Error"); ++ if ((r = sshpkt_get_u32(ssh, &gss->major)) != 0 || ++ (r = sshpkt_get_u32(ssh, &gss->minor)) != 0 || ++ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || ++ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt_get failed: %s", ssh_err(r)); ++ fatal("GSSAPI Error: \n%.400s", msg); ++ return 0; ++} ++ ++/*******************************************************/ ++/******************** KEXGSSGEX ************************/ ++/*******************************************************/ ++ ++int ++kexgssgex_client(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ int r; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (ssh_gssapi_id_kex(kex->gss, kex->name, kex->kex_type) == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ if (ssh_gssapi_import_name(kex->gss, kex->gss_host)) ++ fatal("Couldn't import hostname"); ++ ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(kex->gss, kex->gss_client)) ++ fatal("Couldn't acquire client credentials"); ++ ++ debug("Doing group exchange"); ++ kex->min = DH_GRP_MIN; ++ kex->max = DH_GRP_MAX; ++ kex->nbits = dh_estimate(kex->dh_need * 8); ++ ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->min)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || ++ (r = sshpkt_put_u32(ssh, kex->max)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("Failed to construct a packet: %s", ssh_err(r)); ++ ++ debug("Wait SSH2_MSG_KEXGSS_GROUP"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUP, &input_kexgssgex_group); ++ return 0; ++} ++ ++static int ++kexgssgex_final(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ struct sshbuf *buf = NULL; ++ struct sshbuf *empty = NULL; ++ struct sshbuf *shared_secret = NULL; ++ BIGNUM *dh_server_pub = NULL; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ int r = SSH_ERR_INTERNAL_ERROR; + + /* + * We _must_ have received a COMPLETE message in reply from the + * server, which will have set server_blob and msg_tok + */ + -+ if (type != SSH2_MSG_KEXGSS_COMPLETE) -+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); -+ -+ /* compute shared secret */ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ case KEX_GSS_GRP14_SHA256: -+ case KEX_GSS_GRP16_SHA512: -+ r = kex_dh_dec(kex, server_blob, &shared_secret); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80) -+ fatal("The received key has MSB of last octet set!"); -+ r = kex_c25519_dec(kex, server_blob, &shared_secret); -+ break; -+ case KEX_GSS_NISTP256_SHA256: -+ if (sshbuf_len(server_blob) != 65) -+ fatal("The received NIST-P256 key did not match" -+ "expected length (expected 65, got %zu)", sshbuf_len(server_blob)); -+ -+ if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) -+ fatal("The received NIST-P256 key does not have first octet 0x04"); -+ -+ r = kex_ecdh_dec(kex, server_blob, &shared_secret); -+ break; -+ default: -+ r = SSH_ERR_INVALID_ARGUMENT; -+ break; -+ } -+ if (r != 0) ++ /* 7. C verifies that the key Q_S is valid */ ++ /* 8. C computes shared secret */ ++ if ((buf = sshbuf_new()) == NULL || ++ (r = sshbuf_put_stringb(buf, gss->server_blob)) != 0 || ++ (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); + goto out; ++ } ++ sshbuf_free(buf); ++ buf = NULL; + -+ if ((empty = sshbuf_new()) == NULL) { ++ if ((shared_secret = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); + r = SSH_ERR_ALLOC_FAIL; + goto out; + } + -+ hashlen = sizeof(hash); -+ if ((r = kex_gen_hash( -+ kex->hash_alg, -+ kex->client_version, -+ kex->server_version, -+ kex->my, -+ kex->peer, -+ (server_host_key_blob ? server_host_key_blob : empty), -+ kex->client_pub, -+ server_blob, -+ shared_secret, -+ hash, &hashlen)) != 0) -+ fatal_f("Unexpected KEX type %d", kex->kex_type); ++ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ goto out; ++ } + -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; ++ if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ hashlen = sizeof(hash); ++ r = kexgex_hash(kex->hash_alg, kex->client_version, ++ kex->server_version, kex->my, kex->peer, ++ (gss->server_host_key_blob ? gss->server_host_key_blob : empty), ++ kex->min, kex->nbits, kex->max, dh_p, dh_g, pub_key, ++ dh_server_pub, sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), ++ hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) ++ fatal("Failed to calculate hash: %s", ssh_err(r)); ++ ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; + + /* Verify that the hash matches the MIC we just got. */ -+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(ssh_gssapi_checkmic(gss, &gss->buf, &gss->msg_tok))) + sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); + -+ gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, &gss->msg_tok); + + if (kex->gss_deleg_creds) -+ ssh_gssapi_credentials_updated(ctxt); ++ ssh_gssapi_credentials_updated(gss); + + if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; ++ gss_kex_context = gss; + else -+ ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + ++ /* Finally derive the keys and send them */ + if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + ++ if (kex->gss != NULL) { ++ sshbuf_free(gss->server_host_key_blob); ++ gss->server_host_key_blob = NULL; ++ sshbuf_free(gss->server_blob); ++ gss->server_blob = NULL; ++ } +out: + explicit_bzero(hash, sizeof(hash)); -+ explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); -+ sshbuf_free(empty); -+ sshbuf_free(server_host_key_blob); -+ sshbuf_free(server_blob); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ BN_clear_free(dh_server_pub); + sshbuf_free(shared_secret); -+ sshbuf_free(kex->client_pub); -+ kex->client_pub = NULL; + return r; +} + -+int -+kexgssgex_client(struct ssh *ssh) ++static int ++kexgssgex_init_ctx(struct ssh *ssh, ++ gss_buffer_desc *token_ptr) +{ + struct kex *kex = ssh->kex; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, -+ recv_tok = GSS_C_EMPTY_BUFFER, gssbuf, -+ msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; -+ Gssctxt *ctxt; -+ OM_uint32 maj_status, min_status, ret_flags; -+ struct sshbuf *shared_secret = NULL; -+ BIGNUM *p = NULL; -+ BIGNUM *g = NULL; -+ struct sshbuf *buf = NULL; -+ struct sshbuf *server_host_key_blob = NULL; -+ struct sshbuf *server_blob = NULL; -+ BIGNUM *dh_server_pub = NULL; -+ u_char *msg; -+ int type = 0; -+ int first = 1; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; -+ const BIGNUM *pub_key, *dh_p, *dh_g; -+ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; -+ struct sshbuf *empty = NULL; -+ u_char c; ++ Gssctxt *gss = kex->gss; ++ const BIGNUM *pub_key; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags; + int r; + -+ /* Initialise our GSSAPI world */ -+ ssh_gssapi_build_ctx(&ctxt); -+ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) -+ == GSS_C_NO_OID) -+ fatal("Couldn't identify host exchange"); ++ /* Step 2 - call GSS_Init_sec_context() */ ++ debug("Calling gss_init_sec_context"); + -+ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) -+ fatal("Couldn't import hostname"); ++ gss->major = ssh_gssapi_init_ctx(gss, kex->gss_deleg_creds, ++ token_ptr, &send_tok, &ret_flags); + -+ if (kex->gss_client && -+ ssh_gssapi_client_identity(ctxt, kex->gss_client)) -+ fatal("Couldn't acquire client credentials"); ++ if (GSS_ERROR(gss->major)) { ++ /* XXX Useless code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } + -+ debug("Doing group exchange"); -+ nbits = dh_estimate(kex->dh_need * 8); ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&gss->minor, token_ptr); + -+ kex->min = DH_GRP_MIN; -+ kex->max = DH_GRP_MAX; -+ kex->nbits = nbits; -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || -+ (r = sshpkt_put_u32(ssh, min)) != 0 || -+ (r = sshpkt_put_u32(ssh, nbits)) != 0 || -+ (r = sshpkt_put_u32(ssh, max)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal("Failed to construct a packet: %s", ssh_err(r)); ++ if (gss->major == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); + -+ if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0) -+ fatal("Error: %s", ssh_err(r)); ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (gss->first) { ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ gss->first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("failed to send packet: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, &input_kexgss_hostkey); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgssgex_continue); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, &input_kexgssgex_complete); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, &input_kexgss_error); ++ return 0; ++ } ++ /* No data, and not complete */ ++ if (gss->major != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgssgex_init_ctx(ssh, token_ptr); ++ ++ return kexgssgex_final(ssh); ++} ++ ++static int ++input_kexgssgex_group(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ BIGNUM *p = NULL; ++ BIGNUM *g = NULL; ++ int r; ++ ++ debug("Received SSH2_MSG_KEXGSS_GROUP"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUP, NULL); + + if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || + (r = sshpkt_get_bignum2(ssh, &g)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); + -+ if (BN_num_bits(p) < min || BN_num_bits(p) > max) ++ if (BN_num_bits(p) < kex->min || BN_num_bits(p) > kex->max) + fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", -+ min, BN_num_bits(p), max); ++ kex->min, BN_num_bits(p), kex->max); + + if ((kex->dh = dh_new_group(g, p)) == NULL) + fatal("dn_new_group() failed"); + p = g = NULL; /* belong to kex->dh now */ + -+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) -+ goto out; -+ DH_get0_key(kex->dh, &pub_key, NULL); ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ return r; ++ } + -+ token_ptr = GSS_C_NO_BUFFER; ++ return kexgssgex_init_ctx(ssh, GSS_C_NO_BUFFER); ++} + -+ do { -+ /* Step 2 - call GSS_Init_sec_context() */ -+ debug("Calling gss_init_sec_context"); ++static int ++input_kexgssgex_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ int r; + -+ maj_status = ssh_gssapi_init_ctx(ctxt, -+ kex->gss_deleg_creds, token_ptr, &send_tok, -+ &ret_flags); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); + -+ if (GSS_ERROR(maj_status)) { -+ /* XXX Useles code: Missing send? */ -+ if (send_tok.length != 0) { -+ if ((r = sshpkt_start(ssh, -+ SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, -+ send_tok.length)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ } -+ fatal("gss_init_context failed"); -+ } -+ -+ /* If we've got an old receive buffer get rid of it */ -+ if (token_ptr != GSS_C_NO_BUFFER) -+ gss_release_buffer(&min_status, &recv_tok); -+ -+ if (maj_status == GSS_S_COMPLETE) { -+ /* If mutual state flag is not true, kex fails */ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual authentication failed"); -+ -+ /* If integ avail flag is not true kex fails */ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity check failed"); -+ } -+ -+ /* -+ * If we have data to send, then the last message that we -+ * received cannot have been a 'complete'. -+ */ -+ if (send_tok.length != 0) { -+ if (first) { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, -+ send_tok.length)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ first = 0; -+ } else { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh,send_tok.value, -+ send_tok.length)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ } -+ if ((r = sshpkt_send(ssh)) != 0) -+ fatal("sshpkt_send failed: %s", ssh_err(r)); -+ gss_release_buffer(&min_status, &send_tok); -+ -+ /* If we've sent them data, they should reply */ -+ do { -+ type = ssh_packet_read(ssh); -+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -+ u_char *tmp = NULL; -+ size_t tmp_len = 0; -+ -+ debug("Received KEXGSS_HOSTKEY"); -+ if (server_host_key_blob) -+ fatal("Server host key received more than once"); -+ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) -+ fatal("sshbuf_from failed"); -+ } -+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); -+ -+ switch (type) { -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ debug("Received GSSAPI_CONTINUE"); -+ if (maj_status == GSS_S_COMPLETE) -+ fatal("GSSAPI Continue received from server when complete"); -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -+ &recv_tok)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ break; -+ case SSH2_MSG_KEXGSS_COMPLETE: -+ debug("Received GSSAPI_COMPLETE"); -+ if (msg_tok.value != NULL) -+ fatal("Received GSSAPI_COMPLETE twice?"); -+ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || -+ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -+ &msg_tok)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ /* Is there a token included? */ -+ if ((r = sshpkt_get_u8(ssh, &c)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ if (c) { -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc( -+ ssh, &recv_tok)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ /* If we're already complete - protocol error */ -+ if (maj_status == GSS_S_COMPLETE) -+ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); -+ } else { -+ /* No token included */ -+ if (maj_status != GSS_S_COMPLETE) -+ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); -+ } -+ break; -+ case SSH2_MSG_KEXGSS_ERROR: -+ debug("Received Error"); -+ if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || -+ (r = sshpkt_get_u32(ssh, &min_status)) != 0 || -+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || -+ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ fatal("GSSAPI Error: \n%.400s", msg); -+ default: -+ sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", -+ type); -+ } -+ token_ptr = &recv_tok; -+ } else { -+ /* No data, and not complete */ -+ if (maj_status != GSS_S_COMPLETE) -+ fatal("Not complete, and no token output"); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ /* -+ * We _must_ have received a COMPLETE message in reply from the -+ * server, which will have set dh_server_pub and msg_tok -+ */ -+ -+ if (type != SSH2_MSG_KEXGSS_COMPLETE) ++ debug("Received GSSAPI_CONTINUE"); ++ if (gss->major == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ if (!(gss->major & GSS_S_CONTINUE_NEEDED)) + fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ return kexgssgex_init_ctx(ssh, &recv_tok); ++} + -+ /* 7. C verifies that the key Q_S is valid */ -+ /* 8. C computes shared secret */ -+ if ((buf = sshbuf_new()) == NULL || -+ (r = sshbuf_put_stringb(buf, server_blob)) != 0 || -+ (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) -+ goto out; -+ sshbuf_free(buf); -+ buf = NULL; ++static int ++input_kexgssgex_complete(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; ++ u_char c; ++ int r; + -+ if ((shared_secret = sshbuf_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); ++ ++ debug("Received GSSAPI_COMPLETE"); ++ if (gss->msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &gss->server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &gss->msg_tok)) != 0) ++ fatal("Failed to read message: %s", ssh_err(r)); ++ ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (gss->major == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ if (gss->major != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); + } ++ if ((r = sshpkt_get_end(ssh)) != 0) ++ fatal("Expecting end of packet."); + -+ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) -+ goto out; -+ if ((empty = sshbuf_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return kexgssgex_init_ctx(ssh, &recv_tok); + -+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); -+ hashlen = sizeof(hash); -+ if ((r = kexgex_hash( -+ kex->hash_alg, -+ kex->client_version, -+ kex->server_version, -+ kex->my, -+ kex->peer, -+ (server_host_key_blob ? server_host_key_blob : empty), -+ kex->min, kex->nbits, kex->max, -+ dh_p, dh_g, -+ pub_key, -+ dh_server_pub, -+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), -+ hash, &hashlen)) != 0) -+ fatal("Failed to calculate hash: %s", ssh_err(r)); -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ -+ /* Verify that the hash matches the MIC we just got. */ -+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) -+ sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); -+ -+ gss_release_buffer(&min_status, &msg_tok); -+ -+ if (kex->gss_deleg_creds) -+ ssh_gssapi_credentials_updated(ctxt); -+ -+ if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; -+ else -+ ssh_gssapi_delete_ctx(&ctxt); -+ -+ /* Finally derive the keys and send them */ -+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) -+ r = kex_send_newkeys(ssh); -+out: -+ sshbuf_free(buf); -+ sshbuf_free(server_blob); -+ sshbuf_free(empty); -+ explicit_bzero(hash, sizeof(hash)); -+ DH_free(kex->dh); -+ kex->dh = NULL; -+ BN_clear_free(dh_server_pub); -+ sshbuf_free(shared_secret); -+ sshbuf_free(server_host_key_blob); -+ return r; ++ return kexgssgex_final(ssh); +} + +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --color -ruNp a/kexgsss.c b/kexgsss.c --- a/kexgsss.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/kexgsss.c 2024-08-28 12:35:41.250432122 +0200 -@@ -0,0 +1,482 @@ ++++ b/kexgsss.c 2024-09-16 11:46:34.710940224 +0200 +@@ -0,0 +1,590 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1889,33 +2002,18 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + +extern ServerOptions options; + ++static int input_kexgss_init(int, u_int32_t, struct ssh *); ++static int input_kexgss_continue(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_groupreq(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_init(int, u_int32_t, struct ssh *); ++static int input_kexgssgex_continue(int, u_int32_t, struct ssh *); ++ +int +kexgss_server(struct ssh *ssh) +{ + struct kex *kex = ssh->kex; -+ OM_uint32 maj_status, min_status; -+ -+ /* -+ * Some GSSAPI implementations use the input value of ret_flags (an -+ * output variable) as a means of triggering mechanism specific -+ * features. Initializing it to zero avoids inadvertently -+ * activating this non-standard behaviour. -+ */ -+ -+ OM_uint32 ret_flags = 0; -+ gss_buffer_desc gssbuf = {0, NULL}, recv_tok, msg_tok; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ Gssctxt *ctxt = NULL; -+ struct sshbuf *shared_secret = NULL; -+ struct sshbuf *client_pubkey = NULL; -+ struct sshbuf *server_pubkey = NULL; -+ struct sshbuf *empty = sshbuf_new(); -+ int type = 0; + gss_OID oid; + char *mechs; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; -+ int r; + + /* Initialise GSSAPI */ + @@ -1931,135 +2029,91 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + debug2_f("Identifying %s", kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) -+ fatal("Unknown gssapi mechanism"); ++ fatal("Unknown gssapi mechanism"); + + debug2_f("Acquiring credentials"); + -+ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&kex->gss, oid))) + fatal("Unable to acquire credentials for the server"); + -+ do { -+ debug("Wait SSH2_MSG_KEXGSS_INIT"); -+ type = ssh_packet_read(ssh); -+ switch(type) { -+ case SSH2_MSG_KEXGSS_INIT: -+ if (gssbuf.value != NULL) -+ fatal("Received KEXGSS_INIT after initialising"); -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -+ &recv_tok)) != 0 || -+ (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (kex->gss == NULL) ++ fatal("Unable to allocate memory for gss context"); + -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ case KEX_GSS_GRP14_SHA256: -+ case KEX_GSS_GRP16_SHA512: -+ r = kex_dh_enc(kex, client_pubkey, &server_pubkey, -+ &shared_secret); -+ break; -+ case KEX_GSS_NISTP256_SHA256: -+ r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, -+ &shared_secret); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, -+ &shared_secret); -+ break; -+ default: -+ fatal_f("Unexpected KEX type %d", kex->kex_type); -+ } -+ if (r != 0) -+ goto out; ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, &input_kexgss_init); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgss_continue); ++ debug("Wait SSH2_MSG_KEXGSS_INIT"); ++ return 0; ++} + -+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++static inline void ++kexgss_accept_ctx(struct ssh *ssh, ++ gss_buffer_desc *recv_tok, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ int r; + -+ /* Calculate the hash early so we can free the -+ * client_pubkey, which has reference to the parent -+ * buffer state->incoming_packet -+ */ -+ hashlen = sizeof(hash); -+ if ((r = kex_gen_hash( -+ kex->hash_alg, -+ kex->client_version, -+ kex->server_version, -+ kex->peer, -+ kex->my, -+ empty, -+ client_pubkey, -+ server_pubkey, -+ shared_secret, -+ hash, &hashlen)) != 0) -+ goto out; ++ gss->major = mm_ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags); ++ gss_release_buffer(&gss->minor, recv_tok); + -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; ++ if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) ++ fatal("Zero length token output when incomplete"); + -+ sshbuf_free(client_pubkey); -+ client_pubkey = NULL; ++ if (gss->buf.value == NULL) ++ fatal("No client public key"); + -+ break; -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -+ &recv_tok)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ break; -+ default: -+ sshpkt_disconnect(ssh, -+ "Protocol error: didn't expect packet type %d", -+ type); -+ } ++ if (gss->major & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, send_tok); ++ } ++} + -+ maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags); ++static inline int ++kexgss_final(struct ssh *ssh, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc msg_tok; ++ int r; + -+ gss_release_buffer(&min_status, &recv_tok); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); + -+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) -+ fatal("Zero length token output when incomplete"); -+ -+ if (gssbuf.value == NULL) -+ fatal("No client public key"); -+ -+ if (maj_status & GSS_S_CONTINUE_NEEDED) { -+ debug("Sending GSSAPI_CONTINUE"); ++ if (GSS_ERROR(gss->major)) { ++ if (send_tok->length > 0) { + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ gss_release_buffer(&min_status, &send_tok); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ if (GSS_ERROR(maj_status)) { -+ if (send_tok.length > 0) { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || + (r = sshpkt_send(ssh)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } + fatal("accept_ctx died"); + } + -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ if (!(*ret_flags & GSS_C_MUTUAL_FLAG)) + fatal("Mutual Authentication flag wasn't set"); + -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ if (!(*ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); + -+ if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) ++ if (GSS_ERROR(mm_ssh_gssapi_sign(gss, &gss->buf, &msg_tok))) + fatal("Couldn't get MIC"); + + if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || -+ (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || ++ (r = sshpkt_put_stringb(ssh, gss->server_pubkey)) != 0 || + (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + -+ if (send_tok.length != 0) { ++ if (send_tok->length != 0) { + if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); + } else { + if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ @@ -2068,59 +2122,139 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + if ((r = sshpkt_send(ssh)) != 0) + fatal("sshpkt_send failed: %s", ssh_err(r)); + -+ gss_release_buffer(&min_status, &send_tok); -+ gss_release_buffer(&min_status, &msg_tok); ++ gss_release_buffer(&gss->minor, send_tok); ++ gss_release_buffer(&gss->minor, &msg_tok); + + if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; ++ gss_kex_context = gss; + else -+ ssh_gssapi_delete_ctx(&ctxt); ++ ssh_gssapi_delete_ctx(&kex->gss); + -+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ if ((r = kex_derive_keys(ssh, gss->hash, gss->hashlen, gss->shared_secret)) == 0) + r = kex_send_newkeys(ssh); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); -+out: -+ sshbuf_free(empty); -+ explicit_bzero(hash, sizeof(hash)); -+ sshbuf_free(shared_secret); -+ sshbuf_free(client_pubkey); -+ sshbuf_free(server_pubkey); ++ ++ if (kex->gss != NULL) { ++ explicit_bzero(gss->hash, sizeof(gss->hash)); ++ sshbuf_free(gss->shared_secret); ++ gss->shared_secret = NULL; ++ sshbuf_free(gss->server_pubkey); ++ gss->server_pubkey = NULL; ++ } + return r; +} + ++static int ++input_kexgss_init(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ struct sshbuf *empty; ++ struct sshbuf *client_pubkey = NULL; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ debug("SSH2_MSG_KEXGSS_INIT received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); ++ break; ++ default: ++ fatal_f("Unexpected KEX type %d", kex->kex_type); ++ } ++ if (r != 0) { ++ sshbuf_free(client_pubkey); ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return r; ++ } ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ ++ if ((empty = sshbuf_new()) == NULL) { ++ sshbuf_free(client_pubkey); ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ /* Calculate the hash early so we can free the ++ * client_pubkey, which has reference to the parent ++ * buffer state->incoming_packet ++ */ ++ gss->hashlen = sizeof(gss->hash); ++ r = kex_gen_hash(kex->hash_alg, kex->client_version, kex->server_version, ++ kex->peer, kex->my, empty, client_pubkey, gss->server_pubkey, ++ gss->shared_secret, gss->hash, &gss->hashlen); ++ sshbuf_free(empty); ++ sshbuf_free(client_pubkey); ++ if (r != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ return r; ++ } ++ ++ gss->buf.value = gss->hash; ++ gss->buf.length = gss->hashlen; ++ ++ kexgss_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgss_final(ssh, &send_tok, &ret_flags); ++} ++ ++static int ++input_kexgss_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ kexgss_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgss_final(ssh, &send_tok, &ret_flags); ++} ++ ++/*******************************************************/ ++/******************** KEXGSSGEX ************************/ ++/*******************************************************/ ++ +int +kexgssgex_server(struct ssh *ssh) +{ + struct kex *kex = ssh->kex; -+ OM_uint32 maj_status, min_status; -+ -+ /* -+ * Some GSSAPI implementations use the input value of ret_flags (an -+ * output variable) as a means of triggering mechanism specific -+ * features. Initializing it to zero avoids inadvertently -+ * activating this non-standard behaviour. -+ */ -+ -+ OM_uint32 ret_flags = 0; -+ gss_buffer_desc gssbuf, recv_tok, msg_tok; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ Gssctxt *ctxt = NULL; -+ struct sshbuf *shared_secret = NULL; -+ int type = 0; + gss_OID oid; + char *mechs; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; -+ BIGNUM *dh_client_pub = NULL; -+ const BIGNUM *pub_key, *dh_p, *dh_g; -+ int min = -1, max = -1, nbits = -1; -+ int cmin = -1, cmax = -1; /* client proposal */ -+ struct sshbuf *empty = sshbuf_new(); -+ int r; + + /* Initialise GSSAPI */ + @@ -2128,29 +2262,194 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + * in the GSSAPI code are no longer available. This kludges them back + * into life + */ -+ if (!ssh_gssapi_oid_table_ok()) -+ if ((mechs = ssh_gssapi_server_mechanisms())) -+ free(mechs); ++ if (!ssh_gssapi_oid_table_ok()) { ++ mechs = ssh_gssapi_server_mechanisms(); ++ free(mechs); ++ } + + debug2_f("Identifying %s", kex->name); + oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) -+ fatal("Unknown gssapi mechanism"); ++ fatal("Unknown gssapi mechanism"); + + debug2_f("Acquiring credentials"); + -+ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) ++ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&kex->gss, oid))) + fatal("Unable to acquire credentials for the server"); + -+ /* 5. S generates an ephemeral key pair (do the allocations early) */ ++ ssh_gssapi_build_ctx(&kex->gss); ++ if (kex->gss == NULL) ++ fatal("Unable to allocate memory for gss context"); ++ + debug("Doing group exchange"); -+ ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUPREQ); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUPREQ, &input_kexgssgex_groupreq); ++ return 0; ++} ++ ++static inline void ++kexgssgex_accept_ctx(struct ssh *ssh, ++ gss_buffer_desc *recv_tok, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ int r; ++ ++ gss->major = mm_ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags); ++ gss_release_buffer(&gss->minor, recv_tok); ++ ++ if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) ++ fatal("Zero length token output when incomplete"); ++ ++ if (gss->dh_client_pub == NULL) ++ fatal("No client public key"); ++ ++ if (gss->major & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&gss->minor, send_tok); ++ } ++} ++ ++static inline int ++kexgssgex_final(struct ssh *ssh, ++ gss_buffer_desc *send_tok, ++ OM_uint32 *ret_flags) ++{ ++ struct kex *kex = ssh->kex; ++ Gssctxt *gss = kex->gss; ++ gss_buffer_desc msg_tok; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ struct sshbuf *shared_secret = NULL; ++ struct sshbuf *empty = NULL; ++ int r; ++ ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); ++ ++ if (GSS_ERROR(gss->major)) { ++ if (send_tok->length > 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("accept_ctx died"); ++ } ++ ++ if (!(*ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual Authentication flag wasn't set"); ++ ++ if (!(*ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity flag wasn't set"); ++ ++ /* calculate shared secret */ ++ shared_secret = sshbuf_new(); ++ if (shared_secret == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if ((r = kex_dh_compute_key(kex, gss->dh_client_pub, shared_secret)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ goto out; ++ } ++ ++ if ((empty = sshbuf_new()) == NULL) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ hashlen = sizeof(hash); ++ r = kexgex_hash(kex->hash_alg, kex->client_version, kex->server_version, ++ kex->peer, kex->my, empty, kex->min, kex->nbits, kex->max, dh_p, dh_g, ++ gss->dh_client_pub, pub_key, sshbuf_ptr(shared_secret), ++ sshbuf_len(shared_secret), hash, &hashlen); ++ sshbuf_free(empty); ++ if (r != 0) ++ fatal("kexgex_hash failed: %s", ssh_err(r)); ++ ++ gss->buf.value = hash; ++ gss->buf.length = hashlen; ++ ++ if (GSS_ERROR(mm_ssh_gssapi_sign(gss, &gss->buf, &msg_tok))) ++ fatal("Couldn't get MIC"); ++ ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || ++ (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ if (send_tok->length != 0) { ++ if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ ++ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } else { ++ if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt_send failed: %s", ssh_err(r)); ++ ++ gss_release_buffer(&gss->minor, send_tok); ++ gss_release_buffer(&gss->minor, &msg_tok); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = gss; ++ else ++ ssh_gssapi_delete_ctx(&kex->gss); ++ ++ /* Finally derive the keys and send them */ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++ ++ /* If this was a rekey, then save out any delegated credentials we ++ * just exchanged. */ ++ if (options.gss_store_rekey) ++ ssh_gssapi_rekey_creds(); ++ ++ if (kex->gss != NULL) ++ BN_clear_free(gss->dh_client_pub); ++ ++out: ++ explicit_bzero(hash, sizeof(hash)); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ sshbuf_free(shared_secret); ++ return r; ++} ++ ++static int ++input_kexgssgex_groupreq(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ const BIGNUM *dh_p, *dh_g; ++ int min = -1, max = -1, nbits = -1; ++ int cmin = -1, cmax = -1; /* client proposal */ ++ int r; ++ ++ /* 5. S generates an ephemeral key pair (do the allocations early) */ ++ ++ debug("SSH2_MSG_KEXGSS_GROUPREQ received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUPREQ, NULL); ++ + /* store client proposal to provide valid signature */ + if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || + (r = sshpkt_get_u32(ssh, &nbits)) != 0 || + (r = sshpkt_get_u32(ssh, &cmax)) != 0 || + (r = sshpkt_get_end(ssh)) != 0) + fatal("sshpkt failed: %s", ssh_err(r)); ++ + kex->nbits = nbits; + kex->min = cmin; + kex->max = cmax; @@ -2158,9 +2457,10 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + max = MIN(DH_GRP_MAX, cmax); + nbits = MAXIMUM(DH_GRP_MIN, nbits); + nbits = MINIMUM(DH_GRP_MAX, nbits); ++ + if (max < min || nbits < min || max < nbits) -+ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", -+ min, nbits, max); ++ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", min, nbits, max); ++ + kex->dh = mm_choose_dh(min, nbits, max); + if (kex->dh == NULL) { + sshpkt_disconnect(ssh, "Protocol error: no matching group found"); @@ -2178,151 +2478,83 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + fatal("ssh_packet_write_wait: %s", ssh_err(r)); + + /* Compute our exchange value in parallel with the client */ -+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) -+ goto out; -+ -+ do { -+ debug("Wait SSH2_MSG_GSSAPI_INIT"); -+ type = ssh_packet_read(ssh); -+ switch(type) { -+ case SSH2_MSG_KEXGSS_INIT: -+ if (dh_client_pub != NULL) -+ fatal("Received KEXGSS_INIT after initialising"); -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -+ &recv_tok)) != 0 || -+ (r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ -+ break; -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -+ &recv_tok)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ break; -+ default: -+ sshpkt_disconnect(ssh, -+ "Protocol error: didn't expect packet type %d", -+ type); -+ } -+ -+ maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags); -+ -+ gss_release_buffer(&min_status, &recv_tok); -+ -+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) -+ fatal("Zero length token output when incomplete"); -+ -+ if (dh_client_pub == NULL) -+ fatal("No client public key"); -+ -+ if (maj_status & GSS_S_CONTINUE_NEEDED) { -+ debug("Sending GSSAPI_CONTINUE"); -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ gss_release_buffer(&min_status, &send_tok); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ if (GSS_ERROR(maj_status)) { -+ if (send_tok.length > 0) { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ } -+ fatal("accept_ctx died"); ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) { ++ ssh_gssapi_delete_ctx(&kex->gss); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ return r; + } + -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual Authentication flag wasn't set"); -+ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity flag wasn't set"); -+ -+ /* calculate shared secret */ -+ if ((shared_secret = sshbuf_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) -+ goto out; -+ -+ DH_get0_key(kex->dh, &pub_key, NULL); -+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); -+ hashlen = sizeof(hash); -+ if ((r = kexgex_hash( -+ kex->hash_alg, -+ kex->client_version, -+ kex->server_version, -+ kex->peer, -+ kex->my, -+ empty, -+ cmin, nbits, cmax, -+ dh_p, dh_g, -+ dh_client_pub, -+ pub_key, -+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), -+ hash, &hashlen)) != 0) -+ fatal("kexgex_hash failed: %s", ssh_err(r)); -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ -+ if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) -+ fatal("Couldn't get MIC"); -+ -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || -+ (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ if (send_tok.length != 0) { -+ if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ } else { -+ if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ } -+ if ((r = sshpkt_send(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ gss_release_buffer(&min_status, &send_tok); -+ gss_release_buffer(&min_status, &msg_tok); -+ -+ if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; -+ else -+ ssh_gssapi_delete_ctx(&ctxt); -+ -+ /* Finally derive the keys and send them */ -+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) -+ r = kex_send_newkeys(ssh); -+ -+ /* If this was a rekey, then save out any delegated credentials we -+ * just exchanged. */ -+ if (options.gss_store_rekey) -+ ssh_gssapi_rekey_creds(); -+out: -+ sshbuf_free(empty); -+ explicit_bzero(hash, sizeof(hash)); -+ DH_free(kex->dh); -+ kex->dh = NULL; -+ BN_clear_free(dh_client_pub); -+ sshbuf_free(shared_secret); -+ return r; ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, &input_kexgssgex_init); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgssgex_continue); ++ debug("Wait SSH2_MSG_KEXGSS_INIT"); ++ return 0; +} ++ ++static int ++input_kexgssgex_init(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ debug("SSH2_MSG_KEXGSS_INIT received"); ++ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &gss->dh_client_pub)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ ++ kexgssgex_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgssgex_final(ssh, &send_tok, &ret_flags); ++} ++ ++static int ++input_kexgssgex_continue(int type, ++ u_int32_t seq, ++ struct ssh *ssh) ++{ ++ Gssctxt *gss = ssh->kex->gss; ++ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ret_flags = 0; ++ int r; ++ ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ kexgssgex_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); ++ if (gss->major & GSS_S_CONTINUE_NEEDED) ++ return 0; ++ ++ return kexgssgex_final(ssh, &send_tok, &ret_flags); ++} ++ +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --color -ruNp a/kex.h b/kex.h --- a/kex.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/kex.h 2024-08-28 12:35:41.249432103 +0200 -@@ -102,6 +102,15 @@ enum kex_exchange { ++++ b/kex.h 2024-09-16 11:46:34.710940224 +0200 +@@ -29,6 +29,10 @@ + #include "mac.h" + #include "crypto_api.h" + ++#ifdef GSSAPI ++# include "ssh-gss.h" /* Gssctxt */ ++#endif ++ + #ifdef WITH_OPENSSL + # include + # include +@@ -102,6 +106,15 @@ enum kex_exchange { KEX_ECDH_SHA2, KEX_C25519_SHA256, KEX_KEM_SNTRUP761X25519_SHA512, @@ -2338,11 +2570,12 @@ diff --color -ruNp a/kex.h b/kex.h KEX_MAX }; -@@ -164,6 +173,12 @@ struct kex { +@@ -164,6 +177,13 @@ struct kex { u_int flags; int hash_alg; int ec_nid; +#ifdef GSSAPI ++ Gssctxt *gss; + int gss_deleg_creds; + int gss_trust_dns; + char *gss_host; @@ -2351,7 +2584,7 @@ diff --color -ruNp a/kex.h b/kex.h char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); -@@ -189,8 +204,10 @@ int kex_hash_from_name(const char *); +@@ -189,8 +209,10 @@ int kex_hash_from_name(const char *); int kex_nid_from_name(const char *); int kex_names_valid(const char *); char *kex_alg_list(char); @@ -2362,7 +2595,7 @@ diff --color -ruNp a/kex.h b/kex.h int kex_assemble_names(char **, const char *, const char *); void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], const char *, const char *, const char *, const char *, const char *); -@@ -224,6 +241,12 @@ int kexgex_client(struct ssh *); +@@ -224,6 +246,12 @@ int kexgex_client(struct ssh *); int kexgex_server(struct ssh *); int kex_gen_client(struct ssh *); int kex_gen_server(struct ssh *); @@ -2375,7 +2608,7 @@ diff --color -ruNp a/kex.h b/kex.h int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, -@@ -256,6 +279,12 @@ int kexgex_hash(int, const struct sshbu +@@ -256,6 +284,12 @@ int kexgex_hash(int, const struct sshbu const BIGNUM *, const u_char *, size_t, u_char *, size_t *); @@ -2390,7 +2623,7 @@ diff --color -ruNp a/kex.h b/kex.h __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); diff --color -ruNp a/kex-names.c b/kex-names.c --- a/kex-names.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/kex-names.c 2024-08-28 12:35:41.249432103 +0200 ++++ b/kex-names.c 2024-09-16 11:46:34.694939883 +0200 @@ -45,6 +45,10 @@ #include "ssherr.h" #include "xmalloc.h" @@ -2492,8 +2725,8 @@ diff --color -ruNp a/kex-names.c b/kex-names.c + return 1; +} diff --color -ruNp a/Makefile.in b/Makefile.in ---- a/Makefile.in 2024-08-28 12:35:01.200659705 +0200 -+++ b/Makefile.in 2024-08-28 12:35:41.244432006 +0200 +--- a/Makefile.in 2024-09-16 11:45:56.868133454 +0200 ++++ b/Makefile.in 2024-09-16 11:46:34.695939904 +0200 @@ -114,6 +114,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ @@ -2521,8 +2754,8 @@ diff --color -ruNp a/Makefile.in b/Makefile.in regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ diff --color -ruNp a/monitor.c b/monitor.c ---- a/monitor.c 2024-08-28 12:35:01.192659551 +0200 -+++ b/monitor.c 2024-08-28 12:35:41.251432142 +0200 +--- a/monitor.c 2024-09-16 11:45:56.861133305 +0200 ++++ b/monitor.c 2024-09-16 11:46:34.696939926 +0200 @@ -143,6 +143,8 @@ int mm_answer_gss_setup_ctx(struct ssh * int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); @@ -2770,8 +3003,8 @@ diff --color -ruNp a/monitor.c b/monitor.c #endif /* GSSAPI */ diff --color -ruNp a/monitor.h b/monitor.h ---- a/monitor.h 2024-08-28 12:35:01.192659551 +0200 -+++ b/monitor.h 2024-08-28 12:35:41.251432142 +0200 +--- a/monitor.h 2024-09-16 11:45:56.861133305 +0200 ++++ b/monitor.h 2024-09-16 11:46:34.696939926 +0200 @@ -67,6 +67,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, @@ -2782,8 +3015,8 @@ diff --color -ruNp a/monitor.h b/monitor.h struct ssh; diff --color -ruNp a/monitor_wrap.c b/monitor_wrap.c ---- a/monitor_wrap.c 2024-08-28 12:35:01.192659551 +0200 -+++ b/monitor_wrap.c 2024-08-28 12:35:41.251432142 +0200 +--- a/monitor_wrap.c 2024-09-16 11:45:56.862133326 +0200 ++++ b/monitor_wrap.c 2024-09-16 11:46:34.697939947 +0200 @@ -1075,13 +1075,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss } @@ -2862,8 +3095,8 @@ diff --color -ruNp a/monitor_wrap.c b/monitor_wrap.c /* diff --color -ruNp a/monitor_wrap.h b/monitor_wrap.h ---- a/monitor_wrap.h 2024-08-28 12:35:01.193659570 +0200 -+++ b/monitor_wrap.h 2024-08-28 12:35:41.251432142 +0200 +--- a/monitor_wrap.h 2024-09-16 11:45:56.862133326 +0200 ++++ b/monitor_wrap.h 2024-09-16 11:46:34.697939947 +0200 @@ -67,8 +67,10 @@ void mm_decode_activate_server_options(s OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, @@ -2876,53 +3109,9 @@ diff --color -ruNp a/monitor_wrap.h b/monitor_wrap.h #endif #ifdef USE_PAM -diff --color -ruNp a/packet.c b/packet.c ---- a/packet.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/packet.c 2024-08-28 12:35:41.260432315 +0200 -@@ -1517,6 +1517,29 @@ ssh_packet_read(struct ssh *ssh) - return type; - } - -+/* -+ * Waits until a packet has been received, verifies that its type matches -+ * that given, and gives a fatal error and exits if there is a mismatch. -+ */ -+ -+int -+ssh_packet_read_expect(struct ssh *ssh, u_int expected_type) -+{ -+ int r; -+ u_char type; -+ -+ if ((r = ssh_packet_read_seqnr(ssh, &type, NULL)) != 0) -+ return r; -+ if (type != expected_type) { -+ if ((r = sshpkt_disconnect(ssh, -+ "Protocol error: expected packet type %d, got %d", -+ expected_type, type)) != 0) -+ return r; -+ return SSH_ERR_PROTOCOL_ERROR; -+ } -+ return 0; -+} -+ - static int - ssh_packet_read_poll2_mux(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) - { -diff --color -ruNp a/packet.h b/packet.h ---- a/packet.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/packet.h 2024-08-28 12:35:41.260432315 +0200 -@@ -124,6 +124,7 @@ int ssh_packet_send2_wrapped(struct ssh - int ssh_packet_send2(struct ssh *); - - int ssh_packet_read(struct ssh *); -+int ssh_packet_read_expect(struct ssh *, u_int type); - int ssh_packet_read_poll2(struct ssh *, u_char *, u_int32_t *seqnr_p); - int ssh_packet_process_incoming(struct ssh *, const char *buf, u_int len); - int ssh_packet_process_read(struct ssh *, int); diff --color -ruNp a/readconf.c b/readconf.c --- a/readconf.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/readconf.c 2024-08-28 12:35:41.253432180 +0200 ++++ b/readconf.c 2024-09-16 11:46:34.699939990 +0200 @@ -70,6 +70,7 @@ #include "uidswap.h" #include "myproposal.h" @@ -3056,7 +3245,7 @@ diff --color -ruNp a/readconf.c b/readconf.c dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); diff --color -ruNp a/readconf.h b/readconf.h --- a/readconf.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/readconf.h 2024-08-28 12:35:41.254432199 +0200 ++++ b/readconf.h 2024-09-16 11:46:34.699939990 +0200 @@ -40,7 +40,13 @@ typedef struct { int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ @@ -3073,7 +3262,7 @@ diff --color -ruNp a/readconf.h b/readconf.h int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ diff --color -ruNp a/servconf.c b/servconf.c --- a/servconf.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/servconf.c 2024-08-28 12:35:41.255432218 +0200 ++++ b/servconf.c 2024-09-16 11:46:34.700940011 +0200 @@ -68,6 +68,7 @@ #include "auth.h" #include "myproposal.h" @@ -3191,7 +3380,7 @@ diff --color -ruNp a/servconf.c b/servconf.c dump_cfg_fmtint(sKbdInteractiveAuthentication, diff --color -ruNp a/servconf.h b/servconf.h --- a/servconf.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/servconf.h 2024-08-28 12:35:41.255432218 +0200 ++++ b/servconf.h 2024-09-16 11:46:34.700940011 +0200 @@ -149,8 +149,11 @@ typedef struct { int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ @@ -3205,8 +3394,8 @@ diff --color -ruNp a/servconf.h b/servconf.h * authentication. */ int kbd_interactive_authentication; /* If true, permit */ diff --color -ruNp a/session.c b/session.c ---- a/session.c 2024-08-28 12:35:01.197659647 +0200 -+++ b/session.c 2024-08-28 12:35:41.255432218 +0200 +--- a/session.c 2024-09-16 11:45:56.866133411 +0200 ++++ b/session.c 2024-09-16 11:46:34.701940032 +0200 @@ -2674,13 +2674,19 @@ do_cleanup(struct ssh *ssh, Authctxt *au #ifdef KRB5 @@ -3230,8 +3419,8 @@ diff --color -ruNp a/session.c b/session.c /* remove agent socket */ diff --color -ruNp a/ssh.1 b/ssh.1 ---- a/ssh.1 2024-08-28 12:35:01.207659840 +0200 -+++ b/ssh.1 2024-08-28 12:35:41.256432238 +0200 +--- a/ssh.1 2024-09-16 11:45:56.875133603 +0200 ++++ b/ssh.1 2024-09-16 11:46:34.701940032 +0200 @@ -536,7 +536,13 @@ For full details of the options listed b .It GatewayPorts .It GlobalKnownHostsFile @@ -3257,7 +3446,7 @@ diff --color -ruNp a/ssh.1 b/ssh.1 .Ar key-ca-sign diff --color -ruNp a/ssh.c b/ssh.c --- a/ssh.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/ssh.c 2024-08-28 12:35:41.256432238 +0200 ++++ b/ssh.c 2024-09-16 11:46:34.702940054 +0200 @@ -827,6 +827,8 @@ main(int ac, char **av) else if (strcmp(optarg, "kex") == 0 || strcasecmp(optarg, "KexAlgorithms") == 0) @@ -3279,8 +3468,8 @@ diff --color -ruNp a/ssh.c b/ssh.c if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); diff --color -ruNp a/ssh_config b/ssh_config ---- a/ssh_config 2024-08-28 12:35:01.216660014 +0200 -+++ b/ssh_config 2024-08-28 12:35:41.256432238 +0200 +--- a/ssh_config 2024-09-16 11:45:56.884133795 +0200 ++++ b/ssh_config 2024-09-16 11:46:34.702940054 +0200 @@ -24,6 +24,8 @@ # HostbasedAuthentication no # GSSAPIAuthentication no @@ -3292,7 +3481,7 @@ diff --color -ruNp a/ssh_config b/ssh_config # AddressFamily any diff --color -ruNp a/ssh_config.5 b/ssh_config.5 --- a/ssh_config.5 2024-07-01 06:36:28.000000000 +0200 -+++ b/ssh_config.5 2024-08-28 12:35:41.257432257 +0200 ++++ b/ssh_config.5 2024-09-16 11:46:34.703940075 +0200 @@ -938,10 +938,68 @@ The default is Specifies whether user authentication based on GSSAPI is allowed. The default is @@ -3364,7 +3553,7 @@ diff --color -ruNp a/ssh_config.5 b/ssh_config.5 .Xr ssh 1 diff --color -ruNp a/sshconnect2.c b/sshconnect2.c --- a/sshconnect2.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/sshconnect2.c 2024-08-28 12:35:41.258432276 +0200 ++++ b/sshconnect2.c 2024-09-16 11:46:34.703940075 +0200 @@ -222,6 +222,11 @@ ssh_kex2(struct ssh *ssh, char *host, st char *all_key, *hkalgs = NULL; int r, use_known_hosts_order = 0; @@ -3595,7 +3784,7 @@ diff --color -ruNp a/sshconnect2.c b/sshconnect2.c static int diff --color -ruNp a/sshd.c b/sshd.c --- a/sshd.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/sshd.c 2024-08-28 12:35:41.258432276 +0200 ++++ b/sshd.c 2024-09-16 11:46:34.704940096 +0200 @@ -1551,7 +1551,8 @@ main(int ac, char **av) free(fp); } @@ -3607,8 +3796,8 @@ diff --color -ruNp a/sshd.c b/sshd.c exit(1); } diff --color -ruNp a/sshd_config b/sshd_config ---- a/sshd_config 2024-08-28 12:35:01.221660110 +0200 -+++ b/sshd_config 2024-08-28 12:35:41.259432296 +0200 +--- a/sshd_config 2024-09-16 11:45:56.888133880 +0200 ++++ b/sshd_config 2024-09-16 11:46:34.704940096 +0200 @@ -77,6 +77,8 @@ AuthorizedKeysFile .ssh/authorized_keys # GSSAPI options #GSSAPIAuthentication no @@ -3619,8 +3808,8 @@ diff --color -ruNp a/sshd_config b/sshd_config # Set this to 'yes' to enable PAM authentication, account processing, # and session processing. If this is enabled, PAM authentication will diff --color -ruNp a/sshd_config.5 b/sshd_config.5 ---- a/sshd_config.5 2024-08-28 12:35:01.218660052 +0200 -+++ b/sshd_config.5 2024-08-28 12:35:41.259432296 +0200 +--- a/sshd_config.5 2024-09-16 11:45:56.885133816 +0200 ++++ b/sshd_config.5 2024-09-16 11:46:34.704940096 +0200 @@ -739,6 +739,11 @@ Specifies whether to automatically destr on logout. The default is @@ -3667,8 +3856,8 @@ diff --color -ruNp a/sshd_config.5 b/sshd_config.5 Specifies the signature algorithms that will be accepted for hostbased authentication as a list of comma-separated patterns. diff --color -ruNp a/sshd-session.c b/sshd-session.c ---- a/sshd-session.c 2024-08-28 12:35:01.221660110 +0200 -+++ b/sshd-session.c 2024-08-28 12:35:41.263432373 +0200 +--- a/sshd-session.c 2024-09-16 11:45:56.888133880 +0200 ++++ b/sshd-session.c 2024-09-16 11:46:34.705940118 +0200 @@ -660,8 +660,8 @@ notify_hostkeys(struct ssh *ssh) } debug3_f("sent %u hostkeys", nkeys); @@ -3763,8 +3952,8 @@ diff --color -ruNp a/sshd-session.c b/sshd-session.c kex->load_host_public_key=&get_hostkey_public_by_type; diff --color -ruNp a/ssh-gss.h b/ssh-gss.h --- a/ssh-gss.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/ssh-gss.h 2024-08-28 12:35:41.256432238 +0200 -@@ -61,10 +61,34 @@ ++++ b/ssh-gss.h 2024-09-16 11:46:34.710940224 +0200 +@@ -61,10 +61,36 @@ #define SSH_GSS_OIDTYPE 0x06 @@ -3790,6 +3979,8 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h + KEX_GSS_C25519_SHA256_ID "," \ + KEX_GSS_GRP14_SHA1_ID "," \ + KEX_GSS_GEX_SHA1_ID ++ ++#include "digest.h" /* SSH_DIGEST_MAX_LENGTH */ + typedef struct { char *filename; @@ -3799,7 +3990,7 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h void *data; } ssh_gssapi_ccache; -@@ -72,8 +96,11 @@ typedef struct { +@@ -72,8 +98,11 @@ typedef struct { gss_buffer_desc displayname; gss_buffer_desc exportedname; gss_cred_id_t creds; @@ -3811,7 +4002,7 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h } ssh_gssapi_client; typedef struct ssh_gssapi_mech_struct { -@@ -84,6 +111,7 @@ typedef struct ssh_gssapi_mech_struct { +@@ -84,6 +113,7 @@ typedef struct ssh_gssapi_mech_struct { int (*userok) (ssh_gssapi_client *, char *); int (*localname) (ssh_gssapi_client *, char **); void (*storecreds) (ssh_gssapi_client *); @@ -3819,12 +4010,22 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h } ssh_gssapi_mech; typedef struct { -@@ -94,10 +122,11 @@ typedef struct { +@@ -94,10 +124,21 @@ typedef struct { gss_OID oid; /* client */ gss_cred_id_t creds; /* server */ gss_name_t client; /* server */ - gss_cred_id_t client_creds; /* server */ + gss_cred_id_t client_creds; /* both */ ++ struct sshbuf *shared_secret; /* both */ ++ struct sshbuf *server_pubkey; /* server */ ++ struct sshbuf *server_blob; /* client */ ++ struct sshbuf *server_host_key_blob; /* client */ ++ gss_buffer_desc msg_tok; /* client */ ++ gss_buffer_desc buf; /* both */ ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; /* both */ ++ size_t hashlen; /* both */ ++ int first; /* client */ ++ BIGNUM *dh_client_pub; /* server (gex) */ } Gssctxt; extern ssh_gssapi_mech *supported_mechs[]; @@ -3832,7 +4033,7 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -108,6 +137,7 @@ OM_uint32 ssh_gssapi_test_oid_supported( +@@ -108,6 +149,7 @@ OM_uint32 ssh_gssapi_test_oid_supported( struct sshbuf; int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *); @@ -3840,7 +4041,7 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, -@@ -122,17 +152,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **); +@@ -122,17 +164,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 *); @@ -3878,7 +4079,7 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h #endif /* _SSH_GSS_H */ diff --color -ruNp a/sshkey.c b/sshkey.c --- a/sshkey.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/sshkey.c 2024-08-28 12:35:41.260432315 +0200 ++++ b/sshkey.c 2024-09-16 11:46:34.706940139 +0200 @@ -131,6 +131,75 @@ extern const struct sshkey_impl sshkey_x extern const struct sshkey_impl sshkey_xmss_cert_impl; #endif @@ -3974,7 +4175,7 @@ diff --color -ruNp a/sshkey.c b/sshkey.c continue; diff --color -ruNp a/sshkey.h b/sshkey.h --- a/sshkey.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/sshkey.h 2024-08-28 12:35:41.260432315 +0200 ++++ b/sshkey.h 2024-09-16 11:46:34.706940139 +0200 @@ -71,6 +71,7 @@ enum sshkey_types { KEY_ECDSA_SK_CERT, KEY_ED25519_SK, diff --git a/openssh-9.6p1-gsskex-new-api.patch b/openssh-9.6p1-gsskex-new-api.patch deleted file mode 100644 index 0f2eabb..0000000 --- a/openssh-9.6p1-gsskex-new-api.patch +++ /dev/null @@ -1,1965 +0,0 @@ -diff --color -ruNp a/gss-genr.c b/gss-genr.c ---- a/gss-genr.c 2024-05-16 15:49:43.999411060 +0200 -+++ b/gss-genr.c 2024-06-26 12:17:55.586856954 +0200 -@@ -346,6 +346,7 @@ ssh_gssapi_build_ctx(Gssctxt **ctx) - (*ctx)->creds = GSS_C_NO_CREDENTIAL; - (*ctx)->client = GSS_C_NO_NAME; - (*ctx)->client_creds = GSS_C_NO_CREDENTIAL; -+ (*ctx)->first = 1; - } - - /* Delete our context, providing it has been built correctly */ -@@ -371,6 +372,12 @@ ssh_gssapi_delete_ctx(Gssctxt **ctx) - gss_release_name(&ms, &(*ctx)->client); - if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) - gss_release_cred(&ms, &(*ctx)->client_creds); -+ sshbuf_free((*ctx)->shared_secret); -+ sshbuf_free((*ctx)->server_pubkey); -+ sshbuf_free((*ctx)->server_host_key_blob); -+ sshbuf_free((*ctx)->server_blob); -+ explicit_bzero((*ctx)->hash, sizeof((*ctx)->hash)); -+ BN_clear_free((*ctx)->dh_client_pub); - - free(*ctx); - *ctx = NULL; -diff --color -ruNp a/kexgssc.c b/kexgssc.c ---- a/kexgssc.c 2024-05-16 15:49:43.820407648 +0200 -+++ b/kexgssc.c 2024-07-02 16:26:25.628746744 +0200 -@@ -47,566 +47,658 @@ - - #include "ssh-gss.h" - --int --kexgss_client(struct ssh *ssh) -+static int input_kexgss_hostkey(int, u_int32_t, struct ssh *); -+static int input_kexgss_continue(int, u_int32_t, struct ssh *); -+static int input_kexgss_complete(int, u_int32_t, struct ssh *); -+static int input_kexgss_error(int, u_int32_t, struct ssh *); -+static int input_kexgssgex_group(int, u_int32_t, struct ssh *); -+static int input_kexgssgex_continue(int, u_int32_t, struct ssh *); -+static int input_kexgssgex_complete(int, u_int32_t, struct ssh *); -+ -+static int -+kexgss_final(struct ssh *ssh) - { - struct kex *kex = ssh->kex; -- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, -- recv_tok = GSS_C_EMPTY_BUFFER, -- gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; -- Gssctxt *ctxt; -- OM_uint32 maj_status, min_status, ret_flags; -- struct sshbuf *server_blob = NULL; -- struct sshbuf *shared_secret = NULL; -- struct sshbuf *server_host_key_blob = NULL; -+ Gssctxt *gss = kex->gss; - struct sshbuf *empty = NULL; -- u_char *msg; -- int type = 0; -- int first = 1; -+ struct sshbuf *shared_secret = NULL; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t hashlen; -- u_char c; - int r; - -- /* Initialise our GSSAPI world */ -- ssh_gssapi_build_ctx(&ctxt); -- if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) -- == GSS_C_NO_OID) -- fatal("Couldn't identify host exchange"); -- -- if (ssh_gssapi_import_name(ctxt, kex->gss_host)) -- fatal("Couldn't import hostname"); -- -- if (kex->gss_client && -- ssh_gssapi_client_identity(ctxt, kex->gss_client)) -- fatal("Couldn't acquire client credentials"); -- -- /* Step 1 */ -- switch (kex->kex_type) { -- case KEX_GSS_GRP1_SHA1: -- case KEX_GSS_GRP14_SHA1: -- case KEX_GSS_GRP14_SHA256: -- case KEX_GSS_GRP16_SHA512: -- r = kex_dh_keypair(kex); -- break; -- case KEX_GSS_NISTP256_SHA256: -- r = kex_ecdh_keypair(kex); -- break; -- case KEX_GSS_C25519_SHA256: -- r = kex_c25519_keypair(kex); -- break; -- default: -- fatal_f("Unexpected KEX type %d", kex->kex_type); -- } -- if (r != 0) { -- ssh_gssapi_delete_ctx(&ctxt); -- return r; -- } -- -- token_ptr = GSS_C_NO_BUFFER; -- -- do { -- debug("Calling gss_init_sec_context"); -- -- maj_status = ssh_gssapi_init_ctx(ctxt, -- kex->gss_deleg_creds, token_ptr, &send_tok, -- &ret_flags); -- -- if (GSS_ERROR(maj_status)) { -- /* XXX Useles code: Missing send? */ -- if (send_tok.length != 0) { -- if ((r = sshpkt_start(ssh, -- SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, -- send_tok.length)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- } -- fatal("gss_init_context failed"); -- } -- -- /* If we've got an old receive buffer get rid of it */ -- if (token_ptr != GSS_C_NO_BUFFER) -- gss_release_buffer(&min_status, &recv_tok); -- -- if (maj_status == GSS_S_COMPLETE) { -- /* If mutual state flag is not true, kex fails */ -- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -- fatal("Mutual authentication failed"); -- -- /* If integ avail flag is not true kex fails */ -- if (!(ret_flags & GSS_C_INTEG_FLAG)) -- fatal("Integrity check failed"); -- } -- -- /* -- * If we have data to send, then the last message that we -- * received cannot have been a 'complete'. -- */ -- if (send_tok.length != 0) { -- if (first) { -- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, -- send_tok.length)) != 0 || -- (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) -- fatal("failed to construct packet: %s", ssh_err(r)); -- first = 0; -- } else { -- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, -- send_tok.length)) != 0) -- fatal("failed to construct packet: %s", ssh_err(r)); -- } -- if ((r = sshpkt_send(ssh)) != 0) -- fatal("failed to send packet: %s", ssh_err(r)); -- gss_release_buffer(&min_status, &send_tok); -- -- /* If we've sent them data, they should reply */ -- do { -- type = ssh_packet_read(ssh); -- if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -- u_char *tmp = NULL; -- size_t tmp_len = 0; -- -- debug("Received KEXGSS_HOSTKEY"); -- if (server_host_key_blob) -- fatal("Server host key received more than once"); -- if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) -- fatal("Failed to read server host key: %s", ssh_err(r)); -- if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) -- fatal("sshbuf_from failed"); -- } -- } while (type == SSH2_MSG_KEXGSS_HOSTKEY); -- -- switch (type) { -- case SSH2_MSG_KEXGSS_CONTINUE: -- debug("Received GSSAPI_CONTINUE"); -- if (maj_status == GSS_S_COMPLETE) -- fatal("GSSAPI Continue received from server when complete"); -- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -- &recv_tok)) != 0 || -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("Failed to read token: %s", ssh_err(r)); -- break; -- case SSH2_MSG_KEXGSS_COMPLETE: -- debug("Received GSSAPI_COMPLETE"); -- if (msg_tok.value != NULL) -- fatal("Received GSSAPI_COMPLETE twice?"); -- if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || -- (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -- &msg_tok)) != 0) -- fatal("Failed to read message: %s", ssh_err(r)); -- -- /* Is there a token included? */ -- if ((r = sshpkt_get_u8(ssh, &c)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- if (c) { -- if ((r = ssh_gssapi_sshpkt_get_buffer_desc( -- ssh, &recv_tok)) != 0) -- fatal("Failed to read token: %s", ssh_err(r)); -- /* If we're already complete - protocol error */ -- if (maj_status == GSS_S_COMPLETE) -- sshpkt_disconnect(ssh, "Protocol error: received token when complete"); -- } else { -- /* No token included */ -- if (maj_status != GSS_S_COMPLETE) -- sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); -- } -- if ((r = sshpkt_get_end(ssh)) != 0) { -- fatal("Expecting end of packet."); -- } -- break; -- case SSH2_MSG_KEXGSS_ERROR: -- debug("Received Error"); -- if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || -- (r = sshpkt_get_u32(ssh, &min_status)) != 0 || -- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || -- (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt_get failed: %s", ssh_err(r)); -- fatal("GSSAPI Error: \n%.400s", msg); -- default: -- sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", -- type); -- } -- token_ptr = &recv_tok; -- } else { -- /* No data, and not complete */ -- if (maj_status != GSS_S_COMPLETE) -- fatal("Not complete, and no token output"); -- } -- } while (maj_status & GSS_S_CONTINUE_NEEDED); -- - /* - * We _must_ have received a COMPLETE message in reply from the - * server, which will have set server_blob and msg_tok - */ - -- if (type != SSH2_MSG_KEXGSS_COMPLETE) -- fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); -- - /* compute shared secret */ - switch (kex->kex_type) { - case KEX_GSS_GRP1_SHA1: - case KEX_GSS_GRP14_SHA1: - case KEX_GSS_GRP14_SHA256: - case KEX_GSS_GRP16_SHA512: -- r = kex_dh_dec(kex, server_blob, &shared_secret); -+ r = kex_dh_dec(kex, gss->server_blob, &shared_secret); - break; - case KEX_GSS_C25519_SHA256: -- if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80) -+ if (sshbuf_ptr(gss->server_blob)[sshbuf_len(gss->server_blob)] & 0x80) - fatal("The received key has MSB of last octet set!"); -- r = kex_c25519_dec(kex, server_blob, &shared_secret); -+ r = kex_c25519_dec(kex, gss->server_blob, &shared_secret); - break; - case KEX_GSS_NISTP256_SHA256: -- if (sshbuf_len(server_blob) != 65) -- fatal("The received NIST-P256 key did not match" -- "expected length (expected 65, got %zu)", sshbuf_len(server_blob)); -+ if (sshbuf_len(gss->server_blob) != 65) -+ fatal("The received NIST-P256 key did not match " -+ "expected length (expected 65, got %zu)", -+ sshbuf_len(gss->server_blob)); - -- if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) -+ if (sshbuf_ptr(gss->server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) - fatal("The received NIST-P256 key does not have first octet 0x04"); - -- r = kex_ecdh_dec(kex, server_blob, &shared_secret); -+ r = kex_ecdh_dec(kex, gss->server_blob, &shared_secret); - break; - default: - r = SSH_ERR_INVALID_ARGUMENT; - break; - } -- if (r != 0) -+ if (r != 0) { -+ ssh_gssapi_delete_ctx(&kex->gss); - goto out; -+ } - - if ((empty = sshbuf_new()) == NULL) { -+ ssh_gssapi_delete_ctx(&kex->gss); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - - hashlen = sizeof(hash); -- if ((r = kex_gen_hash( -- kex->hash_alg, -- kex->client_version, -- kex->server_version, -- kex->my, -- kex->peer, -- (server_host_key_blob ? server_host_key_blob : empty), -- kex->client_pub, -- server_blob, -- shared_secret, -- hash, &hashlen)) != 0) -+ r = kex_gen_hash(kex->hash_alg, kex->client_version, -+ kex->server_version, kex->my, kex->peer, -+ (gss->server_host_key_blob ? gss->server_host_key_blob : empty), -+ kex->client_pub, gss->server_blob, shared_secret, -+ hash, &hashlen); -+ sshbuf_free(empty); -+ if (r != 0) - fatal_f("Unexpected KEX type %d", kex->kex_type); - -- gssbuf.value = hash; -- gssbuf.length = hashlen; -+ gss->buf.value = hash; -+ gss->buf.length = hashlen; - - /* Verify that the hash matches the MIC we just got. */ -- if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) -+ if (GSS_ERROR(ssh_gssapi_checkmic(gss, &gss->buf, &gss->msg_tok))) - sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); - -- gss_release_buffer(&min_status, &msg_tok); -+ gss_release_buffer(&gss->minor, &gss->msg_tok); - - if (kex->gss_deleg_creds) -- ssh_gssapi_credentials_updated(ctxt); -+ ssh_gssapi_credentials_updated(gss); - - if (gss_kex_context == NULL) -- gss_kex_context = ctxt; -+ gss_kex_context = gss; - else -- ssh_gssapi_delete_ctx(&ctxt); -+ ssh_gssapi_delete_ctx(&kex->gss); - - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); - -+ if (kex->gss != NULL) { -+ sshbuf_free(gss->server_host_key_blob); -+ gss->server_host_key_blob = NULL; -+ sshbuf_free(gss->server_blob); -+ gss->server_blob = NULL; -+ } - out: -- explicit_bzero(hash, sizeof(hash)); - explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); -- sshbuf_free(empty); -- sshbuf_free(server_host_key_blob); -- sshbuf_free(server_blob); -+ explicit_bzero(hash, sizeof(hash)); - sshbuf_free(shared_secret); - sshbuf_free(kex->client_pub); - kex->client_pub = NULL; - return r; - } - -+static int -+kexgss_init_ctx(struct ssh *ssh, -+ gss_buffer_desc *token_ptr) -+{ -+ struct kex *kex = ssh->kex; -+ Gssctxt *gss = kex->gss; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ OM_uint32 ret_flags; -+ int r; -+ -+ debug("Calling gss_init_sec_context"); -+ -+ gss->major = ssh_gssapi_init_ctx(gss, kex->gss_deleg_creds, -+ token_ptr, &send_tok, &ret_flags); -+ -+ if (GSS_ERROR(gss->major)) { -+ /* XXX Useless code: Missing send? */ -+ if (send_tok.length != 0) { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ } -+ fatal("gss_init_context failed"); -+ } -+ -+ /* If we've got an old receive buffer get rid of it */ -+ if (token_ptr != GSS_C_NO_BUFFER) -+ gss_release_buffer(&gss->minor, token_ptr); -+ -+ if (gss->major == GSS_S_COMPLETE) { -+ /* If mutual state flag is not true, kex fails */ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual authentication failed"); -+ -+ /* If integ avail flag is not true kex fails */ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity check failed"); -+ } -+ -+ /* -+ * If we have data to send, then the last message that we -+ * received cannot have been a 'complete'. -+ */ -+ if (send_tok.length != 0) { -+ if (gss->first) { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -+ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) -+ fatal("failed to construct packet: %s", ssh_err(r)); -+ gss->first = 0; -+ } else { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) -+ fatal("failed to construct packet: %s", ssh_err(r)); -+ } -+ if ((r = sshpkt_send(ssh)) != 0) -+ fatal("failed to send packet: %s", ssh_err(r)); -+ gss_release_buffer(&gss->minor, &send_tok); -+ -+ /* If we've sent them data, they should reply */ -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, &input_kexgss_hostkey); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgss_continue); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, &input_kexgss_complete); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, &input_kexgss_error); -+ return 0; -+ } -+ /* No data, and not complete */ -+ if (gss->major != GSS_S_COMPLETE) -+ fatal("Not complete, and no token output"); -+ -+ if (gss->major & GSS_S_CONTINUE_NEEDED) -+ return kexgss_init_ctx(ssh, token_ptr); -+ -+ return kexgss_final(ssh); -+} -+ - int --kexgssgex_client(struct ssh *ssh) -+kexgss_client(struct ssh *ssh) - { - struct kex *kex = ssh->kex; -- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, -- recv_tok = GSS_C_EMPTY_BUFFER, gssbuf, -- msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; -- Gssctxt *ctxt; -- OM_uint32 maj_status, min_status, ret_flags; -- struct sshbuf *shared_secret = NULL; -- BIGNUM *p = NULL; -- BIGNUM *g = NULL; -- struct sshbuf *buf = NULL; -- struct sshbuf *server_host_key_blob = NULL; -- struct sshbuf *server_blob = NULL; -- BIGNUM *dh_server_pub = NULL; -- u_char *msg; -- int type = 0; -- int first = 1; -- u_char hash[SSH_DIGEST_MAX_LENGTH]; -- size_t hashlen; -- const BIGNUM *pub_key, *dh_p, *dh_g; -- int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; -- struct sshbuf *empty = NULL; -- u_char c; - int r; - - /* Initialise our GSSAPI world */ -- ssh_gssapi_build_ctx(&ctxt); -- if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) -- == GSS_C_NO_OID) -+ ssh_gssapi_build_ctx(&kex->gss); -+ if (ssh_gssapi_id_kex(kex->gss, kex->name, kex->kex_type) == GSS_C_NO_OID) - fatal("Couldn't identify host exchange"); - -- if (ssh_gssapi_import_name(ctxt, kex->gss_host)) -+ if (ssh_gssapi_import_name(kex->gss, kex->gss_host)) - fatal("Couldn't import hostname"); - - if (kex->gss_client && -- ssh_gssapi_client_identity(ctxt, kex->gss_client)) -+ ssh_gssapi_client_identity(kex->gss, kex->gss_client)) - fatal("Couldn't acquire client credentials"); - -- debug("Doing group exchange"); -- nbits = dh_estimate(kex->dh_need * 8); -+ /* Step 1 */ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ case KEX_GSS_GRP14_SHA256: -+ case KEX_GSS_GRP16_SHA512: -+ r = kex_dh_keypair(kex); -+ break; -+ case KEX_GSS_NISTP256_SHA256: -+ r = kex_ecdh_keypair(kex); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ r = kex_c25519_keypair(kex); -+ break; -+ default: -+ fatal_f("Unexpected KEX type %d", kex->kex_type); -+ } -+ if (r != 0) { -+ ssh_gssapi_delete_ctx(&kex->gss); -+ return r; -+ } -+ return kexgss_init_ctx(ssh, GSS_C_NO_BUFFER); -+} - -- kex->min = DH_GRP_MIN; -- kex->max = DH_GRP_MAX; -- kex->nbits = nbits; -- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || -- (r = sshpkt_put_u32(ssh, min)) != 0 || -- (r = sshpkt_put_u32(ssh, nbits)) != 0 || -- (r = sshpkt_put_u32(ssh, max)) != 0 || -- (r = sshpkt_send(ssh)) != 0) -- fatal("Failed to construct a packet: %s", ssh_err(r)); -+static int -+input_kexgss_hostkey(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ u_char *tmp = NULL; -+ size_t tmp_len = 0; -+ int r; -+ -+ debug("Received KEXGSS_HOSTKEY"); -+ if (gss->server_host_key_blob) -+ fatal("Server host key received more than once"); -+ if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) -+ fatal("Failed to read server host key: %s", ssh_err(r)); -+ if ((gss->server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) -+ fatal("sshbuf_from failed"); -+ return 0; -+} - -- if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0) -- fatal("Error: %s", ssh_err(r)); -+static int -+input_kexgss_continue(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; -+ int r; - -- if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || -- (r = sshpkt_get_bignum2(ssh, &g)) != 0 || -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); -+ -+ debug("Received GSSAPI_CONTINUE"); -+ if (gss->major == GSS_S_COMPLETE) -+ fatal("GSSAPI Continue received from server when complete"); -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || - (r = sshpkt_get_end(ssh)) != 0) -- fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); -+ fatal("Failed to read token: %s", ssh_err(r)); -+ if (!(gss->major & GSS_S_CONTINUE_NEEDED)) -+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); -+ return kexgss_init_ctx(ssh, &recv_tok); -+} - -- if (BN_num_bits(p) < min || BN_num_bits(p) > max) -- fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", -- min, BN_num_bits(p), max); -+static int -+input_kexgss_complete(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; -+ u_char c; -+ int r; - -- if ((kex->dh = dh_new_group(g, p)) == NULL) -- fatal("dn_new_group() failed"); -- p = g = NULL; /* belong to kex->dh now */ -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); -+ -+ debug("Received GSSAPI_COMPLETE"); -+ if (gss->msg_tok.value != NULL) -+ fatal("Received GSSAPI_COMPLETE twice?"); -+ if ((r = sshpkt_getb_froms(ssh, &gss->server_blob)) != 0 || -+ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &gss->msg_tok)) != 0) -+ fatal("Failed to read message: %s", ssh_err(r)); -+ -+ /* Is there a token included? */ -+ if ((r = sshpkt_get_u8(ssh, &c)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ if (c) { -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0) -+ fatal("Failed to read token: %s", ssh_err(r)); -+ /* If we're already complete - protocol error */ -+ if (gss->major == GSS_S_COMPLETE) -+ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); -+ } else { -+ if (gss->major != GSS_S_COMPLETE) -+ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); -+ } -+ if ((r = sshpkt_get_end(ssh)) != 0) -+ fatal("Expecting end of packet."); - -- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) -- goto out; -- DH_get0_key(kex->dh, &pub_key, NULL); -+ if (gss->major & GSS_S_CONTINUE_NEEDED) -+ return kexgss_init_ctx(ssh, &recv_tok); - -- token_ptr = GSS_C_NO_BUFFER; -+ return kexgss_final(ssh); -+} - -- do { -- /* Step 2 - call GSS_Init_sec_context() */ -- debug("Calling gss_init_sec_context"); -- -- maj_status = ssh_gssapi_init_ctx(ctxt, -- kex->gss_deleg_creds, token_ptr, &send_tok, -- &ret_flags); -- -- if (GSS_ERROR(maj_status)) { -- /* XXX Useles code: Missing send? */ -- if (send_tok.length != 0) { -- if ((r = sshpkt_start(ssh, -- SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, -- send_tok.length)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- } -- fatal("gss_init_context failed"); -- } -+static int -+input_kexgss_error(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ u_char *msg; -+ int r; - -- /* If we've got an old receive buffer get rid of it */ -- if (token_ptr != GSS_C_NO_BUFFER) -- gss_release_buffer(&min_status, &recv_tok); -- -- if (maj_status == GSS_S_COMPLETE) { -- /* If mutual state flag is not true, kex fails */ -- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -- fatal("Mutual authentication failed"); -- -- /* If integ avail flag is not true kex fails */ -- if (!(ret_flags & GSS_C_INTEG_FLAG)) -- fatal("Integrity check failed"); -- } -+ debug("Received Error"); -+ if ((r = sshpkt_get_u32(ssh, &gss->major)) != 0 || -+ (r = sshpkt_get_u32(ssh, &gss->minor)) != 0 || -+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || -+ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt_get failed: %s", ssh_err(r)); -+ fatal("GSSAPI Error: \n%.400s", msg); -+ return 0; -+} - -- /* -- * If we have data to send, then the last message that we -- * received cannot have been a 'complete'. -- */ -- if (send_tok.length != 0) { -- if (first) { -- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, -- send_tok.length)) != 0 || -- (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- first = 0; -- } else { -- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -- (r = sshpkt_put_string(ssh,send_tok.value, -- send_tok.length)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- } -- if ((r = sshpkt_send(ssh)) != 0) -- fatal("sshpkt_send failed: %s", ssh_err(r)); -- gss_release_buffer(&min_status, &send_tok); -- -- /* If we've sent them data, they should reply */ -- do { -- type = ssh_packet_read(ssh); -- if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -- u_char *tmp = NULL; -- size_t tmp_len = 0; -- -- debug("Received KEXGSS_HOSTKEY"); -- if (server_host_key_blob) -- fatal("Server host key received more than once"); -- if ((r = sshpkt_get_string(ssh, &tmp, &tmp_len)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- if ((server_host_key_blob = sshbuf_from(tmp, tmp_len)) == NULL) -- fatal("sshbuf_from failed"); -- } -- } while (type == SSH2_MSG_KEXGSS_HOSTKEY); -- -- switch (type) { -- case SSH2_MSG_KEXGSS_CONTINUE: -- debug("Received GSSAPI_CONTINUE"); -- if (maj_status == GSS_S_COMPLETE) -- fatal("GSSAPI Continue received from server when complete"); -- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -- &recv_tok)) != 0 || -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- break; -- case SSH2_MSG_KEXGSS_COMPLETE: -- debug("Received GSSAPI_COMPLETE"); -- if (msg_tok.value != NULL) -- fatal("Received GSSAPI_COMPLETE twice?"); -- if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || -- (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -- &msg_tok)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- -- /* Is there a token included? */ -- if ((r = sshpkt_get_u8(ssh, &c)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- if (c) { -- if ((r = ssh_gssapi_sshpkt_get_buffer_desc( -- ssh, &recv_tok)) != 0 || -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- /* If we're already complete - protocol error */ -- if (maj_status == GSS_S_COMPLETE) -- sshpkt_disconnect(ssh, "Protocol error: received token when complete"); -- } else { -- /* No token included */ -- if (maj_status != GSS_S_COMPLETE) -- sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); -- } -- break; -- case SSH2_MSG_KEXGSS_ERROR: -- debug("Received Error"); -- if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || -- (r = sshpkt_get_u32(ssh, &min_status)) != 0 || -- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || -- (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- fatal("GSSAPI Error: \n%.400s", msg); -- default: -- sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", -- type); -- } -- token_ptr = &recv_tok; -- } else { -- /* No data, and not complete */ -- if (maj_status != GSS_S_COMPLETE) -- fatal("Not complete, and no token output"); -- } -- } while (maj_status & GSS_S_CONTINUE_NEEDED); -+/*******************************************************/ -+/******************** KEXGSSGEX ************************/ -+/*******************************************************/ -+ -+int -+kexgssgex_client(struct ssh *ssh) -+{ -+ struct kex *kex = ssh->kex; -+ int r; -+ -+ /* Initialise our GSSAPI world */ -+ ssh_gssapi_build_ctx(&kex->gss); -+ if (ssh_gssapi_id_kex(kex->gss, kex->name, kex->kex_type) == GSS_C_NO_OID) -+ fatal("Couldn't identify host exchange"); -+ -+ if (ssh_gssapi_import_name(kex->gss, kex->gss_host)) -+ fatal("Couldn't import hostname"); -+ -+ if (kex->gss_client && -+ ssh_gssapi_client_identity(kex->gss, kex->gss_client)) -+ fatal("Couldn't acquire client credentials"); -+ -+ debug("Doing group exchange"); -+ kex->min = DH_GRP_MIN; -+ kex->max = DH_GRP_MAX; -+ kex->nbits = dh_estimate(kex->dh_need * 8); -+ -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || -+ (r = sshpkt_put_u32(ssh, kex->min)) != 0 || -+ (r = sshpkt_put_u32(ssh, kex->nbits)) != 0 || -+ (r = sshpkt_put_u32(ssh, kex->max)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal("Failed to construct a packet: %s", ssh_err(r)); -+ -+ debug("Wait SSH2_MSG_KEXGSS_GROUP"); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUP, &input_kexgssgex_group); -+ return 0; -+} -+ -+static int -+kexgssgex_final(struct ssh *ssh) -+{ -+ struct kex *kex = ssh->kex; -+ Gssctxt *gss = kex->gss; -+ struct sshbuf *buf = NULL; -+ struct sshbuf *empty = NULL; -+ struct sshbuf *shared_secret = NULL; -+ BIGNUM *dh_server_pub = NULL; -+ const BIGNUM *pub_key, *dh_p, *dh_g; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; -+ int r = SSH_ERR_INTERNAL_ERROR; - - /* - * We _must_ have received a COMPLETE message in reply from the -- * server, which will have set dh_server_pub and msg_tok -+ * server, which will have set server_blob and msg_tok - */ - -- if (type != SSH2_MSG_KEXGSS_COMPLETE) -- fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); -- - /* 7. C verifies that the key Q_S is valid */ - /* 8. C computes shared secret */ - if ((buf = sshbuf_new()) == NULL || -- (r = sshbuf_put_stringb(buf, server_blob)) != 0 || -- (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) -+ (r = sshbuf_put_stringb(buf, gss->server_blob)) != 0 || -+ (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) { -+ ssh_gssapi_delete_ctx(&kex->gss); - goto out; -+ } - sshbuf_free(buf); - buf = NULL; - - if ((shared_secret = sshbuf_new()) == NULL) { -+ ssh_gssapi_delete_ctx(&kex->gss); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - -- if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) -+ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) { -+ ssh_gssapi_delete_ctx(&kex->gss); - goto out; -+ } -+ - if ((empty = sshbuf_new()) == NULL) { -+ ssh_gssapi_delete_ctx(&kex->gss); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - -+ DH_get0_key(kex->dh, &pub_key, NULL); - DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); - hashlen = sizeof(hash); -- if ((r = kexgex_hash( -- kex->hash_alg, -- kex->client_version, -- kex->server_version, -- kex->my, -- kex->peer, -- (server_host_key_blob ? server_host_key_blob : empty), -- kex->min, kex->nbits, kex->max, -- dh_p, dh_g, -- pub_key, -- dh_server_pub, -- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), -- hash, &hashlen)) != 0) -+ r = kexgex_hash(kex->hash_alg, kex->client_version, -+ kex->server_version, kex->my, kex->peer, -+ (gss->server_host_key_blob ? gss->server_host_key_blob : empty), -+ kex->min, kex->nbits, kex->max, dh_p, dh_g, pub_key, -+ dh_server_pub, sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), -+ hash, &hashlen); -+ sshbuf_free(empty); -+ if (r != 0) - fatal("Failed to calculate hash: %s", ssh_err(r)); - -- gssbuf.value = hash; -- gssbuf.length = hashlen; -+ gss->buf.value = hash; -+ gss->buf.length = hashlen; - - /* Verify that the hash matches the MIC we just got. */ -- if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) -+ if (GSS_ERROR(ssh_gssapi_checkmic(gss, &gss->buf, &gss->msg_tok))) - sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); - -- gss_release_buffer(&min_status, &msg_tok); -+ gss_release_buffer(&gss->minor, &gss->msg_tok); - - if (kex->gss_deleg_creds) -- ssh_gssapi_credentials_updated(ctxt); -+ ssh_gssapi_credentials_updated(gss); - - if (gss_kex_context == NULL) -- gss_kex_context = ctxt; -+ gss_kex_context = gss; - else -- ssh_gssapi_delete_ctx(&ctxt); -+ ssh_gssapi_delete_ctx(&kex->gss); - - /* Finally derive the keys and send them */ - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) - r = kex_send_newkeys(ssh); -+ -+ if (kex->gss != NULL) { -+ sshbuf_free(gss->server_host_key_blob); -+ gss->server_host_key_blob = NULL; -+ sshbuf_free(gss->server_blob); -+ gss->server_blob = NULL; -+ } - out: -- sshbuf_free(buf); -- sshbuf_free(server_blob); -- sshbuf_free(empty); - explicit_bzero(hash, sizeof(hash)); - DH_free(kex->dh); - kex->dh = NULL; - BN_clear_free(dh_server_pub); - sshbuf_free(shared_secret); -- sshbuf_free(server_host_key_blob); - return r; - } - -+static int -+kexgssgex_init_ctx(struct ssh *ssh, -+ gss_buffer_desc *token_ptr) -+{ -+ struct kex *kex = ssh->kex; -+ Gssctxt *gss = kex->gss; -+ const BIGNUM *pub_key; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ OM_uint32 ret_flags; -+ int r; -+ -+ /* Step 2 - call GSS_Init_sec_context() */ -+ debug("Calling gss_init_sec_context"); -+ -+ gss->major = ssh_gssapi_init_ctx(gss, kex->gss_deleg_creds, -+ token_ptr, &send_tok, &ret_flags); -+ -+ if (GSS_ERROR(gss->major)) { -+ /* XXX Useless code: Missing send? */ -+ if (send_tok.length != 0) { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ } -+ fatal("gss_init_context failed"); -+ } -+ -+ /* If we've got an old receive buffer get rid of it */ -+ if (token_ptr != GSS_C_NO_BUFFER) -+ gss_release_buffer(&gss->minor, token_ptr); -+ -+ if (gss->major == GSS_S_COMPLETE) { -+ /* If mutual state flag is not true, kex fails */ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual authentication failed"); -+ -+ /* If integ avail flag is not true kex fails */ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity check failed"); -+ } -+ -+ /* -+ * If we have data to send, then the last message that we -+ * received cannot have been a 'complete'. -+ */ -+ if (send_tok.length != 0) { -+ if (gss->first) { -+ DH_get0_key(kex->dh, &pub_key, NULL); -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) -+ fatal("failed to construct packet: %s", ssh_err(r)); -+ gss->first = 0; -+ } else { -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) -+ fatal("failed to construct packet: %s", ssh_err(r)); -+ } -+ if ((r = sshpkt_send(ssh)) != 0) -+ fatal("failed to send packet: %s", ssh_err(r)); -+ gss_release_buffer(&gss->minor, &send_tok); -+ -+ /* If we've sent them data, they should reply */ -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, &input_kexgss_hostkey); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgssgex_continue); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, &input_kexgssgex_complete); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, &input_kexgss_error); -+ return 0; -+ } -+ /* No data, and not complete */ -+ if (gss->major != GSS_S_COMPLETE) -+ fatal("Not complete, and no token output"); -+ -+ if (gss->major & GSS_S_CONTINUE_NEEDED) -+ return kexgssgex_init_ctx(ssh, token_ptr); -+ -+ return kexgssgex_final(ssh); -+} -+ -+static int -+input_kexgssgex_group(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ struct kex *kex = ssh->kex; -+ BIGNUM *p = NULL; -+ BIGNUM *g = NULL; -+ int r; -+ -+ debug("Received SSH2_MSG_KEXGSS_GROUP"); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUP, NULL); -+ -+ if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || -+ (r = sshpkt_get_bignum2(ssh, &g)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); -+ -+ if (BN_num_bits(p) < kex->min || BN_num_bits(p) > kex->max) -+ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", -+ kex->min, BN_num_bits(p), kex->max); -+ -+ if ((kex->dh = dh_new_group(g, p)) == NULL) -+ fatal("dn_new_group() failed"); -+ p = g = NULL; /* belong to kex->dh now */ -+ -+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) { -+ ssh_gssapi_delete_ctx(&kex->gss); -+ DH_free(kex->dh); -+ kex->dh = NULL; -+ return r; -+ } -+ -+ return kexgssgex_init_ctx(ssh, GSS_C_NO_BUFFER); -+} -+ -+static int -+input_kexgssgex_continue(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; -+ int r; -+ -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); -+ -+ debug("Received GSSAPI_CONTINUE"); -+ if (gss->major == GSS_S_COMPLETE) -+ fatal("GSSAPI Continue received from server when complete"); -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("Failed to read token: %s", ssh_err(r)); -+ if (!(gss->major & GSS_S_CONTINUE_NEEDED)) -+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); -+ return kexgssgex_init_ctx(ssh, &recv_tok); -+} -+ -+static int -+input_kexgssgex_complete(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER; -+ u_char c; -+ int r; -+ -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_HOSTKEY, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_COMPLETE, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_ERROR, NULL); -+ -+ debug("Received GSSAPI_COMPLETE"); -+ if (gss->msg_tok.value != NULL) -+ fatal("Received GSSAPI_COMPLETE twice?"); -+ if ((r = sshpkt_getb_froms(ssh, &gss->server_blob)) != 0 || -+ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &gss->msg_tok)) != 0) -+ fatal("Failed to read message: %s", ssh_err(r)); -+ -+ /* Is there a token included? */ -+ if ((r = sshpkt_get_u8(ssh, &c)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ if (c) { -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0) -+ fatal("Failed to read token: %s", ssh_err(r)); -+ /* If we're already complete - protocol error */ -+ if (gss->major == GSS_S_COMPLETE) -+ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); -+ } else { -+ if (gss->major != GSS_S_COMPLETE) -+ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); -+ } -+ if ((r = sshpkt_get_end(ssh)) != 0) -+ fatal("Expecting end of packet."); -+ -+ if (gss->major & GSS_S_CONTINUE_NEEDED) -+ return kexgssgex_init_ctx(ssh, &recv_tok); -+ -+ return kexgssgex_final(ssh); -+} -+ - #endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --color -ruNp a/kexgsss.c b/kexgsss.c ---- a/kexgsss.c 2024-05-16 15:49:43.820407648 +0200 -+++ b/kexgsss.c 2024-07-02 16:29:05.744790839 +0200 -@@ -50,33 +50,18 @@ - - extern ServerOptions options; - -+static int input_kexgss_init(int, u_int32_t, struct ssh *); -+static int input_kexgss_continue(int, u_int32_t, struct ssh *); -+static int input_kexgssgex_groupreq(int, u_int32_t, struct ssh *); -+static int input_kexgssgex_init(int, u_int32_t, struct ssh *); -+static int input_kexgssgex_continue(int, u_int32_t, struct ssh *); -+ - int - kexgss_server(struct ssh *ssh) - { - struct kex *kex = ssh->kex; -- OM_uint32 maj_status, min_status; -- -- /* -- * Some GSSAPI implementations use the input value of ret_flags (an -- * output variable) as a means of triggering mechanism specific -- * features. Initializing it to zero avoids inadvertently -- * activating this non-standard behaviour. -- */ -- -- OM_uint32 ret_flags = 0; -- gss_buffer_desc gssbuf = {0, NULL}, recv_tok, msg_tok; -- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -- Gssctxt *ctxt = NULL; -- struct sshbuf *shared_secret = NULL; -- struct sshbuf *client_pubkey = NULL; -- struct sshbuf *server_pubkey = NULL; -- struct sshbuf *empty = sshbuf_new(); -- int type = 0; - gss_OID oid; - char *mechs; -- u_char hash[SSH_DIGEST_MAX_LENGTH]; -- size_t hashlen; -- int r; - - /* Initialise GSSAPI */ - -@@ -92,135 +77,91 @@ kexgss_server(struct ssh *ssh) - debug2_f("Identifying %s", kex->name); - oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); - if (oid == GSS_C_NO_OID) -- fatal("Unknown gssapi mechanism"); -+ fatal("Unknown gssapi mechanism"); - - debug2_f("Acquiring credentials"); - -- if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) -+ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&kex->gss, oid))) - fatal("Unable to acquire credentials for the server"); - -- do { -- debug("Wait SSH2_MSG_KEXGSS_INIT"); -- type = ssh_packet_read(ssh); -- switch(type) { -- case SSH2_MSG_KEXGSS_INIT: -- if (gssbuf.value != NULL) -- fatal("Received KEXGSS_INIT after initialising"); -- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -- &recv_tok)) != 0 || -- (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -+ ssh_gssapi_build_ctx(&kex->gss); -+ if (kex->gss == NULL) -+ fatal("Unable to allocate memory for gss context"); -+ -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, &input_kexgss_init); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgss_continue); -+ debug("Wait SSH2_MSG_KEXGSS_INIT"); -+ return 0; -+} - -- switch (kex->kex_type) { -- case KEX_GSS_GRP1_SHA1: -- case KEX_GSS_GRP14_SHA1: -- case KEX_GSS_GRP14_SHA256: -- case KEX_GSS_GRP16_SHA512: -- r = kex_dh_enc(kex, client_pubkey, &server_pubkey, -- &shared_secret); -- break; -- case KEX_GSS_NISTP256_SHA256: -- r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, -- &shared_secret); -- break; -- case KEX_GSS_C25519_SHA256: -- r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, -- &shared_secret); -- break; -- default: -- fatal_f("Unexpected KEX type %d", kex->kex_type); -- } -- if (r != 0) -- goto out; -- -- /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ -- -- /* Calculate the hash early so we can free the -- * client_pubkey, which has reference to the parent -- * buffer state->incoming_packet -- */ -- hashlen = sizeof(hash); -- if ((r = kex_gen_hash( -- kex->hash_alg, -- kex->client_version, -- kex->server_version, -- kex->peer, -- kex->my, -- empty, -- client_pubkey, -- server_pubkey, -- shared_secret, -- hash, &hashlen)) != 0) -- goto out; -- -- gssbuf.value = hash; -- gssbuf.length = hashlen; -- -- sshbuf_free(client_pubkey); -- client_pubkey = NULL; -- -- break; -- case SSH2_MSG_KEXGSS_CONTINUE: -- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -- &recv_tok)) != 0 || -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- break; -- default: -- sshpkt_disconnect(ssh, -- "Protocol error: didn't expect packet type %d", -- type); -- } -+static inline void -+kexgss_accept_ctx(struct ssh *ssh, -+ gss_buffer_desc *recv_tok, -+ gss_buffer_desc *send_tok, -+ OM_uint32 *ret_flags) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ int r; - -- maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, -- &send_tok, &ret_flags); -+ gss->major = mm_ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags); -+ gss_release_buffer(&gss->minor, recv_tok); - -- gss_release_buffer(&min_status, &recv_tok); -+ if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) -+ fatal("Zero length token output when incomplete"); - -- if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) -- fatal("Zero length token output when incomplete"); -+ if (gss->buf.value == NULL) -+ fatal("No client public key"); - -- if (gssbuf.value == NULL) -- fatal("No client public key"); -+ if (gss->major & GSS_S_CONTINUE_NEEDED) { -+ debug("Sending GSSAPI_CONTINUE"); -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ gss_release_buffer(&gss->minor, send_tok); -+ } -+} - -- if (maj_status & GSS_S_CONTINUE_NEEDED) { -- debug("Sending GSSAPI_CONTINUE"); -- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -- (r = sshpkt_send(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- gss_release_buffer(&min_status, &send_tok); -- } -- } while (maj_status & GSS_S_CONTINUE_NEEDED); -+static inline int -+kexgss_final(struct ssh *ssh, -+ gss_buffer_desc *send_tok, -+ OM_uint32 *ret_flags) -+{ -+ struct kex *kex = ssh->kex; -+ Gssctxt *gss = kex->gss; -+ gss_buffer_desc msg_tok; -+ int r; -+ -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); - -- if (GSS_ERROR(maj_status)) { -- if (send_tok.length > 0) { -+ if (GSS_ERROR(gss->major)) { -+ if (send_tok->length > 0) { - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || - (r = sshpkt_send(ssh)) != 0) - fatal("sshpkt failed: %s", ssh_err(r)); - } - fatal("accept_ctx died"); - } - -- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ if (!(*ret_flags & GSS_C_MUTUAL_FLAG)) - fatal("Mutual Authentication flag wasn't set"); - -- if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ if (!(*ret_flags & GSS_C_INTEG_FLAG)) - fatal("Integrity flag wasn't set"); - -- if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) -+ if (GSS_ERROR(mm_ssh_gssapi_sign(gss, &gss->buf, &msg_tok))) - fatal("Couldn't get MIC"); - - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || -- (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || -+ (r = sshpkt_put_stringb(ssh, gss->server_pubkey)) != 0 || - (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) - fatal("sshpkt failed: %s", ssh_err(r)); - -- if (send_tok.length != 0) { -+ if (send_tok->length != 0) { - if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ -- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) -+ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0) - fatal("sshpkt failed: %s", ssh_err(r)); - } else { - if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ -@@ -229,59 +170,139 @@ kexgss_server(struct ssh *ssh) - if ((r = sshpkt_send(ssh)) != 0) - fatal("sshpkt_send failed: %s", ssh_err(r)); - -- gss_release_buffer(&min_status, &send_tok); -- gss_release_buffer(&min_status, &msg_tok); -+ gss_release_buffer(&gss->minor, send_tok); -+ gss_release_buffer(&gss->minor, &msg_tok); - - if (gss_kex_context == NULL) -- gss_kex_context = ctxt; -+ gss_kex_context = gss; - else -- ssh_gssapi_delete_ctx(&ctxt); -+ ssh_gssapi_delete_ctx(&kex->gss); - -- if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) -+ if ((r = kex_derive_keys(ssh, gss->hash, gss->hashlen, gss->shared_secret)) == 0) - r = kex_send_newkeys(ssh); - - /* If this was a rekey, then save out any delegated credentials we - * just exchanged. */ - if (options.gss_store_rekey) - ssh_gssapi_rekey_creds(); --out: -- sshbuf_free(empty); -- explicit_bzero(hash, sizeof(hash)); -- sshbuf_free(shared_secret); -- sshbuf_free(client_pubkey); -- sshbuf_free(server_pubkey); -+ -+ if (kex->gss != NULL) { -+ explicit_bzero(gss->hash, sizeof(gss->hash)); -+ sshbuf_free(gss->shared_secret); -+ gss->shared_secret = NULL; -+ sshbuf_free(gss->server_pubkey); -+ gss->server_pubkey = NULL; -+ } - return r; - } - --int --kexgssgex_server(struct ssh *ssh) -+static int -+input_kexgss_init(int type, -+ u_int32_t seq, -+ struct ssh *ssh) - { - struct kex *kex = ssh->kex; -- OM_uint32 maj_status, min_status; -+ Gssctxt *gss = kex->gss; -+ struct sshbuf *empty; -+ struct sshbuf *client_pubkey = NULL; -+ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; -+ OM_uint32 ret_flags = 0; -+ int r; -+ -+ debug("SSH2_MSG_KEXGSS_INIT received"); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); - -- /* -- * Some GSSAPI implementations use the input value of ret_flags (an -- * output variable) as a means of triggering mechanism specific -- * features. Initializing it to zero avoids inadvertently -- * activating this non-standard behaviour. -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || -+ (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ case KEX_GSS_GRP14_SHA256: -+ case KEX_GSS_GRP16_SHA512: -+ r = kex_dh_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); -+ break; -+ case KEX_GSS_NISTP256_SHA256: -+ r = kex_ecdh_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ r = kex_c25519_enc(kex, client_pubkey, &gss->server_pubkey, &gss->shared_secret); -+ break; -+ default: -+ fatal_f("Unexpected KEX type %d", kex->kex_type); -+ } -+ if (r != 0) { -+ sshbuf_free(client_pubkey); -+ ssh_gssapi_delete_ctx(&kex->gss); -+ return r; -+ } -+ -+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ -+ -+ if ((empty = sshbuf_new()) == NULL) { -+ sshbuf_free(client_pubkey); -+ ssh_gssapi_delete_ctx(&kex->gss); -+ return SSH_ERR_ALLOC_FAIL; -+ } -+ -+ /* Calculate the hash early so we can free the -+ * client_pubkey, which has reference to the parent -+ * buffer state->incoming_packet - */ -+ gss->hashlen = sizeof(gss->hash); -+ r = kex_gen_hash(kex->hash_alg, kex->client_version, kex->server_version, -+ kex->peer, kex->my, empty, client_pubkey, gss->server_pubkey, -+ gss->shared_secret, gss->hash, &gss->hashlen); -+ sshbuf_free(empty); -+ sshbuf_free(client_pubkey); -+ if (r != 0) { -+ ssh_gssapi_delete_ctx(&kex->gss); -+ return r; -+ } -+ -+ gss->buf.value = gss->hash; -+ gss->buf.length = gss->hashlen; -+ -+ kexgss_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); -+ if (gss->major & GSS_S_CONTINUE_NEEDED) -+ return 0; - -+ return kexgss_final(ssh, &send_tok, &ret_flags); -+} -+ -+static int -+input_kexgss_continue(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; - OM_uint32 ret_flags = 0; -- gss_buffer_desc gssbuf, recv_tok, msg_tok; -- gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -- Gssctxt *ctxt = NULL; -- struct sshbuf *shared_secret = NULL; -- int type = 0; -+ int r; -+ -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ kexgss_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); -+ if (gss->major & GSS_S_CONTINUE_NEEDED) -+ return 0; -+ -+ return kexgss_final(ssh, &send_tok, &ret_flags); -+} -+ -+/*******************************************************/ -+/******************** KEXGSSGEX ************************/ -+/*******************************************************/ -+ -+int -+kexgssgex_server(struct ssh *ssh) -+{ -+ struct kex *kex = ssh->kex; - gss_OID oid; - char *mechs; -- u_char hash[SSH_DIGEST_MAX_LENGTH]; -- size_t hashlen; -- BIGNUM *dh_client_pub = NULL; -- const BIGNUM *pub_key, *dh_p, *dh_g; -- int min = -1, max = -1, nbits = -1; -- int cmin = -1, cmax = -1; /* client proposal */ -- struct sshbuf *empty = sshbuf_new(); -- int r; - - /* Initialise GSSAPI */ - -@@ -289,153 +310,125 @@ kexgssgex_server(struct ssh *ssh) - * in the GSSAPI code are no longer available. This kludges them back - * into life - */ -- if (!ssh_gssapi_oid_table_ok()) -- if ((mechs = ssh_gssapi_server_mechanisms())) -- free(mechs); -+ if (!ssh_gssapi_oid_table_ok()) { -+ mechs = ssh_gssapi_server_mechanisms(); -+ free(mechs); -+ } - - debug2_f("Identifying %s", kex->name); - oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); - if (oid == GSS_C_NO_OID) -- fatal("Unknown gssapi mechanism"); -+ fatal("Unknown gssapi mechanism"); - - debug2_f("Acquiring credentials"); - -- if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&ctxt, oid))) -+ if (GSS_ERROR(mm_ssh_gssapi_server_ctx(&kex->gss, oid))) - fatal("Unable to acquire credentials for the server"); - -- /* 5. S generates an ephemeral key pair (do the allocations early) */ -- debug("Doing group exchange"); -- ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUPREQ); -- /* store client proposal to provide valid signature */ -- if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || -- (r = sshpkt_get_u32(ssh, &nbits)) != 0 || -- (r = sshpkt_get_u32(ssh, &cmax)) != 0 || -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- kex->nbits = nbits; -- kex->min = cmin; -- kex->max = cmax; -- min = MAX(DH_GRP_MIN, cmin); -- max = MIN(DH_GRP_MAX, cmax); -- nbits = MAXIMUM(DH_GRP_MIN, nbits); -- nbits = MINIMUM(DH_GRP_MAX, nbits); -- if (max < min || nbits < min || max < nbits) -- fatal("GSS_GEX, bad parameters: %d !< %d !< %d", -- min, nbits, max); -- kex->dh = mm_choose_dh(min, nbits, max); -- if (kex->dh == NULL) { -- sshpkt_disconnect(ssh, "Protocol error: no matching group found"); -- fatal("Protocol error: no matching group found"); -- } -+ ssh_gssapi_build_ctx(&kex->gss); -+ if (kex->gss == NULL) -+ fatal("Unable to allocate memory for gss context"); - -- DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); -- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 || -- (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || -- (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || -- (r = sshpkt_send(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- -- if ((r = ssh_packet_write_wait(ssh)) != 0) -- fatal("ssh_packet_write_wait: %s", ssh_err(r)); -- -- /* Compute our exchange value in parallel with the client */ -- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) -- goto out; -+ debug("Doing group exchange"); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUPREQ, &input_kexgssgex_groupreq); -+ return 0; -+} - -- do { -- debug("Wait SSH2_MSG_GSSAPI_INIT"); -- type = ssh_packet_read(ssh); -- switch(type) { -- case SSH2_MSG_KEXGSS_INIT: -- if (dh_client_pub != NULL) -- fatal("Received KEXGSS_INIT after initialising"); -- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -- &recv_tok)) != 0 || -- (r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -+static inline void -+kexgssgex_accept_ctx(struct ssh *ssh, -+ gss_buffer_desc *recv_tok, -+ gss_buffer_desc *send_tok, -+ OM_uint32 *ret_flags) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ int r; - -- /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ -- break; -- case SSH2_MSG_KEXGSS_CONTINUE: -- if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, -- &recv_tok)) != 0 || -- (r = sshpkt_get_end(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- break; -- default: -- sshpkt_disconnect(ssh, -- "Protocol error: didn't expect packet type %d", -- type); -- } -+ gss->major = mm_ssh_gssapi_accept_ctx(gss, recv_tok, send_tok, ret_flags); -+ gss_release_buffer(&gss->minor, recv_tok); - -- maj_status = mm_ssh_gssapi_accept_ctx(ctxt, &recv_tok, -- &send_tok, &ret_flags); -+ if (gss->major != GSS_S_COMPLETE && send_tok->length == 0) -+ fatal("Zero length token output when incomplete"); - -- gss_release_buffer(&min_status, &recv_tok); -+ if (gss->dh_client_pub == NULL) -+ fatal("No client public key"); - -- if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) -- fatal("Zero length token output when incomplete"); -+ if (gss->major & GSS_S_CONTINUE_NEEDED) { -+ debug("Sending GSSAPI_CONTINUE"); -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ gss_release_buffer(&gss->minor, send_tok); -+ } -+} - -- if (dh_client_pub == NULL) -- fatal("No client public key"); -+static inline int -+kexgssgex_final(struct ssh *ssh, -+ gss_buffer_desc *send_tok, -+ OM_uint32 *ret_flags) -+{ -+ struct kex *kex = ssh->kex; -+ Gssctxt *gss = kex->gss; -+ gss_buffer_desc msg_tok; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; -+ const BIGNUM *pub_key, *dh_p, *dh_g; -+ struct sshbuf *shared_secret = NULL; -+ struct sshbuf *empty = NULL; -+ int r; - -- if (maj_status & GSS_S_CONTINUE_NEEDED) { -- debug("Sending GSSAPI_CONTINUE"); -- if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -- (r = sshpkt_send(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -- gss_release_buffer(&min_status, &send_tok); -- } -- } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, NULL); - -- if (GSS_ERROR(maj_status)) { -- if (send_tok.length > 0) { -+ if (GSS_ERROR(gss->major)) { -+ if (send_tok->length > 0) { - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || -- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || -+ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0 || - (r = sshpkt_send(ssh)) != 0) - fatal("sshpkt failed: %s", ssh_err(r)); - } - fatal("accept_ctx died"); - } - -- if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ if (!(*ret_flags & GSS_C_MUTUAL_FLAG)) - fatal("Mutual Authentication flag wasn't set"); - -- if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ if (!(*ret_flags & GSS_C_INTEG_FLAG)) - fatal("Integrity flag wasn't set"); - - /* calculate shared secret */ -- if ((shared_secret = sshbuf_new()) == NULL) { -+ shared_secret = sshbuf_new(); -+ if (shared_secret == NULL) { -+ ssh_gssapi_delete_ctx(&kex->gss); - r = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) -+ if ((r = kex_dh_compute_key(kex, gss->dh_client_pub, shared_secret)) != 0) { -+ ssh_gssapi_delete_ctx(&kex->gss); - goto out; -+ } -+ -+ if ((empty = sshbuf_new()) == NULL) { -+ ssh_gssapi_delete_ctx(&kex->gss); -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } - - DH_get0_key(kex->dh, &pub_key, NULL); - DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); - hashlen = sizeof(hash); -- if ((r = kexgex_hash( -- kex->hash_alg, -- kex->client_version, -- kex->server_version, -- kex->peer, -- kex->my, -- empty, -- cmin, nbits, cmax, -- dh_p, dh_g, -- dh_client_pub, -- pub_key, -- sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), -- hash, &hashlen)) != 0) -+ r = kexgex_hash(kex->hash_alg, kex->client_version, kex->server_version, -+ kex->peer, kex->my, empty, kex->min, kex->nbits, kex->max, dh_p, dh_g, -+ gss->dh_client_pub, pub_key, sshbuf_ptr(shared_secret), -+ sshbuf_len(shared_secret), hash, &hashlen); -+ sshbuf_free(empty); -+ if (r != 0) - fatal("kexgex_hash failed: %s", ssh_err(r)); - -- gssbuf.value = hash; -- gssbuf.length = hashlen; -+ gss->buf.value = hash; -+ gss->buf.length = hashlen; - -- if (GSS_ERROR(mm_ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))) -+ if (GSS_ERROR(mm_ssh_gssapi_sign(gss, &gss->buf, &msg_tok))) - fatal("Couldn't get MIC"); - - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || -@@ -443,24 +436,24 @@ kexgssgex_server(struct ssh *ssh) - (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) - fatal("sshpkt failed: %s", ssh_err(r)); - -- if (send_tok.length != 0) { -+ if (send_tok->length != 0) { - if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ -- (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) -+ (r = sshpkt_put_string(ssh, send_tok->value, send_tok->length)) != 0) - fatal("sshpkt failed: %s", ssh_err(r)); - } else { - if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ - fatal("sshpkt failed: %s", ssh_err(r)); - } - if ((r = sshpkt_send(ssh)) != 0) -- fatal("sshpkt failed: %s", ssh_err(r)); -+ fatal("sshpkt_send failed: %s", ssh_err(r)); - -- gss_release_buffer(&min_status, &send_tok); -- gss_release_buffer(&min_status, &msg_tok); -+ gss_release_buffer(&gss->minor, send_tok); -+ gss_release_buffer(&gss->minor, &msg_tok); - - if (gss_kex_context == NULL) -- gss_kex_context = ctxt; -+ gss_kex_context = gss; - else -- ssh_gssapi_delete_ctx(&ctxt); -+ ssh_gssapi_delete_ctx(&kex->gss); - - /* Finally derive the keys and send them */ - if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) -@@ -470,13 +463,128 @@ kexgssgex_server(struct ssh *ssh) - * just exchanged. */ - if (options.gss_store_rekey) - ssh_gssapi_rekey_creds(); -+ -+ if (kex->gss != NULL) -+ BN_clear_free(gss->dh_client_pub); -+ - out: -- sshbuf_free(empty); - explicit_bzero(hash, sizeof(hash)); - DH_free(kex->dh); - kex->dh = NULL; -- BN_clear_free(dh_client_pub); - sshbuf_free(shared_secret); - return r; - } -+ -+static int -+input_kexgssgex_groupreq(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ struct kex *kex = ssh->kex; -+ const BIGNUM *dh_p, *dh_g; -+ int min = -1, max = -1, nbits = -1; -+ int cmin = -1, cmax = -1; /* client proposal */ -+ int r; -+ -+ /* 5. S generates an ephemeral key pair (do the allocations early) */ -+ -+ debug("SSH2_MSG_KEXGSS_GROUPREQ received"); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_GROUPREQ, NULL); -+ -+ /* store client proposal to provide valid signature */ -+ if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || -+ (r = sshpkt_get_u32(ssh, &nbits)) != 0 || -+ (r = sshpkt_get_u32(ssh, &cmax)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ kex->nbits = nbits; -+ kex->min = cmin; -+ kex->max = cmax; -+ min = MAX(DH_GRP_MIN, cmin); -+ max = MIN(DH_GRP_MAX, cmax); -+ nbits = MAXIMUM(DH_GRP_MIN, nbits); -+ nbits = MINIMUM(DH_GRP_MAX, nbits); -+ -+ if (max < min || nbits < min || max < nbits) -+ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", min, nbits, max); -+ -+ kex->dh = mm_choose_dh(min, nbits, max); -+ if (kex->dh == NULL) { -+ sshpkt_disconnect(ssh, "Protocol error: no matching group found"); -+ fatal("Protocol error: no matching group found"); -+ } -+ -+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ if ((r = ssh_packet_write_wait(ssh)) != 0) -+ fatal("ssh_packet_write_wait: %s", ssh_err(r)); -+ -+ /* Compute our exchange value in parallel with the client */ -+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) { -+ ssh_gssapi_delete_ctx(&kex->gss); -+ DH_free(kex->dh); -+ kex->dh = NULL; -+ return r; -+ } -+ -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, &input_kexgssgex_init); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_CONTINUE, &input_kexgssgex_continue); -+ debug("Wait SSH2_MSG_KEXGSS_INIT"); -+ return 0; -+} -+ -+static int -+input_kexgssgex_init(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; -+ OM_uint32 ret_flags = 0; -+ int r; -+ -+ debug("SSH2_MSG_KEXGSS_INIT received"); -+ ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); -+ -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || -+ (r = sshpkt_get_bignum2(ssh, &gss->dh_client_pub)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ -+ -+ kexgssgex_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); -+ if (gss->major & GSS_S_CONTINUE_NEEDED) -+ return 0; -+ -+ return kexgssgex_final(ssh, &send_tok, &ret_flags); -+} -+ -+static int -+input_kexgssgex_continue(int type, -+ u_int32_t seq, -+ struct ssh *ssh) -+{ -+ Gssctxt *gss = ssh->kex->gss; -+ gss_buffer_desc recv_tok, send_tok = GSS_C_EMPTY_BUFFER; -+ OM_uint32 ret_flags = 0; -+ int r; -+ -+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, &recv_tok)) != 0 || -+ (r = sshpkt_get_end(ssh)) != 0) -+ fatal("sshpkt failed: %s", ssh_err(r)); -+ -+ kexgssgex_accept_ctx(ssh, &recv_tok, &send_tok, &ret_flags); -+ if (gss->major & GSS_S_CONTINUE_NEEDED) -+ return 0; -+ -+ return kexgssgex_final(ssh, &send_tok, &ret_flags); -+} -+ - #endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --color -ruNp a/kex.h b/kex.h ---- a/kex.h 2024-05-16 15:49:43.986410812 +0200 -+++ b/kex.h 2024-06-18 12:19:48.580347469 +0200 -@@ -29,6 +29,10 @@ - #include "mac.h" - #include "crypto_api.h" - -+#ifdef GSSAPI -+# include "ssh-gss.h" /* Gssctxt */ -+#endif -+ - #ifdef WITH_OPENSSL - # include - # include -@@ -177,6 +181,7 @@ struct kex { - int hash_alg; - int ec_nid; - #ifdef GSSAPI -+ Gssctxt *gss; - int gss_deleg_creds; - int gss_trust_dns; - char *gss_host; -diff --color -ruNp a/ssh-gss.h b/ssh-gss.h ---- a/ssh-gss.h 2024-05-16 15:49:43.837407972 +0200 -+++ b/ssh-gss.h 2024-06-27 14:12:48.659866937 +0200 -@@ -88,6 +88,8 @@ extern char **k5users_allowed_cmds; - KEX_GSS_GRP14_SHA1_ID "," \ - KEX_GSS_GEX_SHA1_ID - -+#include "digest.h" /* SSH_DIGEST_MAX_LENGTH */ -+ - typedef struct { - char *filename; - char *envvar; -@@ -127,6 +129,16 @@ typedef struct { - gss_cred_id_t creds; /* server */ - gss_name_t client; /* server */ - gss_cred_id_t client_creds; /* both */ -+ struct sshbuf *shared_secret; /* both */ -+ struct sshbuf *server_pubkey; /* server */ -+ struct sshbuf *server_blob; /* client */ -+ struct sshbuf *server_host_key_blob; /* client */ -+ gss_buffer_desc msg_tok; /* client */ -+ gss_buffer_desc buf; /* both */ -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; /* both */ -+ size_t hashlen; /* both */ -+ int first; /* client */ -+ BIGNUM *dh_client_pub; /* server (gex) */ - } Gssctxt; - - extern ssh_gssapi_mech *supported_mechs[]; diff --git a/openssh.spec b/openssh.spec index a0c21c7..d0a4203 100644 --- a/openssh.spec +++ b/openssh.spec @@ -145,7 +145,7 @@ Patch711: openssh-7.8p1-UsePAM-warning.patch # Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures # upstream MR: # https://github.com/openssh-gsskex/openssh-gsskex/pull/21 -Patch800: openssh-8.0p1-gssapi-keyex.patch +Patch800: openssh-9.6p1-gssapi-keyex.patch #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html Patch801: openssh-6.6p1-force_krb.patch # add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843) @@ -156,8 +156,6 @@ Patch802: openssh-6.6p1-GSSAPIEnablek5users.patch Patch804: openssh-7.7p1-gssapi-new-unique.patch # Respect k5login_directory option in krk5.conf (#1328243) Patch805: openssh-7.2p2-k5login_directory.patch -# Rewriting OpenSSH GSS KEX to use new packet API -Patch806: openssh-9.6p1-gsskex-new-api.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 Patch901: openssh-6.6p1-kuserok.patch @@ -393,7 +391,6 @@ popd %patch -P 801 -p1 -b .force_krb %patch -P 804 -p1 -b .ccache_name %patch -P 805 -p1 -b .k5login -%patch -P 806 -p1 -b .gsskex-new-api # %patch -P 901 -p1 -b .kuserok %patch -P 906 -p1 -b .fromto-remote From ddef24ba7eb2c56098426b4a9fb0518b514b1181 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 9 Oct 2024 12:52:03 +0200 Subject: [PATCH 43/80] Rebasing to OpenSSH 9.9p1 --- .gitignore | 2 + openssh-6.6p1-allow-ip-opts.patch | 2 +- openssh-6.7p1-coverity.patch | 16 - openssh-7.6p1-audit.patch | 97 +- openssh-7.7p1-fips.patch | 63 +- openssh-8.0p1-crypto-policies.patch | 12 +- openssh-8.0p1-pkcs11-uri.patch | 44 +- openssh-8.7p1-nohostsha1proof.patch | 41 - openssh-9.0p1-evp-fips-ecdh.patch | 207 --- ....patch => openssh-9.0p1-evp-fips-kex.patch | 307 +++- openssh-9.3p1-merged-openssl-evp.patch | 1237 ----------------- openssh-9.6p1-gssapi-keyex.patch | 9 +- openssh.spec | 18 +- sources | 4 +- 14 files changed, 445 insertions(+), 1614 deletions(-) delete mode 100644 openssh-9.0p1-evp-fips-ecdh.patch rename openssh-9.0p1-evp-fips-dh.patch => openssh-9.0p1-evp-fips-kex.patch (50%) delete mode 100644 openssh-9.3p1-merged-openssl-evp.patch diff --git a/.gitignore b/.gitignore index f760b87..7004cb5 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,5 @@ pam_ssh_agent_auth-0.9.2.tar.bz2 /openssh-9.6p1.tar.gz.asc /openssh-9.8p1.tar.gz /openssh-9.8p1.tar.gz.asc +/openssh-9.9p1.tar.gz +/openssh-9.9p1.tar.gz.asc diff --git a/openssh-6.6p1-allow-ip-opts.patch b/openssh-6.6p1-allow-ip-opts.patch index d969b5c..995e04e 100644 --- a/openssh-6.6p1-allow-ip-opts.patch +++ b/openssh-6.6p1-allow-ip-opts.patch @@ -38,5 +38,5 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c + } + } while (i < option_size); } - return; #endif /* IP_OPTIONS */ + } diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index d98da28..ffe0c69 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -73,22 +73,6 @@ diff -up openssh-8.5p1/loginrec.c.coverity openssh-8.5p1/loginrec.c strncpy(ut->ut_host, li->hostname, MIN_SIZEOF(ut->ut_host, li->hostname)); # endif -@@ -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 */ -+ /* coverity[buffer_size_warning : FALSE] */ - strncpy(ut.ut_user, username, sizeof(ut.ut_user)); - strlcpy(ut.ut_line, "ssh:notty", sizeof(ut.ut_line)); - -@@ -1699,6 +1702,7 @@ record_failed_login(struct ssh *ssh, con - ut.ut_pid = getpid(); - - /* strncpy because we don't necessarily want nul termination */ -+ /* coverity[buffer_size_warning : FALSE] */ - strncpy(ut.ut_host, hostname, sizeof(ut.ut_host)); - - if (ssh_packet_connection_is_on_socket(ssh) && 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 diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index c884292..2c7ddc5 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -1086,7 +1086,7 @@ 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 \ + kexsntrup761x25519.o kexmlkem768x25519.o sntrup761.o kexgen.o \ kexgssc.o \ sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ - sshbuf-io.o @@ -2056,7 +2056,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c #include "ssh-sandbox.h" #include "auth-options.h" #include "version.h" -@@ -260,8 +261,8 @@ struct sshbuf *loginmsg; +@@ -260,8 +261,44 @@ struct sshbuf *loginmsg; struct sshbuf *loginmsg; /* Prototypes for various functions defined later in this file. */ @@ -2064,6 +2064,42 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c -void demote_sensitive_data(void); +void destroy_sensitive_data(struct ssh *); +void demote_sensitive_data(struct ssh *); ++ ++static int ++sshkey_is_private(const struct sshkey *k) ++{ ++ switch (k->type) { ++#ifdef WITH_OPENSSL ++ case KEY_RSA_CERT: ++ case KEY_RSA: { ++ const BIGNUM *d; ++ const RSA *rsa = EVP_PKEY_get0_RSA(k->pkey); ++ RSA_get0_key(rsa, NULL, NULL, &d); ++ return d != NULL; ++ } ++ case KEY_DSA_CERT: ++ case KEY_DSA: { ++ const BIGNUM *priv_key; ++ DSA_get0_key(k->dsa, NULL, &priv_key); ++ return priv_key != NULL; ++ } ++#ifdef OPENSSL_HAS_ECC ++ case KEY_ECDSA_CERT: ++ case KEY_ECDSA: { ++ const EC_KEY * ecdsa = EVP_PKEY_get0_EC_KEY(k->pkey); ++ return EC_KEY_get0_private_key(ecdsa) != NULL; ++ } ++#endif /* OPENSSL_HAS_ECC */ ++#endif /* WITH_OPENSSL */ ++ case KEY_ED25519_CERT: ++ case KEY_ED25519: ++ return (k->ed25519_pk != NULL); ++ default: ++ /* fatal("key_is_private: bad key type %d", k->type); */ ++ return 0; ++ } ++} ++ static void do_ssh2_kex(struct ssh *); /* @@ -2222,7 +2258,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c if (the_active_state != NULL && the_authctxt != NULL) { @@ -2525,7 +2593,9 @@ cleanup_exit(int i) - _exit(EXIT_AUTH_ATTEMPTED); + } #ifdef SSH_AUDIT_EVENTS /* done after do_cleanup so it can cancel the PAM auth 'thread' */ - if (the_active_state != NULL && mm_is_monitor()) @@ -2231,57 +2267,4 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c + mm_is_monitor()) audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif - _exit(i); -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 -+sshkey_is_private(const struct sshkey *k) -+{ -+ switch (k->type) { -+#ifdef WITH_OPENSSL -+ case KEY_RSA_CERT: -+ case KEY_RSA: { -+ const BIGNUM *d; -+ RSA_get0_key(k->rsa, NULL, NULL, &d); -+ return d != NULL; -+ } -+ case KEY_DSA_CERT: -+ case KEY_DSA: { -+ const BIGNUM *priv_key; -+ DSA_get0_key(k->dsa, NULL, &priv_key); -+ return priv_key != NULL; -+ } -+#ifdef OPENSSL_HAS_ECC -+ case KEY_ECDSA_CERT: -+ case KEY_ECDSA: -+ return EC_KEY_get0_private_key(k->ecdsa) != NULL; -+#endif /* OPENSSL_HAS_ECC */ -+#endif /* WITH_OPENSSL */ -+ case KEY_ED25519_CERT: -+ case KEY_ED25519: -+ return (k->ed25519_pk != NULL); -+ default: -+ /* fatal("key_is_private: bad key type %d", k->type); */ -+ return 0; -+ } -+} -+ -+int - sshkey_is_cert(const struct sshkey *k) - { - 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 *); -+int sshkey_is_private(const struct sshkey *); - int sshkey_is_cert(const struct sshkey *); - int sshkey_is_sk(const struct sshkey *); - int sshkey_type_is_cert(int); + /* Override default fatal exit value when auth was attempted */ diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index 6a14cb3..a53f9f6 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -427,9 +427,9 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c --- openssh-8.6p1/sshkey.c.fips 2021-05-06 12:08:36.493926838 +0200 +++ openssh-8.6p1/sshkey.c 2021-05-06 12:08:36.502926908 +0200 @@ -36,6 +36,7 @@ + #include + #include #include - #include - #include +#include #endif @@ -544,13 +544,13 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c - name = _PATH_SSH_CLIENT_ID_ED25519; + name = FIPS_mode() ? _PATH_SSH_CLIENT_ID_RSA : _PATH_SSH_CLIENT_ID_ED25519; else { - switch (sshkey_type_from_name(key_type_name)) { + switch (sshkey_type_from_shortname(key_type_name)) { #ifdef WITH_DSA @@ -1098,9 +1104,17 @@ do_gen_all_hostkeys(struct passwd *pw) first = 1; printf("%s: generating new host keys: ", __progname); } -+ type = sshkey_type_from_name(key_types[i].key_type); ++ type = sshkey_type_from_shortname(key_types[i].key_type); + + /* Skip the keys that are not supported in FIPS mode */ + if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) { @@ -561,7 +561,7 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c + printf("%s ", key_types[i].key_type_display); fflush(stdout); -- type = sshkey_type_from_name(key_types[i].key_type); +- type = sshkey_type_from_shortname(key_types[i].key_type); if ((fd = mkstemp(prv_tmp)) == -1) { error("Could not save your private key in %s: %s", prv_tmp, strerror(errno)); @@ -572,31 +572,31 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c - key_type_name = DEFAULT_KEY_TYPE_NAME; + key_type_name = FIPS_mode() ? FIPS_DEFAULT_KEY_TYPE_NAME : DEFAULT_KEY_TYPE_NAME; - type = sshkey_type_from_name(key_type_name); + type = sshkey_type_from_shortname(key_type_name); type_bits_valid(type, key_type_name, &bits); diff -up openssh-9.3p1/ssh-rsa.c.evpgenrsa openssh-9.3p1/ssh-rsa.c --- openssh-9.3p1/ssh-rsa.c.evpgenrsa 2022-06-30 15:14:58.200518353 +0200 +++ openssh-9.3p1/ssh-rsa.c 2022-06-30 15:24:31.499641196 +0200 @@ -33,6 +33,7 @@ + + #include #include - #include - #include +#include #include #include @@ -1705,6 +1707,8 @@ ssh_rsa_generate(u_int bits, RSA goto out; - - if (EVP_PKEY_keygen(ctx, &res) <= 0) { + } + if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) { + if (FIPS_mode()) + logit_f("the key length might be unsupported by FIPS mode approved key generation method"); ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } -diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c ---- openssh-8.7p1/kexgen.c.fips3 2022-07-11 16:11:21.973519913 +0200 -+++ openssh-8.7p1/kexgen.c 2022-07-11 16:25:31.172187365 +0200 +diff -up openssh-9.9p1/kexgen.c.xxx openssh-9.9p1/kexgen.c +--- openssh-9.9p1/kexgen.c.xxx 2024-10-09 10:35:56.285946080 +0200 ++++ openssh-9.9p1/kexgen.c 2024-10-09 10:41:52.792597194 +0200 @@ -31,6 +31,7 @@ #include #include @@ -605,7 +605,7 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c #include "sshkey.h" #include "kex.h" -@@ -115,10 +116,20 @@ kex_gen_client(struct ssh *ssh) +@@ -115,13 +116,28 @@ kex_gen_client(struct ssh *ssh) break; #endif case KEX_C25519_SHA256: @@ -624,11 +624,20 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c + r = SSH_ERR_INVALID_ARGUMENT; + } else { + r = kex_kem_sntrup761x25519_keypair(kex); ++ } + break; + case KEX_KEM_MLKEM768X25519_SHA256: +- r = kex_kem_mlkem768x25519_keypair(kex); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768x25519_keypair(kex); + } break; default: r = SSH_ERR_INVALID_ARGUMENT; -@@ -186,11 +197,21 @@ input_kex_gen_reply(int type, u_int32_t +@@ -189,15 +205,30 @@ input_kex_gen_reply(int type, u_int32_t break; #endif case KEX_C25519_SHA256: @@ -649,11 +658,22 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c + } else { + r = kex_kem_sntrup761x25519_dec(kex, server_blob, + &shared_secret); ++ } + break; + case KEX_KEM_MLKEM768X25519_SHA256: +- r = kex_kem_mlkem768x25519_dec(kex, server_blob, +- &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768x25519_dec(kex, server_blob, ++ &shared_secret); + } break; default: r = SSH_ERR_INVALID_ARGUMENT; -@@ -285,12 +306,22 @@ input_kex_gen_init(int type, u_int32_t s +@@ -312,16 +343,31 @@ input_kex_gen_init(int type, u_int32_t s break; #endif case KEX_C25519_SHA256: @@ -676,6 +696,17 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c + } else { + r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, + &server_pubkey, &shared_secret); ++ } + break; + case KEX_KEM_MLKEM768X25519_SHA256: +- r = kex_kem_mlkem768x25519_enc(kex, client_pubkey, +- &server_pubkey, &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768x25519_enc(kex, client_pubkey, ++ &server_pubkey, &shared_secret); + } break; default: diff --git a/openssh-8.0p1-crypto-policies.patch b/openssh-8.0p1-crypto-policies.patch index fd1e59d..a666c5c 100644 --- a/openssh-8.0p1-crypto-policies.patch +++ b/openssh-8.0p1-crypto-policies.patch @@ -166,8 +166,8 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x +.Pp Specifies the permitted KEX (Key Exchange) algorithms that will be used and their preference order. - The selected algorithm will the the first algorithm in this list that -@@ -1338,28 +1343,17 @@ Multiple algorithms must be comma-separa + The selected algorithm will be the first algorithm in this list that +@@ -1338,29 +1343,17 @@ Multiple algorithms must be comma-separa .Pp If the specified list begins with a .Sq + @@ -187,7 +187,8 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x -.Pp -The default is: -.Bd -literal -offset indent --sntrup761x25519-sha512@openssh.com, +-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, +-mlkem768x25519-sha256, -curve25519-sha256,curve25519-sha256@libssh.org, -ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, -diffie-hellman-group-exchange-sha256, @@ -517,13 +518,14 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Pp The supported algorithms are: .Pp -@@ -1075,16 +1080,6 @@ ecdh-sha2-nistp521 +@@ -1075,17 +1080,6 @@ ecdh-sha2-nistp521 sntrup761x25519-sha512@openssh.com .El .Pp -The default is: -.Bd -literal -offset indent --sntrup761x25519-sha512@openssh.com, +-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, +-mlkem768x25519-sha256, -curve25519-sha256,curve25519-sha256@libssh.org, -ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, -diffie-hellman-group-exchange-sha256, diff --git a/openssh-8.0p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch index 9931d92..bdc4722 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -1353,9 +1353,17 @@ diff -up openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-c 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-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c ---- openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 -+++ openssh-9.6p1/ssh-pkcs11.c 2024-01-12 14:28:09.170975480 +0100 +diff -up openssh-9.9p1/ssh-pkcs11.c.xxx openssh-9.9p1/ssh-pkcs11.c +--- openssh-9.9p1/ssh-pkcs11.c.xxx 2024-10-09 11:56:35.890126144 +0200 ++++ openssh-9.9p1/ssh-pkcs11.c 2024-10-09 11:56:48.528459585 +0200 +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #define CRYPTOKI_COMPAT + #include "pkcs11.h" @@ -55,8 +55,8 @@ struct pkcs11_slotinfo { int logged_in; }; @@ -1556,7 +1564,7 @@ diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c } static RSA_METHOD *rsa_method; -@@ -195,6 +286,56 @@ static EC_KEY_METHOD *ec_key_method; +@@ -195,6 +286,60 @@ static EC_KEY_METHOD *ec_key_method; static int ec_key_idx = 0; #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ @@ -1573,13 +1581,17 @@ diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c + + /* sanity - is it a RSA key with associated app_data? */ + switch (key->type) { -+ case KEY_RSA: -+ k11 = RSA_get_ex_data(key->rsa, rsa_idx); ++ case KEY_RSA: { ++ const RSA *rsa = EVP_PKEY_get0_RSA(key->pkey); ++ k11 = RSA_get_ex_data(rsa, rsa_idx); + break; ++ } +#ifdef HAVE_EC_KEY_METHOD_NEW -+ case KEY_ECDSA: -+ k11 = EC_KEY_get_ex_data(key->ecdsa, ec_key_idx); ++ case KEY_ECDSA: { ++ const EC_KEY * ecdsa = EVP_PKEY_get0_EC_KEY(key->pkey); ++ k11 = EC_KEY_get_ex_data(ecdsa, ec_key_idx); + break; ++ } +#endif + default: + error("Unknown key type %d", key->type); @@ -1733,9 +1745,9 @@ diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c + k11->label[label_attrib->ulValueLen] = 0; + } + - RSA_set_method(rsa, rsa_method); - RSA_set_ex_data(rsa, rsa_idx, k11); - return (0); + if (RSA_set_method(rsa, rsa_method) != 1) + fatal_f("RSA_set_method failed"); + if (RSA_set_ex_data(rsa, rsa_idx, k11) != 1) @@ -532,8 +683,8 @@ ecdsa_do_sign(const unsigned char *dgst, return (NULL); } @@ -1766,9 +1778,9 @@ diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c + k11->label[label_attrib->ulValueLen] = 0; + } + - EC_KEY_set_method(ec, ec_key_method); - EC_KEY_set_ex_data(ec, ec_key_idx, k11); - + if (EC_KEY_set_method(ec, ec_key_method) != 1) + fatal_f("EC_KEY_set_method failed"); + if (EC_KEY_set_ex_data(ec, ec_key_idx, k11) != 1) @@ -622,7 +779,8 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider } #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ @@ -1895,7 +1907,7 @@ diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c key = sshkey_new(KEY_UNSPEC); @@ -810,7 +970,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ - ec = NULL; /* now owned by key */ + key->flags |= SSHKEY_FLAG_EXT; fail: - for (i = 0; i < 3; i++) @@ -1979,7 +1991,7 @@ diff -up openssh-9.6p1/ssh-pkcs11.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11.c key = sshkey_new(KEY_UNSPEC); @@ -905,7 +1067,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr - rsa = NULL; /* now owned by key */ + key->flags |= SSHKEY_FLAG_EXT; fail: - for (i = 0; i < 3; i++) diff --git a/openssh-8.7p1-nohostsha1proof.patch b/openssh-8.7p1-nohostsha1proof.patch index abc6aa4..dae0932 100644 --- a/openssh-8.7p1-nohostsha1proof.patch +++ b/openssh-8.7p1-nohostsha1proof.patch @@ -94,47 +94,6 @@ diff -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c is_proof ? "hostkey proof" : "KEX", siglen); sshbuf_reset(m); -diff -up openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck openssh-8.7p1/regress/cert-userkey.sh ---- openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck 2023-01-25 14:26:52.885963113 +0100 -+++ openssh-8.7p1/regress/cert-userkey.sh 2023-01-25 14:27:25.757219800 +0100 -@@ -7,7 +7,8 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us - cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak - cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak - --PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` -+#ssh-dss keys are incompatible with DEFAULT crypto policy -+PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss' | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` - EXTRA_TYPES="" - rsa="" - -diff -up openssh-8.7p1/regress/Makefile.sshrsacheck openssh-8.7p1/regress/Makefile ---- openssh-8.7p1/regress/Makefile.sshrsacheck 2023-01-20 13:07:54.169676051 +0100 -+++ openssh-8.7p1/regress/Makefile 2023-01-20 13:07:54.290677074 +0100 -@@ -2,7 +2,8 @@ - - tests: prep file-tests t-exec unit - --REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 -+#ssh-dss tests will not pass on DEFAULT crypto-policy because of SHA1, skipping -+REGRESS_TARGETS= t1 t2 t3 t4 t5 t7 t8 t9 t10 t11 t12 - - # File based tests - file-tests: $(REGRESS_TARGETS) -diff -up openssh-8.7p1/regress/test-exec.sh.sshrsacheck openssh-8.7p1/regress/test-exec.sh ---- openssh-8.7p1/regress/test-exec.sh.sshrsacheck 2023-01-25 14:24:54.778040819 +0100 -+++ openssh-8.7p1/regress/test-exec.sh 2023-01-25 14:26:39.500858590 +0100 -@@ -581,8 +581,9 @@ maybe_filter_sk() { - fi - } - --SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk` --SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk` -+#ssh-dss keys are incompatible with DEFAULT crypto policy -+SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'` -+SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'` - - for t in ${SSH_KEYTYPES}; do - # generate user key diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p1/regress/unittests/kex/test_kex.c --- openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck 2023-01-26 13:34:52.645743677 +0100 +++ openssh-8.7p1/regress/unittests/kex/test_kex.c 2023-01-26 13:36:56.220745823 +0100 diff --git a/openssh-9.0p1-evp-fips-ecdh.patch b/openssh-9.0p1-evp-fips-ecdh.patch deleted file mode 100644 index 0313c6f..0000000 --- a/openssh-9.0p1-evp-fips-ecdh.patch +++ /dev/null @@ -1,207 +0,0 @@ -diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../openssh-8.7p1/kexecdh.c ./kexecdh.c ---- ../openssh-8.7p1/kexecdh.c 2021-08-20 06:03:49.000000000 +0200 -+++ ./kexecdh.c 2023-04-13 14:30:14.882449593 +0200 -@@ -35,17 +35,57 @@ - #include - - #include -+#include -+#include -+#include -+#include - - #include "sshkey.h" - #include "kex.h" - #include "sshbuf.h" - #include "digest.h" - #include "ssherr.h" -+#include "log.h" - - static int - kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key, - const EC_GROUP *, struct sshbuf **); - -+static EC_KEY * -+generate_ec_keys(int ec_nid) -+{ -+ EC_KEY *client_key = NULL; -+ EVP_PKEY *pkey = NULL; -+ EVP_PKEY_CTX *ctx = NULL; -+ OSSL_PARAM_BLD *param_bld = NULL; -+ OSSL_PARAM *params = NULL; -+ const char *group_name; -+ -+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL || -+ (param_bld = OSSL_PARAM_BLD_new()) == NULL) -+ goto out; -+ if ((group_name = OSSL_EC_curve_nid2name(ec_nid)) == NULL || -+ OSSL_PARAM_BLD_push_utf8_string(param_bld, -+ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 || -+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { -+ error_f("Could not create OSSL_PARAM"); -+ goto out; -+ } -+ if (EVP_PKEY_keygen_init(ctx) != 1 || -+ EVP_PKEY_CTX_set_params(ctx, params) != 1 || -+ EVP_PKEY_generate(ctx, &pkey) != 1 || -+ (client_key = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) { -+ error_f("Could not generate ec keys"); -+ goto out; -+ } -+out: -+ EVP_PKEY_free(pkey); -+ EVP_PKEY_CTX_free(ctx); -+ OSSL_PARAM_BLD_free(param_bld); -+ OSSL_PARAM_free(params); -+ return client_key; -+} -+ - int - kex_ecdh_keypair(struct kex *kex) - { -@@ -55,11 +95,7 @@ - struct sshbuf *buf = NULL; - int r; - -- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { -- r = SSH_ERR_ALLOC_FAIL; -- goto out; -- } -- if (EC_KEY_generate_key(client_key) != 1) { -+ if ((client_key = generate_ec_keys(kex->ec_nid)) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -@@ -101,11 +137,7 @@ - *server_blobp = NULL; - *shared_secretp = NULL; - -- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { -- r = SSH_ERR_ALLOC_FAIL; -- goto out; -- } -- if (EC_KEY_generate_key(server_key) != 1) { -+ if ((server_key = generate_ec_keys(kex->ec_nid)) == NULL) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -@@ -140,11 +172,21 @@ - { - struct sshbuf *buf = NULL; - BIGNUM *shared_secret = NULL; -- EC_POINT *dh_pub = NULL; -- u_char *kbuf = NULL; -- size_t klen = 0; -+ EVP_PKEY_CTX *ctx = NULL; -+ EVP_PKEY *pkey = NULL, *dh_pkey = NULL; -+ OSSL_PARAM_BLD *param_bld = NULL; -+ OSSL_PARAM *params = NULL; -+ u_char *kbuf = NULL, *pub = NULL; -+ size_t klen = 0, publen; -+ const char *group_name; - int r; - -+ /* import EC_KEY to EVP_PKEY */ -+ if ((r = ssh_create_evp_ec(key, kex->ec_nid, &pkey)) != 0) { -+ error_f("Could not create EVP_PKEY"); -+ goto out; -+ } -+ - *shared_secretp = NULL; - - if ((buf = sshbuf_new()) == NULL) { -@@ -153,45 +195,82 @@ - } - if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0) - goto out; -- if ((dh_pub = EC_POINT_new(group)) == NULL) { -+ -+ /* the public key is in the buffer in octet string UNCOMPRESSED -+ * format. See sshbuf_put_ec */ -+ if ((r = sshbuf_get_string(buf, &pub, &publen)) != 0) -+ goto out; -+ sshbuf_reset(buf); -+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || -+ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) { -+ if ((group_name = OSSL_EC_curve_nid2name(kex->ec_nid)) == NULL) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ if (OSSL_PARAM_BLD_push_octet_string(param_bld, -+ OSSL_PKEY_PARAM_PUB_KEY, pub, publen) != 1 || -+ OSSL_PARAM_BLD_push_utf8_string(param_bld, -+ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 || -+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { -+ error_f("Failed to set params for dh_pkey"); -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ if (EVP_PKEY_fromdata_init(ctx) != 1 || -+ EVP_PKEY_fromdata(ctx, &dh_pkey, -+ EVP_PKEY_PUBLIC_KEY, params) != 1 || -+ EVP_PKEY_public_check(ctx) != 1) { -+ error_f("Peer public key import failed"); -+ r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- sshbuf_reset(buf); - - #ifdef DEBUG_KEXECDH - fputs("public key:\n", stderr); -- sshkey_dump_ec_point(group, dh_pub); -+ EVP_PKEY_print_public_fp(stderr, dh_pkey, 0, NULL); - #endif -- if (sshkey_ec_validate_public(group, dh_pub) != 0) { -- r = SSH_ERR_MESSAGE_INCOMPLETE; -+ EVP_PKEY_CTX_free(ctx); -+ ctx = NULL; -+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || -+ EVP_PKEY_derive_init(ctx) != 1 || -+ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 || -+ EVP_PKEY_derive(ctx, NULL, &klen) != 1) { -+ error_f("Failed to get derive information"); -+ r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- klen = (EC_GROUP_get_degree(group) + 7) / 8; -- if ((kbuf = malloc(klen)) == NULL || -- (shared_secret = BN_new()) == NULL) { -+ if ((kbuf = malloc(klen)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen || -- BN_bin2bn(kbuf, klen, shared_secret) == NULL) { -+ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - #ifdef DEBUG_KEXECDH - dump_digest("shared secret", kbuf, klen); - #endif -+ if ((shared_secret = BN_new()) == NULL || -+ (BN_bin2bn(kbuf, klen, shared_secret) == NULL)) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } - if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0) - goto out; - *shared_secretp = buf; - buf = NULL; - out: -- EC_POINT_clear_free(dh_pub); -+ EVP_PKEY_CTX_free(ctx); -+ EVP_PKEY_free(pkey); -+ EVP_PKEY_free(dh_pkey); -+ OSSL_PARAM_BLD_free(param_bld); -+ OSSL_PARAM_free(params); - BN_clear_free(shared_secret); - freezero(kbuf, klen); -+ freezero(pub, publen); - sshbuf_free(buf); - return r; - } diff --git a/openssh-9.0p1-evp-fips-dh.patch b/openssh-9.0p1-evp-fips-kex.patch similarity index 50% rename from openssh-9.0p1-evp-fips-dh.patch rename to openssh-9.0p1-evp-fips-kex.patch index 8c70197..36fd1cf 100644 --- a/openssh-9.0p1-evp-fips-dh.patch +++ b/openssh-9.0p1-evp-fips-kex.patch @@ -128,7 +128,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.c openssh-9.0p1-patched/kex.c --- openssh-9.0p1/kex.c 2023-05-25 09:24:28.731868327 +0200 +++ openssh-9.0p1-patched/kex.c 2023-05-25 09:23:44.841379532 +0200 -@@ -1623,3 +1623,47 @@ +@@ -1623,3 +1623,142 @@ return r; } @@ -137,6 +137,101 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + * Creates an EVP_PKEY from the given parameters and keys. + * The private key can be omitted. + */ ++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; ++} ++ ++int ++kex_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; ++} ++ +int +kex_create_evp_dh(EVP_PKEY **pkey, const BIGNUM *p, const BIGNUM *q, + const BIGNUM *g, const BIGNUM *pub, const BIGNUM *priv) @@ -281,12 +376,220 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x # ifdef OPENSSL_HAS_ECC # include # else /* OPENSSL_HAS_ECC */ -@@ -283,6 +286,8 @@ +@@ -283,6 +286,9@@ const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); +int kex_create_evp_dh(EVP_PKEY **, const BIGNUM *, const BIGNUM *, + const BIGNUM *, const BIGNUM *, const BIGNUM *); ++int kex_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey); #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(const char *, const u_char *, int); +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../openssh-8.7p1/kexecdh.c ./kexecdh.c +--- ../openssh-8.7p1/kexecdh.c 2021-08-20 06:03:49.000000000 +0200 ++++ ./kexecdh.c 2023-04-13 14:30:14.882449593 +0200 +@@ -35,17 +35,57 @@ + #include + + #include ++#include ++#include ++#include ++#include + + #include "sshkey.h" + #include "kex.h" + #include "sshbuf.h" + #include "digest.h" + #include "ssherr.h" ++#include "log.h" + + static int + kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key, + const EC_GROUP *, struct sshbuf **); + ++static EC_KEY * ++generate_ec_keys(int ec_nid) ++{ ++ EC_KEY *client_key = NULL; ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ const char *group_name; ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) ++ goto out; ++ if ((group_name = OSSL_EC_curve_nid2name(ec_nid)) == NULL || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ error_f("Could not create OSSL_PARAM"); ++ goto out; ++ } ++ if (EVP_PKEY_keygen_init(ctx) != 1 || ++ EVP_PKEY_CTX_set_params(ctx, params) != 1 || ++ EVP_PKEY_generate(ctx, &pkey) != 1 || ++ (client_key = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) { ++ error_f("Could not generate ec keys"); ++ goto out; ++ } ++out: ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(ctx); ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); ++ return client_key; ++} ++ + int + kex_ecdh_keypair(struct kex *kex) + { +@@ -55,11 +95,7 @@ + struct sshbuf *buf = NULL; + int r; + +- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if (EC_KEY_generate_key(client_key) != 1) { ++ if ((client_key = generate_ec_keys(kex->ec_nid)) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +@@ -101,11 +137,7 @@ + *server_blobp = NULL; + *shared_secretp = NULL; + +- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { +- r = SSH_ERR_ALLOC_FAIL; +- goto out; +- } +- if (EC_KEY_generate_key(server_key) != 1) { ++ if ((server_key = generate_ec_keys(kex->ec_nid)) == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +@@ -140,11 +172,21 @@ + { + struct sshbuf *buf = NULL; + BIGNUM *shared_secret = NULL; +- EC_POINT *dh_pub = NULL; +- u_char *kbuf = NULL; +- size_t klen = 0; ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *pkey = NULL, *dh_pkey = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ u_char *kbuf = NULL, *pub = NULL; ++ size_t klen = 0, publen; ++ const char *group_name; + int r; + ++ /* import EC_KEY to EVP_PKEY */ ++ if ((r = kex_create_evp_ec(key, kex->ec_nid, &pkey)) != 0) { ++ error_f("Could not create EVP_PKEY"); ++ goto out; ++ } ++ + *shared_secretp = NULL; + + if ((buf = sshbuf_new()) == NULL) { +@@ -153,45 +195,82 @@ + } + if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0) + goto out; +- if ((dh_pub = EC_POINT_new(group)) == NULL) { ++ ++ /* the public key is in the buffer in octet string UNCOMPRESSED ++ * format. See sshbuf_put_ec */ ++ if ((r = sshbuf_get_string(buf, &pub, &publen)) != 0) ++ goto out; ++ sshbuf_reset(buf); ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) { ++ if ((group_name = OSSL_EC_curve_nid2name(kex->ec_nid)) == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (OSSL_PARAM_BLD_push_octet_string(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, pub, publen) != 1 || ++ OSSL_PARAM_BLD_push_utf8_string(param_bld, ++ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ error_f("Failed to set params for dh_pkey"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1 || ++ EVP_PKEY_fromdata(ctx, &dh_pkey, ++ EVP_PKEY_PUBLIC_KEY, params) != 1 || ++ EVP_PKEY_public_check(ctx) != 1) { ++ error_f("Peer public key import failed"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- sshbuf_reset(buf); + + #ifdef DEBUG_KEXECDH + fputs("public key:\n", stderr); +- sshkey_dump_ec_point(group, dh_pub); ++ EVP_PKEY_print_public_fp(stderr, dh_pkey, 0, NULL); + #endif +- if (sshkey_ec_validate_public(group, dh_pub) != 0) { +- r = SSH_ERR_MESSAGE_INCOMPLETE; ++ EVP_PKEY_CTX_free(ctx); ++ ctx = NULL; ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ EVP_PKEY_derive_init(ctx) != 1 || ++ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 || ++ EVP_PKEY_derive(ctx, NULL, &klen) != 1) { ++ error_f("Failed to get derive information"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- klen = (EC_GROUP_get_degree(group) + 7) / 8; +- if ((kbuf = malloc(klen)) == NULL || +- (shared_secret = BN_new()) == NULL) { ++ if ((kbuf = malloc(klen)) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen || +- BN_bin2bn(kbuf, klen, shared_secret) == NULL) { ++ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + #ifdef DEBUG_KEXECDH + dump_digest("shared secret", kbuf, klen); + #endif ++ if ((shared_secret = BN_new()) == NULL || ++ (BN_bin2bn(kbuf, klen, shared_secret) == NULL)) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } + if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0) + goto out; + *shared_secretp = buf; + buf = NULL; + out: +- EC_POINT_clear_free(dh_pub); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_free(dh_pkey); ++ OSSL_PARAM_BLD_free(param_bld); ++ OSSL_PARAM_free(params); + BN_clear_free(shared_secret); + freezero(kbuf, klen); ++ freezero(pub, publen); + sshbuf_free(buf); + return r; + } diff --git a/openssh-9.3p1-merged-openssl-evp.patch b/openssh-9.3p1-merged-openssl-evp.patch deleted file mode 100644 index 6a30485..0000000 --- a/openssh-9.3p1-merged-openssl-evp.patch +++ /dev/null @@ -1,1237 +0,0 @@ -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 }, - }; - -+const EVP_MD * -+ssh_digest_to_md(int digest_type) -+{ -+ switch (digest_type) { -+ case SSH_DIGEST_SHA1: -+ return EVP_sha1(); -+ case SSH_DIGEST_SHA256: -+ return EVP_sha256(); -+ case SSH_DIGEST_SHA384: -+ return EVP_sha384(); -+ case SSH_DIGEST_SHA512: -+ return EVP_sha512(); -+ } -+ return NULL; -+} -+ - static const struct ssh_digest * - ssh_digest_by_alg(int alg) - { -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 - - #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; - const BIGNUM *sig_r, *sig_s; -- u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; -- size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); -+ u_char sigblob[SIGBLOB_LEN]; -+ size_t rlen, slen; -+ int len; - struct sshbuf *b = NULL; -+ u_char *sigb = NULL; -+ const u_char *psig = NULL; - int ret = SSH_ERR_INVALID_ARGUMENT; - - if (lenp != NULL) -@@ -276,17 +282,23 @@ - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA) - return SSH_ERR_INVALID_ARGUMENT; -- if (dlen == 0) -- return SSH_ERR_INTERNAL_ERROR; - -- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, -- digest, sizeof(digest))) != 0) -+ 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); -+ if (ret < 0) { - goto out; -+ } - -- if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { -+ psig = sigb; -+ if ((sig = d2i_DSA_SIG(NULL, &psig, len)) == NULL) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -+ free(sigb); -+ sigb = NULL; - - DSA_SIG_get0(sig, &sig_r, &sig_s); - rlen = BN_num_bytes(sig_r); -@@ -319,7 +331,7 @@ - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - DSA_SIG_free(sig); - sshbuf_free(b); - return ret; -@@ -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 *dsig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; -- u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; -- size_t len, hlen = ssh_digest_bytes(SSH_DIGEST_SHA1); -+ u_char *sigblob = NULL; -+ size_t len, slen; - int ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; - char *ktype = NULL; -+ u_char *sigb = NULL, *psig = NULL; - - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; -- if (hlen == 0) -- return SSH_ERR_INTERNAL_ERROR; - - /* fetch signature */ - 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, dlen, -- digest, sizeof(digest))) != 0) -+ if ((slen = i2d_DSA_SIG(dsig, NULL)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; -- -- switch (DSA_do_verify(digest, hlen, dsig, key->dsa)) { -- case 1: -- ret = 0; -- break; -- case 0: -- ret = SSH_ERR_SIGNATURE_INVALID; -+ } -+ if ((sigb = malloc(slen)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; -- default: -+ } -+ psig = sigb; -+ if ((slen = i2d_DSA_SIG(dsig, &psig)) == 0) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - -+ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0) -+ goto out; -+ 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(dsig); - BN_clear_free(sig_r); - BN_clear_free(sig_s); -@@ -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 - -@@ -44,6 +44,9 @@ - #include "digest.h" - #define SSHKEY_INTERNAL - #include "sshkey.h" -+#ifdef ENABLE_PKCS11 -+#include "ssh-pkcs11.h" -+#endif - - #include "openbsd-compat/openssl-compat.h" - -@@ -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 *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, hlen; -+ int len; - struct sshbuf *b = NULL, *bb = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; - -@@ -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 || -- (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, dlen, -- digest, sizeof(digest))) != 0) -+ -+#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, -+ dlen); -+ EVP_PKEY_free(pkey); -+ if (ret < 0) { - goto out; -+ } - -- if ((esig = ECDSA_do_sign(digest, hlen, key->ecdsa)) == NULL) { -+ psig = sigb; -+ if (d2i_ECDSA_SIG(&esig, &psig, len) == NULL) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- - if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; -@@ -280,7 +309,7 @@ - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - sshbuf_free(b); - sshbuf_free(bb); - 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 *esig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; -- int hash_alg; -- u_char digest[SSH_DIGEST_MAX_LENGTH]; -- size_t hlen; -+ int hash_alg, len; - int ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL, *sigbuf = NULL; - char *ktype = NULL; -+ unsigned char *sigb = NULL, *psig = NULL; - - if (key == NULL || key->ecdsa == NULL || - sshkey_type_plain(key->type) != KEY_ECDSA || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; - -- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || -- (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 */ -@@ -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(esig, NULL)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- if ((ret = ssh_digest_memory(hash_alg, data, dlen, -- digest, sizeof(digest))) != 0) -- goto out; -- -- switch (ECDSA_do_verify(digest, hlen, esig, key->ecdsa)) { -- case 1: -- ret = 0; -- break; -- case 0: -- ret = SSH_ERR_SIGNATURE_INVALID; -+ if ((sigb = malloc(len)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; -- default: -+ } -+ psig = sigb; -+ if ((len = i2d_ECDSA_SIG(esig, &psig)) == 0) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - -+ 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(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" -@@ -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 -@@ -266,6 +266,10 @@ - const char *sshkey_ssh_name_plain(const struct sshkey *); - int sshkey_names_valid2(const char *, int, 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 --git a/ssh-pkcs11.c b/ssh-pkcs11.c ---- a/ssh-pkcs11.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/ssh-pkcs11.c (date 1703110934679) -@@ -620,8 +620,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. Note, that this does NOT guarantee the buffer - * will be null terminated if there are no trailing spaces! */ - static char * -diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c ---- a/ssh-pkcs11-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/ssh-pkcs11-client.c (date 1703110830967) -@@ -402,8 +402,36 @@ - if (helper->nrsa == 0 && helper->nec == 0) - helper_terminate(helper); - } -+ -+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 /* defined(OPENSSL_HAS_ECC) && defined(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 helper *helper, struct sshkey *k) -diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h ---- a/ssh-pkcs11.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/ssh-pkcs11.h (date 1703111023334) -@@ -38,6 +38,12 @@ - /* Only available in ssh-pkcs11-client.c so far */ - int pkcs11_make_cert(const struct sshkey *, - const struct sshkey *, struct sshkey **); -+ -+#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,10 +36,13 @@ - #include "sshkey.h" - #include "digest.h" - #include "log.h" -+#ifdef ENABLE_PKCS11 -+#include "ssh-pkcs11.h" -+#endif - - #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 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; - } - --static int --rsa_hash_alg_nid(int type) --{ -- switch (type) { -- case SSH_DIGEST_SHA1: -- return NID_sha1; -- case SSH_DIGEST_SHA256: -- return NID_sha256; -- case SSH_DIGEST_SHA512: -- return NID_sha512; -- default: -- return -1; -- } --} -- - int - ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp) - { -@@ -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 hlen, len; -- int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; -+ EVP_PKEY *pkey = NULL; -+ u_char *sig = NULL; -+ int len, slen = 0; -+ int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; - - if (lenp != NULL) -@@ -409,33 +418,33 @@ - hash_alg = SSH_DIGEST_SHA1; - else - hash_alg = rsa_hash_id_from_keyname(alg); -+ - if (key == NULL || key->rsa == NULL || hash_alg == -1 || - sshkey_type_plain(key->type) != KEY_RSA) - return SSH_ERR_INVALID_ARGUMENT; -- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); -- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) -- return SSH_ERR_KEY_LENGTH; - slen = RSA_size(key->rsa); -- if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) -- return SSH_ERR_INVALID_ARGUMENT; -- -- /* hash the data */ -- nid = rsa_hash_alg_nid(hash_alg); -- 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) -- goto out; -+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) -+ return SSH_ERR_KEY_LENGTH; - -- if ((sig = malloc(slen)) == NULL) { -- ret = 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 (len < slen) { - size_t diff = slen - len; - memmove(sig + diff, sig, len); -@@ -444,6 +453,7 @@ - ret = SSH_ERR_INTERNAL_ERROR; - goto out; - } -+ - /* encode signature */ - if ((b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; -@@ -464,7 +474,6 @@ - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); - freezero(sig, slen); - sshbuf_free(b); - return ret; -@@ -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, hlen; -+ size_t len = 0, diff, modlen; - struct sshbuf *b = NULL; - u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; - -@@ -487,8 +496,7 @@ - sshkey_type_plain(key->type) != KEY_RSA || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; -- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); -- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) -+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) - return SSH_ERR_KEY_LENGTH; - - if ((b = sshbuf_from(sig, siglen)) == NULL) -@@ -540,16 +548,13 @@ - explicit_bzero(sigblob, diff); - len = modlen; - } -- 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 ((ret = ssh_create_evp_rsa(key, &pkey)) != 0) - goto out; - -- 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); -@@ -558,125 +563,110 @@ - return ret; - } - --/* -- * See: -- * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ -- * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn -- */ -- --/* -- * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) -- * oiw(14) secsig(3) algorithms(2) 26 } -- */ --static const u_char id_sha1[] = { -- 0x30, 0x21, /* type Sequence, length 0x21 (33) */ -- 0x30, 0x09, /* type Sequence, length 0x09 */ -- 0x06, 0x05, /* type OID, length 0x05 */ -- 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ -- 0x05, 0x00, /* NULL */ -- 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ --}; -- --/* -- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html -- * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) -- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) -- * id-sha256(1) } -- */ --static const u_char id_sha256[] = { -- 0x30, 0x31, /* type Sequence, length 0x31 (49) */ -- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ -- 0x06, 0x09, /* type OID, length 0x09 */ -- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ -- 0x05, 0x00, /* NULL */ -- 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ --}; -- --/* -- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html -- * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) -- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) -- * id-sha256(3) } -- */ --static const u_char id_sha512[] = { -- 0x30, 0x51, /* type Sequence, length 0x51 (81) */ -- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ -- 0x06, 0x09, /* type OID, length 0x09 */ -- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ -- 0x05, 0x00, /* NULL */ -- 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ --}; -- - static int --rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) -+openssh_RSA_verify(int hash_alg, const u_char *data, size_t datalen, -+ u_char *sigbuf, size_t siglen, EVP_PKEY *pkey) - { -- switch (hash_alg) { -- case SSH_DIGEST_SHA1: -- *oidp = id_sha1; -- *oidlenp = sizeof(id_sha1); -- break; -- case SSH_DIGEST_SHA256: -- *oidp = id_sha256; -- *oidlenp = sizeof(id_sha256); -- break; -- case SSH_DIGEST_SHA512: -- *oidp = id_sha512; -- *oidlenp = sizeof(id_sha512); -- break; -- default: -- return SSH_ERR_INVALID_ARGUMENT; -- } -- return 0; --} -+ size_t rsasize = 0; -+ int ret; - --static int --openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, -- u_char *sigbuf, size_t siglen, RSA *rsa) --{ -- size_t rsasize = 0, oidlen = 0, hlen = 0; -- int ret, len, oidmatch, hashmatch; -- const u_char *oid = NULL; -- u_char *decrypted = NULL; -- -- if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) -- return ret; -- ret = SSH_ERR_INTERNAL_ERROR; -- hlen = ssh_digest_bytes(hash_alg); -- if (hashlen != hlen) { -- ret = SSH_ERR_INVALID_ARGUMENT; -- goto done; -- } -- 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; - goto done; - } -- if ((decrypted = malloc(rsasize)) == NULL) { -- ret = SSH_ERR_ALLOC_FAIL; -- goto done; -- } -- if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, -- RSA_PKCS1_PADDING)) < 0) { -- ret = SSH_ERR_LIBCRYPTO_ERROR; -- goto done; -- } -- if (len < 0 || (size_t)len != hlen + oidlen) { -- ret = SSH_ERR_INVALID_FORMAT; -- goto done; -- } -- oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; -- hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; -- if (!oidmatch || !hashmatch) { -- ret = SSH_ERR_SIGNATURE_INVALID; -- goto done; -- } -- ret = 0; -+ -+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, -+ sigbuf, siglen); -+ - done: -- freezero(decrypted, rsasize); - return ret; - } - -+int -+ssh_create_evp_rsa(const struct sshkey *k, EVP_PKEY **pkey) -+{ -+ 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 (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; -+ } -+ -+ RSA_get0_key(k->rsa, &n, &e, &d); -+ RSA_get0_factors(k->rsa, &p, &q); -+ RSA_get0_crt_params(k->rsa, &dmp1, &dmq1, &iqmp); -+ -+ 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 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; -+ } -+ -+ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ -+ /* 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 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; -+ 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; -+ } -+ -+out: -+ OSSL_PARAM_BLD_free(param_bld); -+ EVP_PKEY_CTX_free(ctx); -+ return ret; -+} -+ - static const struct sshkey_impl_funcs sshkey_rsa_funcs = { - /* .size = */ ssh_rsa_size, - /* .alloc = */ ssh_rsa_alloc, diff --git a/openssh-9.6p1-gssapi-keyex.patch b/openssh-9.6p1-gssapi-keyex.patch index e63b258..2fb5514 100644 --- a/openssh-9.6p1-gssapi-keyex.patch +++ b/openssh-9.6p1-gssapi-keyex.patch @@ -2555,9 +2555,9 @@ diff --color -ruNp a/kex.h b/kex.h # include # include @@ -102,6 +106,15 @@ enum kex_exchange { - KEX_ECDH_SHA2, KEX_C25519_SHA256, KEX_KEM_SNTRUP761X25519_SHA512, + KEX_KEM_MLKEM768X25519_SHA256, +#ifdef GSSAPI + KEX_GSS_GRP1_SHA1, + KEX_GSS_GRP14_SHA1, @@ -2730,7 +2730,7 @@ diff --color -ruNp a/Makefile.in b/Makefile.in @@ -114,6 +114,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ - kexsntrup761x25519.o sntrup761.o kexgen.o \ + kexsntrup761x25519.o kexmlkem768x25519.o sntrup761.o kexgen.o \ + kexgssc.o \ sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ sshbuf-io.o @@ -3609,7 +3609,7 @@ diff --color -ruNp a/sshconnect2.c b/sshconnect2.c free(hkalgs); /* start key exchange */ -@@ -271,14 +312,44 @@ ssh_kex2(struct ssh *ssh, char *host, st +@@ -271,15 +312,45 @@ ssh_kex2(struct ssh *ssh, char *host, st # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif @@ -3628,6 +3628,7 @@ diff --color -ruNp a/sshconnect2.c b/sshconnect2.c +#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_MLKEM768X25519_SHA256] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3949,7 +3950,7 @@ diff --color -ruNp a/sshd-session.c b/sshd-session.c +#endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; - kex->load_host_public_key=&get_hostkey_public_by_type; + kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; diff --color -ruNp a/ssh-gss.h b/ssh-gss.h --- a/ssh-gss.h 2024-07-01 06:36:28.000000000 +0200 +++ b/ssh-gss.h 2024-09-16 11:46:34.710940224 +0200 diff --git a/openssh.spec b/openssh.spec index d0a4203..f5d7b7b 100644 --- a/openssh.spec +++ b/openssh.spec @@ -46,8 +46,8 @@ %{?static_openssl:%global static_libcrypto 1} # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 -%global openssh_ver 9.8p1 -%global openssh_rel 4 +%global openssh_ver 9.9p1 +%global openssh_rel 1 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 10 @@ -188,9 +188,6 @@ Patch953: openssh-7.8p1-scp-ipv6.patch # Mention crypto-policies in manual pages (#1668325) # clarify rhbz#2068423 on the man page of ssh_config Patch962: openssh-8.0p1-crypto-policies.patch -# Use OpenSSL high-level API to produce and verify signatures (#1707485) -# TODO fix the comment above ^ -Patch963: openssh-9.3p1-merged-openssl-evp.patch # Use OpenSSL KDF (#1631761) Patch964: openssh-8.0p1-openssl-kdf.patch # sk-dummy.so built with -fvisibility=hidden does not work @@ -226,8 +223,7 @@ Patch1002: openssh-8.7p1-ssh-manpage.patch # https://github.com/openssh/openssh-portable/pull/323 Patch1006: openssh-8.7p1-negotiate-supported-algs.patch -Patch1012: openssh-9.0p1-evp-fips-dh.patch -Patch1013: openssh-9.0p1-evp-fips-ecdh.patch +Patch1012: openssh-9.0p1-evp-fips-kex.patch Patch1014: openssh-8.7p1-nohostsha1proof.patch Patch1015: openssh-9.6p1-pam-rhost.patch @@ -407,7 +403,7 @@ popd %patch -P 951 -p1 -b .pkcs11-uri %patch -P 953 -p1 -b .scp-ipv6 %patch -P 962 -p1 -b .crypto-policies -%patch -P 963 -p1 -b .openssl-evp +#%patch -P 963 -p1 -b .openssl-evp %patch -P 964 -p1 -b .openssl-kdf %patch -P 965 -p1 -b .visibility %patch -P 966 -p1 -b .x11-ipv6 @@ -431,7 +427,6 @@ popd %patch -P 1006 -p1 -b .negotiate-supported-algs %patch -P 1012 -p1 -b .evp-fips-dh -%patch -P 1013 -p1 -b .evp-fips-ecdh %patch -P 1014 -p1 -b .nosha1hostproof %patch -P 1015 -p1 -b .pam-rhost @@ -549,7 +544,7 @@ popd %endif %check -%{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile +OPENSSL_CONF=/dev/null %{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile %install rm -rf $RPM_BUILD_ROOT @@ -741,6 +736,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Tue Oct 08 2024 Dmitry Belyavskiy - 9.9p1-1 +- Update to OpenSSH 9.9p1 + * Tue Sep 03 2024 Dmitry Belyavskiy - 9.8p1-4 - Synchronize patches from Red Hat diff --git a/sources b/sources index dc4d818..b273b63 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -SHA512 (openssh-9.8p1.tar.gz) = 95dec2f18e58eb47994f3de4430253e0665e185564b65088ca5f4108870e05feddef8cda8d3c0a4b75f18b98cc2c024df0e27de53b48c1a16da8da483cb8292a -SHA512 (openssh-9.8p1.tar.gz.asc) = 4df1f1be2c6ab7f3aebaedd0a773b0e8c8929abb30cd3415873ad55d012cfa113f792e888e5e772dd468c394aeb7e35d62893a514dbc0ab1a03acd79918657f7 +SHA512 (openssh-9.9p1.tar.gz) = 3cc0ed97f3e29ecbd882eca79239f02eb5a1606fce4f3119ddc3c5e86128aa3ff12dc85000879fccc87b60e7d651cfe37376607ac66075fede2118deaa685d6d +SHA512 (openssh-9.9p1.tar.gz.asc) = 916e975c54eb68c0b2f0b0006522b241cbe54c4caa88d31537a6278490c93d9d732c2ab3a080ac084bf75cbdd5402901ec68583cbe7c7cde4a8e40e7a8b78c28 SHA512 (pam_ssh_agent_auth-0.10.4.tar.gz) = caccf72174d15e43f4c86a459ac6448682e62116557cf1e1e828955f3d1731595b238df42adec57860e7f341e92daf5d8285020bcb5018f3b8a5145aa32ee1c2 SHA512 (gpgkey-736060BA.gpg) = df44f3fdbcd1d596705348c7f5aed3f738c5f626a55955e0642f7c6c082995cf36a1b1891bb41b8715cb2aff34fef1c877e0eff0d3507dd00a055ba695757a21 From 2b8473c18afa5fb9e2e83727093634b6cf554b18 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 10 Oct 2024 15:55:43 +0200 Subject: [PATCH 44/80] Update version of pam_ssh_agent_auth --- openssh.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index f5d7b7b..78bab27 100644 --- a/openssh.spec +++ b/openssh.spec @@ -47,9 +47,9 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 9.9p1 -%global openssh_rel 1 +%global openssh_rel 2 %global pam_ssh_agent_ver 0.10.4 -%global pam_ssh_agent_rel 10 +%global pam_ssh_agent_rel 11 Summary: An open source implementation of SSH protocol version 2 Name: openssh @@ -736,6 +736,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Thu Oct 10 2024 Dmitry Belyavskiy - 9.9p1-2 +- Update version of pam_ssh_agent_auth + * Tue Oct 08 2024 Dmitry Belyavskiy - 9.9p1-1 - Update to OpenSSH 9.9p1 From b3639c96162c4c6c94de7bcfdc8abf48e5adedd5 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 11 Oct 2024 14:42:24 +0200 Subject: [PATCH 45/80] Separate ssh-keysign to a dedicated package --- openssh-9.9p1-separate-keysign.patch | 12 ++++++++++++ openssh.spec | 22 +++++++++++++++++++--- 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 openssh-9.9p1-separate-keysign.patch diff --git a/openssh-9.9p1-separate-keysign.patch b/openssh-9.9p1-separate-keysign.patch new file mode 100644 index 0000000..ff0e35f --- /dev/null +++ b/openssh-9.9p1-separate-keysign.patch @@ -0,0 +1,12 @@ +diff -up openssh-9.9p1/ssh_config.5.xxx openssh-9.9p1/ssh_config.5 +--- openssh-9.9p1/ssh_config.5.xxx 2024-10-11 12:01:14.260566303 +0200 ++++ openssh-9.9p1/ssh_config.5 2024-10-11 12:01:59.725654775 +0200 +@@ -759,7 +759,7 @@ or + This option should be placed in the non-hostspecific section. + See + .Xr ssh-keysign 8 +-for more information. ++for more information. ssh-keysign should be installed explicitly. + .It Cm EscapeChar + Sets the escape character (default: + .Ql ~ ) . diff --git a/openssh.spec b/openssh.spec index 78bab27..7e590e0 100644 --- a/openssh.spec +++ b/openssh.spec @@ -47,7 +47,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 9.9p1 -%global openssh_rel 2 +%global openssh_rel 3 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 11 @@ -227,6 +227,7 @@ Patch1012: openssh-9.0p1-evp-fips-kex.patch Patch1014: openssh-8.7p1-nohostsha1proof.patch Patch1015: openssh-9.6p1-pam-rhost.patch +Patch1016: openssh-9.9p1-separate-keysign.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -279,6 +280,10 @@ Summary: An open source SSH client applications Requires: openssh = %{version}-%{release} Requires: crypto-policies >= 20220824-1 +%package keysign +Summary: A helper program used for host-based authentication +Requires: openssh = %{version}-%{release} + %package server Summary: An open source SSH server daemon Requires: openssh = %{version}-%{release} @@ -324,6 +329,11 @@ OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package includes the clients necessary to make encrypted connections to SSH servers. +%description keysign +OpenSSH is a free version of SSH (Secure SHell), a program for logging +into and executing commands on a remote machine. ssh-keysign is a +helper program used for host-based authentication disabled by default. + %description server OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains @@ -429,6 +439,7 @@ popd %patch -P 1012 -p1 -b .evp-fips-dh %patch -P 1014 -p1 -b .nosha1hostproof %patch -P 1015 -p1 -b .pam-rhost +%patch -P 1016 -p1 -b .sep-keysign %patch -P 100 -p1 -b .coverity @@ -658,8 +669,6 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_bindir}/ssh-keygen %attr(0644,root,root) %{_mandir}/man1/ssh-keygen.1* %attr(0755,root,root) %dir %{_libexecdir}/openssh -%attr(4555,root,root) %{_libexecdir}/openssh/ssh-keysign -%attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8* %files clients %attr(0755,root,root) %{_bindir}/ssh @@ -687,6 +696,10 @@ test -f %{sysconfig_anaconda} && \ %attr(0644,root,root) %{_userunitdir}/ssh-agent.service %attr(0644,root,root) %{_userunitdir}/ssh-agent.socket +%files keysign +%attr(4555,root,root) %{_libexecdir}/openssh/ssh-keysign +%attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8* + %files server %dir %attr(0711,root,root) %{_datadir}/empty.sshd %attr(0755,root,root) %{_sbindir}/sshd @@ -736,6 +749,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Fri Oct 11 2024 Dmitry Belyavskiy - 9.9p1-3 +- Separate ssh-keysign to a dedicated package + * Thu Oct 10 2024 Dmitry Belyavskiy - 9.9p1-2 - Update version of pam_ssh_agent_auth From 2c05d867133c439a0909ebf858709272ce656725 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 11 Oct 2024 14:43:34 +0200 Subject: [PATCH 46/80] Use FIPS KEX defaults in FIPS mode --- openssh-7.7p1-fips.patch | 20 ++++++++++++++++++++ openssh.spec | 1 + 2 files changed, 21 insertions(+) diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index a53f9f6..5d8da08 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -744,3 +744,23 @@ diff -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; +diff -up openssh-9.9p1/kex.c.xxx openssh-9.9p1/kex.c +--- openssh-9.9p1/kex.c.xxx 2024-10-11 12:44:08.087426597 +0200 ++++ openssh-9.9p1/kex.c 2024-10-11 14:00:10.404714521 +0200 +@@ -40,6 +40,7 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include + # ifdef HAVE_EVP_KDF_CTX_NEW + # include + # include +@@ -109,7 +110,7 @@ kex_proposal_populate_entries(struct ssh + + /* Append EXT_INFO signalling to KexAlgorithms */ + if (kexalgos == NULL) +- kexalgos = defprop[PROPOSAL_KEX_ALGS]; ++ kexalgos = FIPS_mode() ? KEX_DEFAULT_KEX_FIPS : defprop[PROPOSAL_KEX_ALGS]; + if ((cp = kex_names_cat(kexalgos, ssh->kex->server ? + "ext-info-s,kex-strict-s-v00@openssh.com" : + "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) diff --git a/openssh.spec b/openssh.spec index 7e590e0..f14f90d 100644 --- a/openssh.spec +++ b/openssh.spec @@ -751,6 +751,7 @@ test -f %{sysconfig_anaconda} && \ %changelog * Fri Oct 11 2024 Dmitry Belyavskiy - 9.9p1-3 - Separate ssh-keysign to a dedicated package +- Use FIPS KEX defaults in FIPS mode * Thu Oct 10 2024 Dmitry Belyavskiy - 9.9p1-2 - Update version of pam_ssh_agent_auth From e0b8822dc8c5676863dcc9666441a2b3a82b2a44 Mon Sep 17 00:00:00 2001 From: Nils Kattenbeck Date: Mon, 14 Oct 2024 16:58:19 +0000 Subject: [PATCH 47/80] Avoid warning when OPTIONS var is not set by environment file --- sshd@.service | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sshd@.service b/sshd@.service index be6d3b9..c077be2 100644 --- a/sshd@.service +++ b/sshd@.service @@ -8,6 +8,9 @@ After=sshd-keygen.target Wants=ssh-host-keys-migration.service [Service] +# Set option as empty variable to avoid warnings upon expanding the command line +# when the config file under /etc does not exist or is empty. +Environment=OPTIONS= EnvironmentFile=-/etc/sysconfig/sshd ExecStart=-/usr/sbin/sshd -i $OPTIONS StandardInput=socket From 10c69e8578453553a454426ec66067e827bde6bb Mon Sep 17 00:00:00 2001 From: Nils Kattenbeck Date: Mon, 14 Oct 2024 17:01:01 +0000 Subject: [PATCH 48/80] Avoid warning when OPTIONS var is not set by environment file --- sshd.service | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sshd.service b/sshd.service index 0cb2a26..350624d 100644 --- a/sshd.service +++ b/sshd.service @@ -9,6 +9,9 @@ Wants=ssh-host-keys-migration.service [Service] Type=notify +# Set option as empty variable to suppress warnings upon expanding the command line +# when the config file under /etc does not exist or is empty. +Environment=OPTIONS= EnvironmentFile=-/etc/sysconfig/sshd ExecStart=/usr/sbin/sshd -D $OPTIONS ExecReload=/bin/kill -HUP $MAINPID From 7f540abac3cdd30d854264b0dc0d9a0f95197207 Mon Sep 17 00:00:00 2001 From: Nils Kattenbeck Date: Mon, 14 Oct 2024 17:01:30 +0000 Subject: [PATCH 49/80] Avoid warning when OPTIONS var is not set by environment file --- sshd-keygen@.service | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sshd-keygen@.service b/sshd-keygen@.service index f27f729..aee1303 100644 --- a/sshd-keygen@.service +++ b/sshd-keygen@.service @@ -4,6 +4,9 @@ ConditionFileNotEmpty=|!/etc/ssh/ssh_host_%i_key [Service] Type=oneshot +# Set option as empty variable to suppress warnings upon expanding the command line +# when the config file under /etc does not exist or is empty. +Environment=OPTIONS= EnvironmentFile=-/etc/sysconfig/sshd ExecStart=/usr/libexec/openssh/sshd-keygen %i From 0fd6584c66535c298373dd6035e5594a464312ea Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Tue, 15 Oct 2024 14:38:14 +0200 Subject: [PATCH 50/80] Gssapi-keyex: fix issues found by static analysis Signed-off-by: Zoltan Fridrich --- openssh-9.6p1-gssapi-keyex.patch | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/openssh-9.6p1-gssapi-keyex.patch b/openssh-9.6p1-gssapi-keyex.patch index 2fb5514..ef1f97e 100644 --- a/openssh-9.6p1-gssapi-keyex.patch +++ b/openssh-9.6p1-gssapi-keyex.patch @@ -1240,8 +1240,8 @@ diff --color -ruNp a/kexgen.c b/kexgen.c const struct sshbuf *client_version, diff --color -ruNp a/kexgssc.c b/kexgssc.c --- a/kexgssc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/kexgssc.c 2024-09-16 11:46:34.709940203 +0200 -@@ -0,0 +1,704 @@ ++++ b/kexgssc.c 2024-10-14 15:18:02.491798105 +0200 +@@ -0,0 +1,706 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1603,6 +1603,7 @@ diff --color -ruNp a/kexgssc.c b/kexgssc.c + if (gss->major & GSS_S_CONTINUE_NEEDED) + return kexgss_init_ctx(ssh, &recv_tok); + ++ gss_release_buffer(&gss->minor, &recv_tok); + return kexgss_final(ssh); +} + @@ -1942,14 +1943,15 @@ diff --color -ruNp a/kexgssc.c b/kexgssc.c + if (gss->major & GSS_S_CONTINUE_NEEDED) + return kexgssgex_init_ctx(ssh, &recv_tok); + ++ gss_release_buffer(&gss->minor, &recv_tok); + return kexgssgex_final(ssh); +} + +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --color -ruNp a/kexgsss.c b/kexgsss.c --- a/kexgsss.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/kexgsss.c 2024-09-16 11:46:34.710940224 +0200 -@@ -0,0 +1,590 @@ ++++ b/kexgsss.c 2024-10-14 15:18:02.491798105 +0200 +@@ -0,0 +1,601 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -2082,6 +2084,9 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + struct kex *kex = ssh->kex; + Gssctxt *gss = kex->gss; + gss_buffer_desc msg_tok; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ struct sshbuf *shared_secret = NULL; + int r; + + ssh_dispatch_set(ssh, SSH2_MSG_KEXGSS_INIT, NULL); @@ -2125,12 +2130,18 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + gss_release_buffer(&gss->minor, send_tok); + gss_release_buffer(&gss->minor, &msg_tok); + ++ hashlen = gss->hashlen; ++ memcpy(hash, gss->hash, hashlen); ++ explicit_bzero(gss->hash, sizeof(gss->hash)); ++ shared_secret = gss->shared_secret; ++ gss->shared_secret = NULL; ++ + if (gss_kex_context == NULL) + gss_kex_context = gss; + else + ssh_gssapi_delete_ctx(&kex->gss); + -+ if ((r = kex_derive_keys(ssh, gss->hash, gss->hashlen, gss->shared_secret)) == 0) ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) + r = kex_send_newkeys(ssh); + + /* If this was a rekey, then save out any delegated credentials we @@ -2139,12 +2150,11 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + ssh_gssapi_rekey_creds(); + + if (kex->gss != NULL) { -+ explicit_bzero(gss->hash, sizeof(gss->hash)); -+ sshbuf_free(gss->shared_secret); -+ gss->shared_secret = NULL; + sshbuf_free(gss->server_pubkey); + gss->server_pubkey = NULL; + } ++ explicit_bzero(hash, sizeof(hash)); ++ sshbuf_free(shared_secret); + return r; +} + @@ -2187,7 +2197,8 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + } + if (r != 0) { + sshbuf_free(client_pubkey); -+ ssh_gssapi_delete_ctx(&kex->gss); ++ gss_release_buffer(&gss->minor, &recv_tok); ++ ssh_gssapi_delete_ctx(&kex->gss); + return r; + } + @@ -2195,6 +2206,7 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + + if ((empty = sshbuf_new()) == NULL) { + sshbuf_free(client_pubkey); ++ gss_release_buffer(&gss->minor, &recv_tok); + ssh_gssapi_delete_ctx(&kex->gss); + return SSH_ERR_ALLOC_FAIL; + } @@ -2210,6 +2222,7 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c + sshbuf_free(empty); + sshbuf_free(client_pubkey); + if (r != 0) { ++ gss_release_buffer(&gss->minor, &recv_tok); + ssh_gssapi_delete_ctx(&kex->gss); + return r; + } From 5f1bef29885c4c9a347c4be27724a5f2382596c0 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 16 Oct 2024 15:14:16 +0200 Subject: [PATCH 51/80] Memory management improvements --- openssh-8.7p1-audit-hostname.patch | 106 ----------------------- openssh-9.0p1-audit-log.patch | 133 ++++++++++++++++++++++++++++- openssh.spec | 9 +- 3 files changed, 135 insertions(+), 113 deletions(-) delete mode 100644 openssh-8.7p1-audit-hostname.patch diff --git a/openssh-8.7p1-audit-hostname.patch b/openssh-8.7p1-audit-hostname.patch deleted file mode 100644 index e450c00..0000000 --- a/openssh-8.7p1-audit-hostname.patch +++ /dev/null @@ -1,106 +0,0 @@ -diff --color -ruNp a/audit-linux.c b/audit-linux.c ---- a/audit-linux.c 2024-05-09 12:38:08.843017319 +0200 -+++ b/audit-linux.c 2024-05-09 12:47:05.162267634 +0200 -@@ -52,7 +52,7 @@ extern u_int utmp_len; - const char *audit_username(void); - - static void --linux_audit_user_logxxx(int uid, const char *username, -+linux_audit_user_logxxx(int uid, const char *username, const char *hostname, - const char *ip, const char *ttyn, int success, int event) - { - int audit_fd, rc, saved_errno; -@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const c - } - rc = audit_log_acct_message(audit_fd, event, - NULL, "login", username ? username : "(unknown)", -- username == NULL ? uid : -1, NULL, ip, ttyn, success); -+ username == NULL ? uid : -1, hostname, ip, ttyn, success); - saved_errno = errno; - close(audit_fd); - -@@ -181,9 +181,11 @@ audit_run_command(struct ssh *ssh, const - { - if (!user_login_count++) - linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ options.use_dns ? remote_hostname(ssh) : NULL, - ssh_remote_ipaddr(ssh), - "ssh", 1, AUDIT_USER_LOGIN); - linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ options.use_dns ? remote_hostname(ssh) : NULL, - ssh_remote_ipaddr(ssh), - "ssh", 1, AUDIT_USER_START); - return 0; -@@ -193,10 +195,12 @@ void - audit_end_command(struct ssh *ssh, int handle, const char *command) - { - linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ options.use_dns ? remote_hostname(ssh) : NULL, - ssh_remote_ipaddr(ssh), - "ssh", 1, AUDIT_USER_END); - if (user_login_count && !--user_login_count) - linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ options.use_dns ? remote_hostname(ssh) : NULL, - ssh_remote_ipaddr(ssh), - "ssh", 1, AUDIT_USER_LOGOUT); - } -@@ -211,19 +215,27 @@ void - audit_session_open(struct logininfo *li) - { - if (!user_login_count++) -- linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ linux_audit_user_logxxx(li->uid, NULL, -+ options.use_dns ? li->hostname : NULL, -+ options.use_dns ? NULL : li->hostname, - li->line, 1, AUDIT_USER_LOGIN); -- linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ linux_audit_user_logxxx(li->uid, NULL, -+ options.use_dns ? li->hostname : NULL, -+ options.use_dns ? NULL : li->hostname, - li->line, 1, AUDIT_USER_START); - } - - void - audit_session_close(struct logininfo *li) - { -- linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ linux_audit_user_logxxx(li->uid, NULL, -+ options.use_dns ? li->hostname : NULL, -+ options.use_dns ? NULL : li->hostname, - li->line, 1, AUDIT_USER_END); - if (user_login_count && !--user_login_count) -- linux_audit_user_logxxx(li->uid, NULL, li->hostname, -+ linux_audit_user_logxxx(li->uid, NULL, -+ options.use_dns ? li->hostname : NULL, -+ options.use_dns ? NULL : li->hostname, - li->line, 1, AUDIT_USER_LOGOUT); - } - -@@ -236,6 +248,7 @@ audit_event(struct ssh *ssh, ssh_audit_e - linux_audit_user_auth(-1, audit_username(), - ssh_remote_ipaddr(ssh), "ssh", 0, event); - linux_audit_user_logxxx(-1, audit_username(), -+ options.use_dns ? remote_hostname(ssh) : NULL, - ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); - break; - case SSH_AUTH_FAIL_PASSWD: -@@ -254,9 +267,11 @@ audit_event(struct ssh *ssh, ssh_audit_e - if (user_login_count) { - while (user_login_count--) - linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ options.use_dns ? remote_hostname(ssh) : NULL, - ssh_remote_ipaddr(ssh), - "ssh", 1, AUDIT_USER_END); - linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ options.use_dns ? remote_hostname(ssh) : NULL, - ssh_remote_ipaddr(ssh), - "ssh", 1, AUDIT_USER_LOGOUT); - } -@@ -265,6 +280,7 @@ audit_event(struct ssh *ssh, ssh_audit_e - case SSH_CONNECTION_ABANDON: - case SSH_INVALID_USER: - linux_audit_user_logxxx(-1, audit_username(), -+ options.use_dns ? remote_hostname(ssh) : NULL, - ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); - break; - default: diff --git a/openssh-9.0p1-audit-log.patch b/openssh-9.0p1-audit-log.patch index fbf5094..ae9550f 100644 --- a/openssh-9.0p1-audit-log.patch +++ b/openssh-9.0p1-audit-log.patch @@ -52,9 +52,27 @@ diff -up openssh-9.0p1/audit.h.patch openssh-9.0p1/audit.h 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 *); -diff -up openssh-9.0p1/audit-linux.c.patch openssh-9.0p1/audit-linux.c ---- openssh-9.0p1/audit-linux.c.patch 2022-10-24 15:02:16.544858331 +0200 -+++ openssh-9.0p1/audit-linux.c 2022-10-24 15:21:58.165303951 +0200 +diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c +--- openssh-9.9p1/audit-linux.c.xxx 2024-10-15 11:49:48.092151974 +0200 ++++ openssh-9.9p1/audit-linux.c 2024-10-15 12:08:17.179158343 +0200 +@@ -52,7 +52,7 @@ extern u_int utmp_len; + const char *audit_username(void); + + static void +-linux_audit_user_logxxx(int uid, const char *username, ++linux_audit_user_logxxx(int uid, const char *username, const char *hostname, + const char *ip, const char *ttyn, int success, int event) + { + int audit_fd, rc, saved_errno; +@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const c + } + rc = audit_log_acct_message(audit_fd, event, + NULL, "login", username ? username : "(unknown)", +- username == NULL ? uid : -1, NULL, ip, ttyn, success); ++ username == NULL ? uid : -1, hostname, ip, ttyn, success); + saved_errno = errno; + close(audit_fd); + @@ -137,10 +137,12 @@ fatal_report: } @@ -117,3 +135,112 @@ diff -up openssh-9.0p1/audit-linux.c.patch openssh-9.0p1/audit-linux.c out: saved_errno = errno; audit_close(audit_fd); +@@ -179,26 +211,34 @@ audit_connection_from(const char *host, + int + audit_run_command(struct ssh *ssh, const char *command) + { ++ char * audit_hostname = options.use_dns ? remote_hostname(ssh) : NULL; + if (!user_login_count++) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ audit_hostname, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGIN); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ audit_hostname, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_START); ++ free(audit_hostname); + return 0; + } + + void + audit_end_command(struct ssh *ssh, int handle, const char *command) + { ++ char * audit_hostname = options.use_dns ? remote_hostname(ssh) : NULL; + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ audit_hostname, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ audit_hostname, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); ++ free(audit_hostname); + } + + void +@@ -211,31 +251,41 @@ void + audit_session_open(struct logininfo *li) + { + if (!user_login_count++) +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_LOGIN); +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_START); + } + + void + audit_session_close(struct logininfo *li) + { +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) +- linux_audit_user_logxxx(li->uid, NULL, li->hostname, ++ linux_audit_user_logxxx(li->uid, NULL, ++ options.use_dns ? li->hostname : NULL, ++ options.use_dns ? NULL : li->hostname, + li->line, 1, AUDIT_USER_LOGOUT); + } + + void + audit_event(struct ssh *ssh, ssh_audit_event_t event) + { ++ char * audit_hostname = options.use_dns ? remote_hostname(ssh) : NULL; ++ + switch(event) { + case SSH_NOLOGIN: + case SSH_LOGIN_ROOT_DENIED: + linux_audit_user_auth(-1, audit_username(), + ssh_remote_ipaddr(ssh), "ssh", 0, event); +- linux_audit_user_logxxx(-1, audit_username(), ++ linux_audit_user_logxxx(-1, audit_username(), audit_hostname, + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + case SSH_AUTH_FAIL_PASSWD: +@@ -255,9 +305,11 @@ audit_event(struct ssh *ssh, ssh_audit_e + if (user_login_count) { + while (user_login_count--) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ audit_hostname, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, ++ audit_hostname, + ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); + } +@@ -266,12 +318,14 @@ audit_event(struct ssh *ssh, ssh_audit_e + case SSH_CONNECTION_ABANDON: + case SSH_INVALID_USER: + linux_audit_user_logxxx(-1, audit_username(), ++ audit_hostname, + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); + break; + default: + debug("%s: unhandled event %d", __func__, event); + break; + } ++ free(audit_hostname); + } + + void diff --git a/openssh.spec b/openssh.spec index f14f90d..5b0009a 100644 --- a/openssh.spec +++ b/openssh.spec @@ -47,7 +47,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 9.9p1 -%global openssh_rel 3 +%global openssh_rel 4 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 11 @@ -90,8 +90,6 @@ Patch200: openssh-7.6p1-audit.patch Patch201: openssh-7.1p2-audit-race-condition.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2049947 Patch202: openssh-9.0p1-audit-log.patch -# Correctly audit hostname and IP address -Patch203: openssh-8.7p1-audit-hostname.patch # --- pam_ssh-agent --- # make it build reusing the openssh sources @@ -429,7 +427,6 @@ popd %patch -P 200 -p1 -b .audit %patch -P 201 -p1 -b .audit-race %patch -P 202 -p1 -b .audit-log -%patch -P 203 -p1 -b .audit-hostname %patch -P 700 -p1 -b .fips %patch -P 1002 -p1 -b .ssh-manpage @@ -749,6 +746,10 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Wed Oct 16 2024 Dmitry Belyavskiy - 9.9p1-4 +- Resolve memory management issues after rebase +- Define OPTIONS env in systemd modules (https://src.fedoraproject.org/rpms/openssh/pull-request/92) + * Fri Oct 11 2024 Dmitry Belyavskiy - 9.9p1-3 - Separate ssh-keysign to a dedicated package - Use FIPS KEX defaults in FIPS mode From 9bab787a28ad5e67119dde105198b2e947df3f05 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 28 Oct 2024 17:41:21 +0100 Subject: [PATCH 52/80] Fix MLKEM for BE platforms --- openssh-9.9p1-mlkembe.patch | 98 +++++++++++++++++++++++++++++++++++++ openssh.spec | 9 +++- 2 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 openssh-9.9p1-mlkembe.patch diff --git a/openssh-9.9p1-mlkembe.patch b/openssh-9.9p1-mlkembe.patch new file mode 100644 index 0000000..aa0c26c --- /dev/null +++ b/openssh-9.9p1-mlkembe.patch @@ -0,0 +1,98 @@ +diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c +index 679446e9..2b5d3960 100644 +--- a/kexmlkem768x25519.c ++++ b/kexmlkem768x25519.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: kexmlkem768x25519.c,v 1.1 2024/09/02 12:13:56 djm Exp $ */ ++/* $OpenBSD: kexmlkem768x25519.c,v 1.2 2024/10/27 02:06:59 djm Exp $ */ + /* + * Copyright (c) 2023 Markus Friedl. All rights reserved. + * +@@ -34,6 +34,9 @@ + #include + #include + #include ++#ifdef HAVE_ENDIAN_H ++# include ++#endif + + #include "sshkey.h" + #include "kex.h" +diff --git a/libcrux_mlkem768_sha3.h b/libcrux_mlkem768_sha3.h +index a82d60e8..b8ac1436 100644 +--- a/libcrux_mlkem768_sha3.h ++++ b/libcrux_mlkem768_sha3.h +@@ -1,4 +1,5 @@ +-/* $OpenBSD: libcrux_mlkem768_sha3.h,v 1.1 2024/09/02 12:13:56 djm Exp $ */ ++/* $OpenBSD: libcrux_mlkem768_sha3.h,v 1.2 2024/10/27 02:06:01 djm Exp $ */ ++ + /* Extracted from libcrux revision 84c5d87b3092c59294345aa269ceefe0eb97cc35 */ + + /* +@@ -160,18 +161,19 @@ static inline void Eurydice_slice_to_array3(uint8_t *dst_tag, char *dst_ok, + // CORE STUFF (conversions, endianness, ...) + + static inline void core_num__u64_9__to_le_bytes(uint64_t v, uint8_t buf[8]) { ++ v = htole64(v); + memcpy(buf, &v, sizeof(v)); + } + static inline uint64_t core_num__u64_9__from_le_bytes(uint8_t buf[8]) { + uint64_t v; + memcpy(&v, buf, sizeof(v)); +- return v; ++ return le64toh(v); + } + + static inline uint32_t core_num__u32_8__from_le_bytes(uint8_t buf[4]) { + uint32_t v; + memcpy(&v, buf, sizeof(v)); +- return v; ++ return le32toh(v); + } + + static inline uint32_t core_num__u8_6__count_ones(uint8_t x0) { +diff --git a/mlkem768.sh b/mlkem768.sh +index 2fdc2831..3d12b2ed 100644 +--- a/mlkem768.sh ++++ b/mlkem768.sh +@@ -1,9 +1,10 @@ + #!/bin/sh +-# $OpenBSD: mlkem768.sh,v 1.2 2024/09/04 05:11:33 djm Exp $ ++# $OpenBSD: mlkem768.sh,v 1.3 2024/10/27 02:06:01 djm Exp $ + # Placed in the Public Domain. + # + +-WANT_LIBCRUX_REVISION="origin/main" ++#WANT_LIBCRUX_REVISION="origin/main" ++WANT_LIBCRUX_REVISION="84c5d87b3092c59294345aa269ceefe0eb97cc35" + + FILES=" + libcrux/libcrux-ml-kem/cg/eurydice_glue.h +@@ -47,6 +48,7 @@ echo '#define KRML_NOINLINE __attribute__((noinline, unused))' + echo '#define KRML_HOST_EPRINTF(...)' + echo '#define KRML_HOST_EXIT(x) fatal_f("internal error")' + echo ++ + for i in $FILES; do + echo "/* from $i */" + # Changes to all files: +@@ -56,11 +58,16 @@ for i in $FILES; do + -e 's/[ ]*$//' \ + $i | \ + case "$i" in +- # XXX per-file handling goes here. ++ */libcrux-ml-kem/cg/eurydice_glue.h) ++ # Replace endian functions with versions that work. ++ perl -0777 -pe 's/(static inline void core_num__u64_9__to_le_bytes.*\n)([^}]*\n)/\1 v = htole64(v);\n\2/' | ++ perl -0777 -pe 's/(static inline uint64_t core_num__u64_9__from_le_bytes.*?)return v;/\1return le64toh(v);/s' | ++ perl -0777 -pe 's/(static inline uint32_t core_num__u32_8__from_le_bytes.*?)return v;/\1return le32toh(v);/s' ++ ;; + # Default: pass through. + *) +- cat +- ;; ++ cat ++ ;; + esac + echo + done diff --git a/openssh.spec b/openssh.spec index 5b0009a..28cf598 100644 --- a/openssh.spec +++ b/openssh.spec @@ -47,7 +47,7 @@ # Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 9.9p1 -%global openssh_rel 4 +%global openssh_rel 5 %global pam_ssh_agent_ver 0.10.4 %global pam_ssh_agent_rel 11 @@ -226,6 +226,9 @@ Patch1014: openssh-8.7p1-nohostsha1proof.patch Patch1015: openssh-9.6p1-pam-rhost.patch Patch1016: openssh-9.9p1-separate-keysign.patch +# upstream cf3e48ee8ba1beeccddd2f203b558fa102be67a2 +# upstream 0c3927c45f8a57b511c874c4d51a8c89414f74ef +Patch1017: openssh-9.9p1-mlkembe.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -437,6 +440,7 @@ popd %patch -P 1014 -p1 -b .nosha1hostproof %patch -P 1015 -p1 -b .pam-rhost %patch -P 1016 -p1 -b .sep-keysign +%patch -P 1017 -p1 -b .mlkembe %patch -P 100 -p1 -b .coverity @@ -746,6 +750,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Mon Oct 28 2024 Dmitry Belyavskiy - 9.9p1-5 +- Fix MLKEM for BE platforms + * Wed Oct 16 2024 Dmitry Belyavskiy - 9.9p1-4 - Resolve memory management issues after rebase - Define OPTIONS env in systemd modules (https://src.fedoraproject.org/rpms/openssh/pull-request/92) From 7551e5647175e7cd441970ab589f486ffc51bd3b Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Fri, 17 Jan 2025 21:50:57 +0000 Subject: [PATCH 53/80] Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild --- openssh.spec | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index 28cf598..37f7c3b 100644 --- a/openssh.spec +++ b/openssh.spec @@ -54,7 +54,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist} +Release: %{openssh_rel}%{?dist}.1 URL: http://www.openssh.com/portable.html #URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz @@ -308,7 +308,7 @@ Requires: openssh = %{version}-%{release} %package -n pam_ssh_agent_auth Summary: PAM module for authentication with ssh-agent Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist} +Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.1 License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL %description @@ -750,6 +750,9 @@ test -f %{sysconfig_anaconda} && \ %endif %changelog +* Fri Jan 17 2025 Fedora Release Engineering - 9.9p1-5.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild + * Mon Oct 28 2024 Dmitry Belyavskiy - 9.9p1-5 - Fix MLKEM for BE platforms From 50fa131d405e70354a9f6b27d5b5be0f1c266ef2 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 27 Jan 2025 11:10:48 +0100 Subject: [PATCH 54/80] Remove pam-ssh-agent subcomponent Resolves: rhbz#2338440 --- openssh.spec | 100 +- pam_ssh_agent-configure-c99.patch | 249 ----- pam_ssh_agent-rmheaders | 36 - pam_ssh_agent_auth-0.10.2-compat.patch | 992 ------------------ pam_ssh_agent_auth-0.10.2-dereference.patch | 20 - pam_ssh_agent_auth-0.10.3-seteuid.patch | 37 - pam_ssh_agent_auth-0.10.4-rsasha2.patch | 19 - pam_ssh_agent_auth-0.9.2-visibility.patch | 21 - ...ssh_agent_auth-0.9.3-agent_structure.patch | 96 -- pam_ssh_agent_auth-0.9.3-build.patch | 198 ---- sources | 1 - 11 files changed, 6 insertions(+), 1763 deletions(-) delete mode 100644 pam_ssh_agent-configure-c99.patch delete mode 100644 pam_ssh_agent-rmheaders delete mode 100644 pam_ssh_agent_auth-0.10.2-compat.patch delete mode 100644 pam_ssh_agent_auth-0.10.2-dereference.patch delete mode 100644 pam_ssh_agent_auth-0.10.3-seteuid.patch delete mode 100644 pam_ssh_agent_auth-0.10.4-rsasha2.patch delete mode 100644 pam_ssh_agent_auth-0.9.2-visibility.patch delete mode 100644 pam_ssh_agent_auth-0.9.3-agent_structure.patch delete mode 100644 pam_ssh_agent_auth-0.9.3-build.patch diff --git a/openssh.spec b/openssh.spec index 37f7c3b..fba7b89 100644 --- a/openssh.spec +++ b/openssh.spec @@ -25,13 +25,6 @@ # Do we want libedit support %global libedit 1 -# Whether to build pam_ssh_agent_auth -%if 0%{?!nopam:1} -%global pam_ssh_agent 1 -%else -%global pam_ssh_agent 0 -%endif - # Reserve options to override askpass settings with: # rpm -ba|--rebuild --define 'skip_xxx 1' %{?skip_gnome_askpass:%global no_gnome_askpass 1} @@ -45,24 +38,18 @@ # rpm -ba|--rebuild --define "static_openssl 1" %{?static_openssl:%global static_libcrypto 1} -# Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1 %global openssh_ver 9.9p1 -%global openssh_rel 5 -%global pam_ssh_agent_ver 0.10.4 -%global pam_ssh_agent_rel 11 +%global openssh_rel 6 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} Release: %{openssh_rel}%{?dist}.1 URL: http://www.openssh.com/portable.html -#URL1: https://github.com/jbeverly/pam_ssh_agent_auth/ Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc Source2: sshd.pam Source3: gpgkey-736060BA.gpg -Source4: https://github.com/jbeverly/pam_ssh_agent_auth/archive/pam_ssh_agent_auth-%{pam_ssh_agent_ver}.tar.gz -Source5: pam_ssh_agent-rmheaders Source6: ssh-keycat.pam Source7: sshd.sysconfig Source9: sshd@.service @@ -91,25 +78,6 @@ Patch201: openssh-7.1p2-audit-race-condition.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2049947 Patch202: openssh-9.0p1-audit-log.patch -# --- pam_ssh-agent --- -# make it build reusing the openssh sources -Patch300: pam_ssh_agent_auth-0.9.3-build.patch -# check return value of seteuid() -# https://sourceforge.net/p/pamsshagentauth/bugs/23/ -Patch301: pam_ssh_agent_auth-0.10.3-seteuid.patch -# explicitly make pam callbacks visible -Patch302: pam_ssh_agent_auth-0.9.2-visibility.patch -# update to current version of agent structure -Patch305: pam_ssh_agent_auth-0.9.3-agent_structure.patch -# remove prefixes to be able to build against current openssh library -Patch306: pam_ssh_agent_auth-0.10.2-compat.patch -# Fix NULL dereference from getpwuid() return value -# https://sourceforge.net/p/pamsshagentauth/bugs/22/ -Patch307: pam_ssh_agent_auth-0.10.2-dereference.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=2070113 -Patch308: pam_ssh_agent_auth-0.10.4-rsasha2.patch -Patch309: pam_ssh_agent-configure-c99.patch - #https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX) Patch400: openssh-7.8p1-role-mls.patch #https://bugzilla.redhat.com/show_bug.cgi?id=781634 @@ -305,12 +273,6 @@ Requires: openssh = %{version}-%{release} Summary: OpenSSH SK driver for test purposes Requires: openssh = %{version}-%{release} -%package -n pam_ssh_agent_auth -Summary: PAM module for authentication with ssh-agent -Version: %{pam_ssh_agent_ver} -Release: %{pam_ssh_agent_rel}.%{openssh_rel}%{?dist}.1 -License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant AND OpenSSL - %description SSH (Secure SHell) is a program for logging into and executing commands on a remote machine. SSH is intended to replace rlogin and @@ -353,32 +315,9 @@ an X11 passphrase dialog for OpenSSH. %description sk-dummy This package contains a test SK driver used for OpenSSH test purposes -%description -n pam_ssh_agent_auth -This package contains a PAM module which can be used to authenticate -users using ssh keys stored in a ssh-agent. Through the use of the -forwarding of ssh-agent connection it also allows to authenticate with -remote ssh-agent instance. - -The module is most useful for su and sudo service stacks. - %prep gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} -%setup -q -a 4 - -%if %{pam_ssh_agent} -pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} -%patch -P 300 -p2 -b .psaa-build -%patch -P 301 -p2 -b .psaa-seteuid -%patch -P 302 -p2 -b .psaa-visibility -%patch -P 306 -p2 -b .psaa-compat -%patch -P 305 -p2 -b .psaa-agent -%patch -P 307 -p2 -b .psaa-deref -%patch -P 308 -p2 -b .rsasha2 -%patch -P 309 -p1 -b .psaa-configure-c99 -# Remove duplicate headers and library files -rm -f $(cat %{SOURCE5}) -popd -%endif +%setup -q %patch -P 400 -p1 -b .role-mls %patch -P 404 -p1 -b .privsep-selinux @@ -445,15 +384,9 @@ popd %patch -P 100 -p1 -b .coverity autoreconf -pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} -autoreconf -popd %build %set_build_flags -# the -fvisibility=hidden is needed for clean build of the pam_ssh_agent_auth -# it is needed for lib(open)ssh build too since it is linked to the pam module too -CFLAGS="$CFLAGS -fvisibility=hidden"; export CFLAGS %if %{pie} %ifarch s390 s390x sparc sparcv9 sparc64 CFLAGS="$CFLAGS -fPIC" @@ -543,18 +476,6 @@ fi popd %endif -%if %{pam_ssh_agent} -pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} -LDFLAGS="$SAVE_LDFLAGS" -%configure --with-selinux \ - --libexecdir=/%{_libdir}/security \ - --with-mantype=man \ - --without-ssl-engine \ - --without-openssl-header-check `# The check is broken` -%make_build -popd -%endif - %check OPENSSL_CONF=/dev/null %{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile @@ -614,12 +535,6 @@ rm -f $RPM_BUILD_ROOT/etc/profile.d/gnome-ssh-askpass.* perl -pi -e "s|$RPM_BUILD_ROOT||g" $RPM_BUILD_ROOT%{_mandir}/man*/* -%if %{pam_ssh_agent} -pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} -%make_install -popd -%endif - install -m 755 -d $RPM_BUILD_ROOT%{_libdir}/sshtest/ install -m 755 regress/misc/sk-dummy/sk-dummy.so $RPM_BUILD_ROOT%{_libdir}/sshtest @@ -742,14 +657,11 @@ test -f %{sysconfig_anaconda} && \ %files sk-dummy %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so -%if %{pam_ssh_agent} -%files -n pam_ssh_agent_auth -%license pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}/OPENSSH_LICENSE -%attr(0755,root,root) %{_libdir}/security/pam_ssh_agent_auth.so -%attr(0644,root,root) %{_mandir}/man8/pam_ssh_agent_auth.8* -%endif - %changelog +* Mon Jan 27 2025 Dmitry Belyavskiy - 9.9p1-6 +- Remove pam-ssh-agent subcomponent + Resolves: rhbz#2338440 + * Fri Jan 17 2025 Fedora Release Engineering - 9.9p1-5.1 - Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild diff --git a/pam_ssh_agent-configure-c99.patch b/pam_ssh_agent-configure-c99.patch deleted file mode 100644 index bc40434..0000000 --- a/pam_ssh_agent-configure-c99.patch +++ /dev/null @@ -1,249 +0,0 @@ -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-rmheaders b/pam_ssh_agent-rmheaders deleted file mode 100644 index ab5899f..0000000 --- a/pam_ssh_agent-rmheaders +++ /dev/null @@ -1,36 +0,0 @@ -authfd.c -authfd.h -atomicio.c -atomicio.h -bufaux.c -bufbn.c -buffer.h -buffer.c -cleanup.c -cipher.h -compat.h -entropy.c -entropy.h -fatal.c -includes.h -kex.h -key.c -key.h -log.c -log.h -match.h -misc.c -misc.h -pathnames.h -platform.h -rsa.h -ssh-dss.c -ssh-rsa.c -ssh.h -ssh2.h -uidswap.c -uidswap.h -uuencode.c -uuencode.h -xmalloc.c -xmalloc.h diff --git a/pam_ssh_agent_auth-0.10.2-compat.patch b/pam_ssh_agent_auth-0.10.2-compat.patch deleted file mode 100644 index 0822b61..0000000 --- a/pam_ssh_agent_auth-0.10.2-compat.patch +++ /dev/null @@ -1,992 +0,0 @@ -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c 2020-09-23 10:52:16.424001475 +0200 -@@ -27,6 +27,7 @@ - * or implied, of Jamie Beverly. - */ - -+#include - #include - #include - #include -@@ -66,8 +67,8 @@ proc_pid_cmdline(char *** inargv) - case EOF: - case '\0': - if (len > 0) { -- argv = pamsshagentauth_xrealloc(argv, count + 1, sizeof(*argv)); -- argv[count] = pamsshagentauth_xcalloc(len + 1, sizeof(*argv[count])); -+ argv = xreallocarray(argv, count + 1, sizeof(*argv)); -+ argv[count] = xcalloc(len + 1, sizeof(*argv[count])); - strncpy(argv[count++], argbuf, len); - memset(argbuf, '\0', MAX_LEN_PER_CMDLINE_ARG + 1); - len = 0; -@@ -106,9 +107,9 @@ pamsshagentauth_free_command_line(char * - { - size_t i; - for (i = 0; i < n_args; i++) -- pamsshagentauth_xfree(argv[i]); -+ free(argv[i]); - -- pamsshagentauth_xfree(argv); -+ free(argv); - return; - } - -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h 2020-09-23 10:52:16.424001475 +0200 -@@ -30,8 +30,8 @@ - #include "openbsd-compat/sys-queue.h" - #include "xmalloc.h" - #include "log.h" --#include "buffer.h" --#include "key.h" -+#include "sshbuf.h" -+#include "sshkey.h" - #include "authfd.h" - #include - -@@ -41,7 +41,7 @@ typedef struct idlist Idlist; - struct identity { - TAILQ_ENTRY(identity) next; - AuthenticationConnection *ac; /* set if agent supports key */ -- Key *key; /* public/private key */ -+ struct sshkey *key; /* public/private key */ - char *filename; /* comment for agent-only keys */ - int tried; - int isprivate; /* key points to the private key */ -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c.psaa-compat 2020-09-23 10:52:16.421001434 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c 2020-09-23 10:52:16.424001475 +0200 -@@ -36,8 +36,8 @@ - #include "openbsd-compat/sys-queue.h" - #include "xmalloc.h" - #include "log.h" --#include "buffer.h" --#include "key.h" -+#include "sshbuf.h" -+#include "sshkey.h" - #include "authfd.h" - #include - #include -@@ -58,6 +58,8 @@ - #include "get_command_line.h" - extern char **environ; - -+#define PAM_SSH_AGENT_AUTH_REQUESTv1 101 -+ - /* - * Added by Jamie Beverly, ensure socket fd points to a socket owned by the user - * A cursory check is done, but to avoid race conditions, it is necessary -@@ -77,7 +79,7 @@ log_action(char ** action, size_t count) - if (count == 0) - return NULL; - -- buf = pamsshagentauth_xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf)); -+ buf = xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf)); - for (i = 0; i < count; i++) { - strcat(buf, (i > 0) ? " '" : "'"); - strncat(buf, action[i], MAX_LEN_PER_CMDLINE_ARG); -@@ -87,21 +89,25 @@ log_action(char ** action, size_t count) - } - - void --agent_action(Buffer *buf, char ** action, size_t count) -+agent_action(struct sshbuf **buf, char ** action, size_t count) - { - size_t i; -- pamsshagentauth_buffer_init(buf); -+ int r; - -- pamsshagentauth_buffer_put_int(buf, count); -+ if ((*buf = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); -+ if ((r = sshbuf_put_u32(*buf, count)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - - for (i = 0; i < count; i++) { -- pamsshagentauth_buffer_put_cstring(buf, action[i]); -+ if ((r = sshbuf_put_cstring(*buf, action[i])) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - } - } - - --void --pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user, -+static void -+pamsshagentauth_session_id2_gen(struct sshbuf ** session_id2, const char * user, - const char * ruser, const char * servicename) - { - u_char *cookie = NULL; -@@ -114,22 +120,23 @@ pamsshagentauth_session_id2_gen(Buffer * - char ** reported_argv = NULL; - size_t count = 0; - char * action_logbuf = NULL; -- Buffer action_agentbuf; -+ struct sshbuf *action_agentbuf = NULL; - uint8_t free_logbuf = 0; - char * retc; - int32_t reti; -+ int r; - -- rnd = pamsshagentauth_arc4random(); -+ rnd = arc4random(); - cookie_len = ((uint8_t) rnd); - while (cookie_len < 16) { - cookie_len += 16; /* Add 16 bytes to the size to ensure that while the length is random, the length is always reasonable; ticket #18 */ - } - -- cookie = pamsshagentauth_xcalloc(1,cookie_len); -+ cookie = xcalloc(1, cookie_len); - - for (i = 0; i < cookie_len; i++) { - if (i % 4 == 0) { -- rnd = pamsshagentauth_arc4random(); -+ rnd = arc4random(); - } - cookie[i] = (u_char) rnd; - rnd >>= 8; -@@ -144,7 +151,8 @@ pamsshagentauth_session_id2_gen(Buffer * - } - else { - action_logbuf = "unknown on this platform"; -- pamsshagentauth_buffer_init(&action_agentbuf); /* stays empty, means unavailable */ -+ if ((action_agentbuf = sshbuf_new()) == NULL) /* stays empty, means unavailable */ -+ fatal("%s: sshbuf_new failed", __func__); - } - - /* -@@ -161,35 +169,39 @@ pamsshagentauth_session_id2_gen(Buffer * - retc = getcwd(pwd, sizeof(pwd) - 1); - time(&ts); - -- pamsshagentauth_buffer_init(session_id2); -+ if ((*session_id2 = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); - -- pamsshagentauth_buffer_put_int(session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1); -- /* pamsshagentauth_debug3("cookie: %s", pamsshagentauth_tohex(cookie, cookie_len)); */ -- pamsshagentauth_buffer_put_string(session_id2, cookie, cookie_len); -- /* pamsshagentauth_debug3("user: %s", user); */ -- pamsshagentauth_buffer_put_cstring(session_id2, user); -- /* pamsshagentauth_debug3("ruser: %s", ruser); */ -- pamsshagentauth_buffer_put_cstring(session_id2, ruser); -- /* pamsshagentauth_debug3("servicename: %s", servicename); */ -- pamsshagentauth_buffer_put_cstring(session_id2, servicename); -- /* pamsshagentauth_debug3("pwd: %s", pwd); */ -- if(retc) -- pamsshagentauth_buffer_put_cstring(session_id2, pwd); -- else -- pamsshagentauth_buffer_put_cstring(session_id2, ""); -- /* pamsshagentauth_debug3("action: %s", action_logbuf); */ -- pamsshagentauth_buffer_put_string(session_id2, action_agentbuf.buf + action_agentbuf.offset, action_agentbuf.end - action_agentbuf.offset); -+ if ((r = sshbuf_put_u32(*session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1)) != 0 || -+ (r = sshbuf_put_string(*session_id2, cookie, cookie_len)) != 0 || -+ (r = sshbuf_put_cstring(*session_id2, user)) != 0 || -+ (r = sshbuf_put_cstring(*session_id2, ruser)) != 0 || -+ (r = sshbuf_put_cstring(*session_id2, servicename)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ if (retc) { -+ if ((r = sshbuf_put_cstring(*session_id2, pwd)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } else { -+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } -+ if ((r = sshbuf_put_stringb(*session_id2, action_agentbuf)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - if (free_logbuf) { -- pamsshagentauth_xfree(action_logbuf); -- pamsshagentauth_buffer_free(&action_agentbuf); -+ free(action_logbuf); -+ sshbuf_free(action_agentbuf); -+ } -+ /* debug3("hostname: %s", hostname); */ -+ if (reti >= 0) { -+ if ((r = sshbuf_put_cstring(*session_id2, hostname)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } else { -+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - } -- /* pamsshagentauth_debug3("hostname: %s", hostname); */ -- if(reti >= 0) -- pamsshagentauth_buffer_put_cstring(session_id2, hostname); -- else -- pamsshagentauth_buffer_put_cstring(session_id2, ""); -- /* pamsshagentauth_debug3("ts: %ld", ts); */ -- pamsshagentauth_buffer_put_int64(session_id2, (uint64_t) ts); -+ /* debug3("ts: %ld", ts); */ -+ if ((r = sshbuf_put_u64(*session_id2, (uint64_t) ts)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - - free(cookie); - return; -@@ -278,7 +290,8 @@ ssh_get_authentication_connection_for_ui - - auth = xmalloc(sizeof(*auth)); - auth->fd = sock; -- buffer_init(&auth->identities); -+ if ((auth->identities = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); - auth->howmany = 0; - - return auth; -@@ -287,9 +300,9 @@ ssh_get_authentication_connection_for_ui - int - pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename) - { -- Buffer session_id2 = { 0 }; -+ struct sshbuf *session_id2 = NULL; - Identity *id; -- Key *key; -+ struct sshkey *key; - AuthenticationConnection *ac; - char *comment; - uint8_t retval = 0; -@@ -299,31 +312,30 @@ pamsshagentauth_find_authorized_keys(con - pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); - - if ((ac = ssh_get_authentication_connection_for_uid(uid))) { -- pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); -+ verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); - for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) - { - if(key != NULL) { -- id = pamsshagentauth_xcalloc(1, sizeof(*id)); -+ id = xcalloc(1, sizeof(*id)); - id->key = key; - id->filename = comment; - id->ac = ac; -- if(userauth_pubkey_from_id(ruser, id, &session_id2)) { -+ if(userauth_pubkey_from_id(ruser, id, session_id2)) { - retval = 1; - } -- pamsshagentauth_xfree(id->filename); -- pamsshagentauth_key_free(id->key); -- pamsshagentauth_xfree(id); -+ free(id->filename); -+ key_free(id->key); -+ free(id); - if(retval == 1) - break; - } - } -- pamsshagentauth_buffer_free(&session_id2); -+ sshbuf_free(session_id2); - ssh_close_authentication_connection(ac); - } - else { -- pamsshagentauth_verbose("No ssh-agent could be contacted"); -+ verbose("No ssh-agent could be contacted"); - } -- /* pamsshagentauth_xfree(session_id2); */ - EVP_cleanup(); - return retval; - } -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c.psaa-compat 2020-09-23 10:52:16.423001461 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c 2020-09-23 10:53:10.631727657 +0200 -@@ -106,7 +106,7 @@ pam_sm_authenticate(pam_handle_t * pamh, - * a patch 8-) - */ - #if ! HAVE___PROGNAME || HAVE_BUNDLE -- __progname = pamsshagentauth_xstrdup(servicename); -+ __progname = xstrdup(servicename); - #endif - - for(i = argc, argv_ptr = (char **) argv; i > 0; ++argv_ptr, i--) { -@@ -132,11 +132,11 @@ pam_sm_authenticate(pam_handle_t * pamh, - #endif - } - -- pamsshagentauth_log_init(__progname, log_lvl, facility, getenv("PAM_SSH_AGENT_AUTH_DEBUG") ? 1 : 0); -+ log_init(__progname, log_lvl, facility, getenv("PAM_SSH_AGENT_AUTH_DEBUG") ? 1 : 0); - pam_get_item(pamh, PAM_USER, (void *) &user); - pam_get_item(pamh, PAM_RUSER, (void *) &ruser_ptr); - -- pamsshagentauth_verbose("Beginning pam_ssh_agent_auth for user %s", user); -+ verbose("Beginning pam_ssh_agent_auth for user %s", user); - - if(ruser_ptr) { - strncpy(ruser, ruser_ptr, sizeof(ruser) - 1); -@@ -151,12 +151,12 @@ pam_sm_authenticate(pam_handle_t * pamh, - #ifdef ENABLE_SUDO_HACK - if( (strlen(sudo_service_name) > 0) && strncasecmp(servicename, sudo_service_name, sizeof(sudo_service_name) - 1) == 0 && getenv("SUDO_USER") ) { - strncpy(ruser, getenv("SUDO_USER"), sizeof(ruser) - 1 ); -- pamsshagentauth_verbose( "Using environment variable SUDO_USER (%s)", ruser ); -+ verbose( "Using environment variable SUDO_USER (%s)", ruser ); - } else - #endif - { - if( ! getpwuid(getuid()) ) { -- pamsshagentauth_verbose("Unable to getpwuid(getuid())"); -+ verbose("Unable to getpwuid(getuid())"); - goto cleanexit; - } - strncpy(ruser, getpwuid(getuid())->pw_name, sizeof(ruser) - 1); -@@ -165,11 +165,11 @@ pam_sm_authenticate(pam_handle_t * pamh, - - /* Might as well explicitely confirm the user exists here */ - if(! getpwnam(ruser) ) { -- pamsshagentauth_verbose("getpwnam(%s) failed, bailing out", ruser); -+ verbose("getpwnam(%s) failed, bailing out", ruser); - goto cleanexit; - } - if( ! getpwnam(user) ) { -- pamsshagentauth_verbose("getpwnam(%s) failed, bailing out", user); -+ verbose("getpwnam(%s) failed, bailing out", user); - goto cleanexit; - } - -@@ -179,8 +179,8 @@ pam_sm_authenticate(pam_handle_t * pamh, - */ - parse_authorized_key_file(user, authorized_keys_file_input); - } else { -- pamsshagentauth_verbose("Using default file=/etc/security/authorized_keys"); -- authorized_keys_file = pamsshagentauth_xstrdup("/etc/security/authorized_keys"); -+ verbose("Using default file=/etc/security/authorized_keys"); -+ authorized_keys_file = xstrdup("/etc/security/authorized_keys"); - } - - /* -@@ -189,7 +189,7 @@ pam_sm_authenticate(pam_handle_t * pamh, - */ - - if(user && strlen(ruser) > 0) { -- pamsshagentauth_verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file); -+ verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file); - - /* - * Attempt to read data from the sshd if we're being called as an auth agent. -@@ -197,10 +197,10 @@ pam_sm_authenticate(pam_handle_t * pamh, - const char* ssh_user_auth = pam_getenv(pamh, "SSH_AUTH_INFO_0"); - int sshd_service = strncasecmp(servicename, sshd_service_name, sizeof(sshd_service_name) - 1); - if (sshd_service == 0 && ssh_user_auth != NULL) { -- pamsshagentauth_verbose("Got SSH_AUTH_INFO_0: `%.20s...'", ssh_user_auth); -+ verbose("Got SSH_AUTH_INFO_0: `%.20s...'", ssh_user_auth); - if (userauth_pubkey_from_pam(ruser, ssh_user_auth) > 0) { - retval = PAM_SUCCESS; -- pamsshagentauth_logit("Authenticated (sshd): `%s' as `%s' using %s", ruser, user, authorized_keys_file); -+ logit("Authenticated (sshd): `%s' as `%s' using %s", ruser, user, authorized_keys_file); - goto cleanexit; - } - } -@@ -208,13 +208,13 @@ pam_sm_authenticate(pam_handle_t * pamh, - * this pw_uid is used to validate the SSH_AUTH_SOCK, and so must be the uid of the ruser invoking the program, not the target-user - */ - if(pamsshagentauth_find_authorized_keys(user, ruser, servicename)) { /* getpwnam(ruser)->pw_uid)) { */ -- pamsshagentauth_logit("Authenticated (agent): `%s' as `%s' using %s", ruser, user, authorized_keys_file); -+ logit("Authenticated (agent): `%s' as `%s' using %s", ruser, user, authorized_keys_file); - retval = PAM_SUCCESS; - } else { -- pamsshagentauth_logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file); -+ logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file); - } - } else { -- pamsshagentauth_logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" ); -+ logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" ); - } - - cleanexit: -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c 2020-09-23 10:52:16.424001475 +0200 -@@ -66,8 +66,8 @@ - #include "xmalloc.h" - #include "match.h" - #include "log.h" --#include "buffer.h" --#include "key.h" -+#include "sshbuf.h" -+#include "sshkey.h" - #include "misc.h" - - #include "xmalloc.h" -@@ -77,7 +77,6 @@ - #include "pathnames.h" - #include "secure_filename.h" - --#include "identity.h" - #include "pam_user_key_allowed2.h" - - extern char *authorized_keys_file; -@@ -117,12 +116,12 @@ parse_authorized_key_file(const char *us - } else { - slash_ptr = strchr(auth_keys_file_buf, '/'); - if(!slash_ptr) -- pamsshagentauth_fatal -+ fatal - ("cannot expand tilde in path without a `/'"); - - owner_uname_len = slash_ptr - auth_keys_file_buf - 1; - if(owner_uname_len > (sizeof(owner_uname) - 1)) -- pamsshagentauth_fatal("Username too long"); -+ fatal("Username too long"); - - strncat(owner_uname, auth_keys_file_buf + 1, owner_uname_len); - if(!authorized_keys_file_allowed_owner_uid) -@@ -130,11 +129,11 @@ parse_authorized_key_file(const char *us - getpwnam(owner_uname)->pw_uid; - } - authorized_keys_file = -- pamsshagentauth_tilde_expand_filename(auth_keys_file_buf, -+ tilde_expand_filename(auth_keys_file_buf, - authorized_keys_file_allowed_owner_uid); - strncpy(auth_keys_file_buf, authorized_keys_file, - sizeof(auth_keys_file_buf) - 1); -- pamsshagentauth_xfree(authorized_keys_file) /* when we -+ free(authorized_keys_file) /* when we - percent_expand - later, we'd step - on this, so free -@@ -150,13 +149,13 @@ parse_authorized_key_file(const char *us - strncat(hostname, fqdn, strcspn(fqdn, ".")); - #endif - authorized_keys_file = -- pamsshagentauth_percent_expand(auth_keys_file_buf, "h", -+ percent_expand(auth_keys_file_buf, "h", - getpwnam(user)->pw_dir, "H", hostname, - "f", fqdn, "u", user, NULL); - } - - int --pam_user_key_allowed(const char *ruser, Key * key) -+pam_user_key_allowed(const char *ruser, struct sshkey * key) - { - return - pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h 2020-09-23 10:52:16.424001475 +0200 -@@ -32,7 +32,7 @@ - #define _PAM_USER_KEY_ALLOWED_H - - #include "identity.h" --int pam_user_key_allowed(const char *, Key *); -+int pam_user_key_allowed(const char *, struct sshkey *); - void parse_authorized_key_file(const char *, const char *); - - #endif -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c 2020-09-23 10:52:16.424001475 +0200 -@@ -45,44 +45,46 @@ - #include "xmalloc.h" - #include "ssh.h" - #include "ssh2.h" --#include "buffer.h" -+#include "sshbuf.h" - #include "log.h" - #include "compat.h" --#include "key.h" -+#include "digest.h" -+#include "sshkey.h" - #include "pathnames.h" - #include "misc.h" - #include "secure_filename.h" - #include "uidswap.h" -- --#include "identity.h" -+#include - - /* return 1 if user allows given key */ - /* Modified slightly from original found in auth2-pubkey.c */ - static int --pamsshagentauth_check_authkeys_file(FILE * f, char *file, Key * key) -+pamsshagentauth_check_authkeys_file(FILE * f, char *file, struct sshkey * key) - { -- char line[SSH_MAX_PUBKEY_BYTES]; -+ char *line = NULL; - int found_key = 0; - u_long linenum = 0; -- Key *found; -+ struct sshkey *found; - char *fp; -+ size_t linesize = 0; - - found_key = 0; -- found = pamsshagentauth_key_new(key->type); -+ found = sshkey_new(key->type); - -- while(read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) { -+ while ((getline(&line, &linesize, f)) != -1) { - char *cp = NULL; /* *key_options = NULL; */ - -+ linenum++; - /* Skip leading whitespace, empty and comment lines. */ - for(cp = line; *cp == ' ' || *cp == '\t'; cp++); - if(!*cp || *cp == '\n' || *cp == '#') - continue; - -- if(pamsshagentauth_key_read(found, &cp) != 1) { -+ if (sshkey_read(found, &cp) != 0) { - /* no key? check if there are options for this key */ - int quoted = 0; - -- pamsshagentauth_verbose("user_key_allowed: check options: '%s'", cp); -+ verbose("user_key_allowed: check options: '%s'", cp); - /* key_options = cp; */ - for(; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) { - if(*cp == '\\' && cp[1] == '"') -@@ -92,26 +94,27 @@ pamsshagentauth_check_authkeys_file(FILE - } - /* Skip remaining whitespace. */ - for(; *cp == ' ' || *cp == '\t'; cp++); -- if(pamsshagentauth_key_read(found, &cp) != 1) { -- pamsshagentauth_verbose("user_key_allowed: advance: '%s'", cp); -+ if(sshkey_read(found, &cp) != 0) { -+ verbose("user_key_allowed: advance: '%s'", cp); - /* still no key? advance to next line */ - continue; - } - } -- if(pamsshagentauth_key_equal(found, key)) { -+ if(sshkey_equal(found, key)) { - found_key = 1; -- pamsshagentauth_logit("matching key found: file/command %s, line %lu", file, -+ logit("matching key found: file/command %s, line %lu", file, - linenum); -- fp = pamsshagentauth_key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX); -- pamsshagentauth_logit("Found matching %s key: %s", -- pamsshagentauth_key_type(found), fp); -- pamsshagentauth_xfree(fp); -+ fp = sshkey_fingerprint(found, SSH_DIGEST_SHA256, SSH_FP_BASE64); -+ logit("Found matching %s key: %s", -+ sshkey_type(found), fp); -+ free(fp); - break; - } - } -- pamsshagentauth_key_free(found); -+ free(line); -+ sshkey_free(found); - if(!found_key) -- pamsshagentauth_verbose("key not found"); -+ verbose("key not found"); - return found_key; - } - -@@ -120,19 +123,19 @@ pamsshagentauth_check_authkeys_file(FILE - * returns 1 if the key is allowed or 0 otherwise. - */ - int --pamsshagentauth_user_key_allowed2(struct passwd *pw, Key * key, char *file) -+pamsshagentauth_user_key_allowed2(struct passwd *pw, struct sshkey * key, char *file) - { - FILE *f; - int found_key = 0; - struct stat st; -- char buf[SSH_MAX_PUBKEY_BYTES]; -+ char buf[256]; - - /* Temporarily use the user's uid. */ -- pamsshagentauth_verbose("trying public key file %s", file); -+ verbose("trying public key file %s", file); - - /* Fail not so quietly if file does not exist */ - if(stat(file, &st) < 0) { -- pamsshagentauth_verbose("File not found: %s", file); -+ verbose("File not found: %s", file); - return 0; - } - -@@ -144,7 +147,7 @@ pamsshagentauth_user_key_allowed2(struct - - if(pamsshagentauth_secure_filename(f, file, pw, buf, sizeof(buf)) != 0) { - fclose(f); -- pamsshagentauth_logit("Authentication refused: %s", buf); -+ logit("Authentication refused: %s", buf); - return 0; - } - -@@ -160,7 +163,7 @@ pamsshagentauth_user_key_allowed2(struct - int - pamsshagentauth_user_key_command_allowed2(char *authorized_keys_command, - char *authorized_keys_command_user, -- struct passwd *user_pw, Key * key) -+ struct passwd *user_pw, struct sshkey * key) - { - FILE *f; - int ok, found_key = 0; -@@ -187,44 +190,44 @@ pamsshagentauth_user_key_command_allowed - else { - pw = getpwnam(authorized_keys_command_user); - if(pw == NULL) { -- pamsshagentauth_logerror("authorized_keys_command_user \"%s\" not found: %s", -+ error("authorized_keys_command_user \"%s\" not found: %s", - authorized_keys_command_user, strerror(errno)); - return 0; - } - } - -- pamsshagentauth_temporarily_use_uid(pw); -+ temporarily_use_uid(pw); - - if(stat(authorized_keys_command, &st) < 0) { -- pamsshagentauth_logerror -+ error - ("Could not stat AuthorizedKeysCommand \"%s\": %s", - authorized_keys_command, strerror(errno)); - goto out; - } - if(pamsshagentauth_auth_secure_path - (authorized_keys_command, &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) { -- pamsshagentauth_logerror("Unsafe AuthorizedKeysCommand: %s", errmsg); -+ error("Unsafe AuthorizedKeysCommand: %s", errmsg); - goto out; - } - - /* open the pipe and read the keys */ - if(pipe(p) != 0) { -- pamsshagentauth_logerror("%s: pipe: %s", __func__, strerror(errno)); -+ error("%s: pipe: %s", __func__, strerror(errno)); - goto out; - } - -- pamsshagentauth_debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"", -+ debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"", - authorized_keys_command, pw->pw_name, username); - - /* - * Don't want to call this in the child, where it can fatal() and - * run cleanup_exit() code. - */ -- pamsshagentauth_restore_uid(); -+ restore_uid(); - - switch ((pid = fork())) { - case -1: /* error */ -- pamsshagentauth_logerror("%s: fork: %s", __func__, strerror(errno)); -+ error("%s: fork: %s", __func__, strerror(errno)); - close(p[0]); - close(p[1]); - return 0; -@@ -234,13 +237,13 @@ pamsshagentauth_user_key_command_allowed - - /* do this before the setresuid so thta they can be logged */ - if((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) { -- pamsshagentauth_logerror("%s: open %s: %s", __func__, _PATH_DEVNULL, -+ error("%s: open %s: %s", __func__, _PATH_DEVNULL, - strerror(errno)); - _exit(1); - } - if(dup2(devnull, STDIN_FILENO) == -1 || dup2(p[1], STDOUT_FILENO) == -1 - || dup2(devnull, STDERR_FILENO) == -1) { -- pamsshagentauth_logerror("%s: dup2: %s", __func__, strerror(errno)); -+ error("%s: dup2: %s", __func__, strerror(errno)); - _exit(1); - } - #if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID) -@@ -248,7 +251,7 @@ pamsshagentauth_user_key_command_allowed - #else - if (setgid(pw->pw_gid) != 0 || setegid(pw->pw_gid) != 0) { - #endif -- pamsshagentauth_logerror("setresgid %u: %s", (u_int) pw->pw_gid, -+ error("setresgid %u: %s", (u_int) pw->pw_gid, - strerror(errno)); - _exit(1); - } -@@ -258,7 +261,7 @@ pamsshagentauth_user_key_command_allowed - #else - if (setuid(pw->pw_uid) != 0 || seteuid(pw->pw_uid) != 0) { - #endif -- pamsshagentauth_logerror("setresuid %u: %s", (u_int) pw->pw_uid, -+ error("setresuid %u: %s", (u_int) pw->pw_uid, - strerror(errno)); - _exit(1); - } -@@ -270,18 +273,18 @@ pamsshagentauth_user_key_command_allowed - - /* pretty sure this will barf because we are now suid, but since we - should't reach this anyway, I'll leave it here */ -- pamsshagentauth_logerror("AuthorizedKeysCommand %s exec failed: %s", -+ error("AuthorizedKeysCommand %s exec failed: %s", - authorized_keys_command, strerror(errno)); - _exit(127); - default: /* parent */ - break; - } - -- pamsshagentauth_temporarily_use_uid(pw); -+ temporarily_use_uid(pw); - - close(p[1]); - if((f = fdopen(p[0], "r")) == NULL) { -- pamsshagentauth_logerror("%s: fdopen: %s", __func__, strerror(errno)); -+ error("%s: fdopen: %s", __func__, strerror(errno)); - close(p[0]); - /* Don't leave zombie child */ - while(waitpid(pid, NULL, 0) == -1 && errno == EINTR); -@@ -292,22 +295,22 @@ pamsshagentauth_user_key_command_allowed - - while(waitpid(pid, &status, 0) == -1) { - if(errno != EINTR) { -- pamsshagentauth_logerror("%s: waitpid: %s", __func__, -+ error("%s: waitpid: %s", __func__, - strerror(errno)); - goto out; - } - } - if(WIFSIGNALED(status)) { -- pamsshagentauth_logerror("AuthorizedKeysCommand %s exited on signal %d", -+ error("AuthorizedKeysCommand %s exited on signal %d", - authorized_keys_command, WTERMSIG(status)); - goto out; - } else if(WEXITSTATUS(status) != 0) { -- pamsshagentauth_logerror("AuthorizedKeysCommand %s returned status %d", -+ error("AuthorizedKeysCommand %s returned status %d", - authorized_keys_command, WEXITSTATUS(status)); - goto out; - } - found_key = ok; - out: -- pamsshagentauth_restore_uid(); -+ restore_uid(); - return found_key; - } -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h 2020-09-23 10:52:16.424001475 +0200 -@@ -32,7 +32,7 @@ - #define _PAM_USER_KEY_ALLOWED_H - - #include "identity.h" --int pamsshagentauth_user_key_allowed2(struct passwd *, Key *, char *); --int pamsshagentauth_user_key_command_allowed2(char *, char *, struct passwd *, Key *); -+int pamsshagentauth_user_key_allowed2(struct passwd *, struct sshkey *, char *); -+int pamsshagentauth_user_key_command_allowed2(char *, char *, struct passwd *, struct sshkey *); - - #endif -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c 2020-09-23 10:52:16.424001475 +0200 -@@ -53,8 +53,8 @@ - #include "xmalloc.h" - #include "match.h" - #include "log.h" --#include "buffer.h" --#include "key.h" -+#include "sshbuf.h" -+#include "sshkey.h" - #include "misc.h" - - -@@ -80,7 +80,7 @@ pamsshagentauth_auth_secure_path(const c - int comparehome = 0; - struct stat st; - -- pamsshagentauth_verbose("auth_secure_filename: checking for uid: %u", uid); -+ verbose("auth_secure_filename: checking for uid: %u", uid); - - if (realpath(name, buf) == NULL) { - snprintf(err, errlen, "realpath %s failed: %s", name, -@@ -115,9 +115,9 @@ pamsshagentauth_auth_secure_path(const c - snprintf(err, errlen, "dirname() failed"); - return -1; - } -- pamsshagentauth_strlcpy(buf, cp, sizeof(buf)); -+ strlcpy(buf, cp, sizeof(buf)); - -- pamsshagentauth_verbose("secure_filename: checking '%s'", buf); -+ verbose("secure_filename: checking '%s'", buf); - if (stat(buf, &st) < 0 || - (st.st_uid != 0 && st.st_uid != uid) || - (st.st_mode & 022) != 0) { -@@ -128,7 +128,7 @@ pamsshagentauth_auth_secure_path(const c - - /* If are passed the homedir then we can stop */ - if (comparehome && strcmp(homedir, buf) == 0) { -- pamsshagentauth_verbose("secure_filename: terminating check at '%s'", -+ verbose("secure_filename: terminating check at '%s'", - buf); - break; - } -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c 2020-09-23 10:52:16.424001475 +0200 -@@ -37,10 +37,11 @@ - #include "xmalloc.h" - #include "ssh.h" - #include "ssh2.h" --#include "buffer.h" -+#include "sshbuf.h" - #include "log.h" - #include "compat.h" --#include "key.h" -+#include "sshkey.h" -+#include "ssherr.h" - #include "pathnames.h" - #include "misc.h" - #include "secure_filename.h" -@@ -48,54 +49,59 @@ - #include "identity.h" - #include "pam_user_authorized_keys.h" - -+#define SSH2_MSG_USERAUTH_TRUST_REQUEST 54 -+ - /* extern u_char *session_id2; - extern uint8_t session_id_len; - */ - - int --userauth_pubkey_from_id(const char *ruser, Identity * id, Buffer * session_id2) -+userauth_pubkey_from_id(const char *ruser, Identity * id, struct sshbuf * session_id2) - { -- Buffer b = { 0 }; -+ struct sshbuf *b = NULL; - char *pkalg = NULL; - u_char *pkblob = NULL, *sig = NULL; -- u_int blen = 0, slen = 0; -- int authenticated = 0; -+ size_t blen = 0, slen = 0; -+ int r, authenticated = 0; - -- pkalg = (char *) key_ssh_name(id->key); -+ pkalg = (char *) sshkey_ssh_name(id->key); - - /* first test if this key is even allowed */ - if(! pam_user_key_allowed(ruser, id->key)) -- goto user_auth_clean_exit; -+ goto user_auth_clean_exit_without_buffer; - -- if(pamsshagentauth_key_to_blob(id->key, &pkblob, &blen) == 0) -- goto user_auth_clean_exit; -+ if(sshkey_to_blob(id->key, &pkblob, &blen) != 0) -+ goto user_auth_clean_exit_without_buffer; - - /* construct packet to sign and test */ -- pamsshagentauth_buffer_init(&b); -+ if ((b = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); - -- pamsshagentauth_buffer_put_string(&b, session_id2->buf + session_id2->offset, session_id2->end - session_id2->offset); -- pamsshagentauth_buffer_put_char(&b, SSH2_MSG_USERAUTH_TRUST_REQUEST); -- pamsshagentauth_buffer_put_cstring(&b, ruser); -- pamsshagentauth_buffer_put_cstring(&b, "pam_ssh_agent_auth"); -- pamsshagentauth_buffer_put_cstring(&b, "publickey"); -- pamsshagentauth_buffer_put_char(&b, 1); -- pamsshagentauth_buffer_put_cstring(&b, pkalg); -- pamsshagentauth_buffer_put_string(&b, pkblob, blen); -+ if ((r = sshbuf_put_string(b, sshbuf_ptr(session_id2), sshbuf_len(session_id2))) != 0 || -+ (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_TRUST_REQUEST)) != 0 || -+ (r = sshbuf_put_cstring(b, ruser)) != 0 || -+ (r = sshbuf_put_cstring(b, "pam_ssh_agent_auth")) != 0 || -+ (r = sshbuf_put_cstring(b, "publickey")) != 0 || -+ (r = sshbuf_put_u8(b, 1)) != 0 || -+ (r = sshbuf_put_cstring(b, pkalg)) != 0 || -+ (r = sshbuf_put_string(b, pkblob, blen)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); - -- if(ssh_agent_sign(id->ac, id->key, &sig, &slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) != 0) -+ if (ssh_agent_sign(id->ac, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b)) != 0) - goto user_auth_clean_exit; - - /* test for correct signature */ -- if(pamsshagentauth_key_verify(id->key, sig, slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) == 1) -+ if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0, NULL) == 0) - authenticated = 1; - - user_auth_clean_exit: - /* if(&b != NULL) */ -- pamsshagentauth_buffer_free(&b); -+ sshbuf_free(b); -+ user_auth_clean_exit_without_buffer: - if(sig != NULL) -- pamsshagentauth_xfree(sig); -+ free(sig); - if(pkblob != NULL) -- pamsshagentauth_xfree(pkblob); -+ free(pkblob); - CRYPTO_cleanup_all_ex_data(); - return authenticated; - } -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h 2020-09-23 10:52:16.424001475 +0200 -@@ -31,7 +31,7 @@ - #ifndef _USERAUTH_PUBKEY_FROM_ID_H - #define _USERAUTH_PUBKEY_FROM_ID_H - --#include --int userauth_pubkey_from_id(const char *, Identity *, Buffer *); -+#include "identity.h" -+int userauth_pubkey_from_id(const char *, Identity *, struct sshbuf *); - - #endif -diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c 2020-09-23 10:52:16.424001475 +0200 -@@ -56,7 +56,7 @@ pamsshagentauth_uudecode(const char *src - /* and remove trailing whitespace because __b64_pton needs this */ - *p = '\0'; - len = pamsshagentauth___b64_pton(encoded, target, targsize); -- pamsshagentauth_xfree(encoded); -+ xfree(encoded); - return len; - } - -@@ -70,7 +70,7 @@ pamsshagentauth_dump_base64(FILE *fp, co - fprintf(fp, "dump_base64: len > 65536\n"); - return; - } -- buf = pamsshagentauth_xmalloc(2*len); -+ buf = malloc(2*len); - n = pamsshagentauth_uuencode(data, len, buf, 2*len); - for (i = 0; i < n; i++) { - fprintf(fp, "%c", buf[i]); -@@ -79,5 +79,5 @@ pamsshagentauth_dump_base64(FILE *fp, co - } - if (i % 70 != 69) - fprintf(fp, "\n"); -- pamsshagentauth_xfree(buf); -+ free(buf); - } ---- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_pam.c.compat 2020-09-23 11:32:30.783695267 +0200 -+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_pam.c 2020-09-23 11:33:21.383389036 +0200 -@@ -33,7 +33,8 @@ - #include - - #include "defines.h" --#include "key.h" -+#include -+#include "sshkey.h" - #include "log.h" - - #include "pam_user_authorized_keys.h" -@@ -42,28 +42,28 @@ - int authenticated = 0; - const char method[] = "publickey "; - -- char* ai = pamsshagentauth_xstrdup(ssh_auth_info); -+ char* ai = xstrdup(ssh_auth_info); - char* saveptr; - - char* auth_line = strtok_r(ai, "\n", &saveptr); - while (auth_line != NULL) { - if (strncmp(auth_line, method, sizeof(method) - 1) == 0) { - char* key_str = auth_line + sizeof(method) - 1; -- Key* key = pamsshagentauth_key_new(KEY_UNSPEC); -+ struct sshkey* key = sshkey_new(KEY_UNSPEC); - if (key == NULL) { - continue; - } -- int r = pamsshagentauth_key_read(key, &key_str); -+ int r = sshkey_read(key, &key_str); - if (r == 1) { - if (pam_user_key_allowed(ruser, key)) { - authenticated = 1; -- pamsshagentauth_key_free(key); -+ sshkey_free(key); - break; - } - } else { -- pamsshagentauth_verbose("Failed to create key for %s: %d", auth_line, r); -+ verbose("Failed to create key for %s: %d", auth_line, r); - } -- pamsshagentauth_key_free(key); -+ sshkey_free(key); - } - auth_line = strtok_r(NULL, "\n", &saveptr); - } diff --git a/pam_ssh_agent_auth-0.10.2-dereference.patch b/pam_ssh_agent_auth-0.10.2-dereference.patch deleted file mode 100644 index bf49c37..0000000 --- a/pam_ssh_agent_auth-0.10.2-dereference.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --git a/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c b/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c ---- a/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c -+++ b/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c -@@ -158,11 +158,12 @@ parse_authorized_key_file(const char *user, - int - pam_user_key_allowed(const char *ruser, struct sshkey * key) - { -+ struct passwd *pw; - return -- pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), -- key, authorized_keys_file) -- || pamsshagentauth_user_key_allowed2(getpwuid(0), key, -- authorized_keys_file) -+ ( (pw = getpwuid(authorized_keys_file_allowed_owner_uid)) && -+ pamsshagentauth_user_key_allowed2(pw, key, authorized_keys_file)) -+ || ((pw = getpwuid(0)) && -+ pamsshagentauth_user_key_allowed2(pw, key, authorized_keys_file)) - || pamsshagentauth_user_key_command_allowed2(authorized_keys_command, - authorized_keys_command_user, - getpwnam(ruser), key); diff --git a/pam_ssh_agent_auth-0.10.3-seteuid.patch b/pam_ssh_agent_auth-0.10.3-seteuid.patch deleted file mode 100644 index be1f8e5..0000000 --- a/pam_ssh_agent_auth-0.10.3-seteuid.patch +++ /dev/null @@ -1,37 +0,0 @@ -diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-seteuid openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c ---- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-seteuid 2017-02-07 15:41:53.172334151 +0100 -+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-02-07 15:41:53.174334149 +0100 -@@ -238,17 +238,26 @@ ssh_get_authentication_socket_for_uid(ui - } - - errno = 0; -- seteuid(uid); /* To ensure a race condition is not used to circumvent the stat -- above, we will temporarily drop UID to the caller */ -- if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) { -+ /* To ensure a race condition is not used to circumvent the stat -+ above, we will temporarily drop UID to the caller */ -+ if (seteuid(uid) == -1) { - close(sock); -- if(errno == EACCES) -- fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid); -+ error("seteuid(%lu) failed with error: %s", -+ (unsigned long) uid, strerror(errno)); - return -1; - } -+ if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) { -+ close(sock); -+ sock = -1; -+ if(errno == EACCES) -+ fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid); -+ } - -- seteuid(0); /* we now continue the regularly scheduled programming */ -- -+ /* we now continue the regularly scheduled programming */ -+ if (0 != seteuid(0)) { -+ fatal("setuid(0) failed with error: %s", strerror(errno)); -+ return -1; -+ } - return sock; - } - diff --git a/pam_ssh_agent_auth-0.10.4-rsasha2.patch b/pam_ssh_agent_auth-0.10.4-rsasha2.patch deleted file mode 100644 index c8815bb..0000000 --- a/pam_ssh_agent_auth-0.10.4-rsasha2.patch +++ /dev/null @@ -1,19 +0,0 @@ -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/pam_ssh_agent_auth-0.9.2-visibility.patch b/pam_ssh_agent_auth-0.9.2-visibility.patch deleted file mode 100644 index aea068d..0000000 --- a/pam_ssh_agent_auth-0.9.2-visibility.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visibility openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c ---- openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visibility 2014-03-31 19:35:17.000000000 +0200 -+++ openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c 2016-01-22 15:22:40.984469774 +0100 -@@ -72,7 +72,7 @@ char *__progname; - extern char *__progname; - #endif - --PAM_EXTERN int -+PAM_EXTERN int __attribute__ ((visibility ("default"))) - pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv) - { - char **argv_ptr; -@@ -214,7 +214,7 @@ cleanexit: - } - - --PAM_EXTERN int -+PAM_EXTERN int __attribute__ ((visibility ("default"))) - pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv) - { - UNUSED(pamh); diff --git a/pam_ssh_agent_auth-0.9.3-agent_structure.patch b/pam_ssh_agent_auth-0.9.3-agent_structure.patch deleted file mode 100644 index 1f2c02c..0000000 --- a/pam_ssh_agent_auth-0.9.3-agent_structure.patch +++ /dev/null @@ -1,96 +0,0 @@ -diff -up openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/identity.h ---- openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-agent 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/identity.h 2017-09-27 14:25:49.421739027 +0200 -@@ -38,6 +38,12 @@ - typedef struct identity Identity; - typedef struct idlist Idlist; - -+typedef struct { -+ int fd; -+ struct sshbuf *identities; -+ int howmany; -+} AuthenticationConnection; -+ - struct identity { - TAILQ_ENTRY(identity) next; - AuthenticationConnection *ac; /* set if agent supports key */ -diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c ---- openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-agent 2017-09-27 14:25:49.420739021 +0200 -+++ openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-09-27 14:25:49.421739027 +0200 -@@ -39,6 +39,7 @@ - #include "sshbuf.h" - #include "sshkey.h" - #include "authfd.h" -+#include "ssherr.h" - #include - #include - #include "ssh2.h" -@@ -291,36 +292,43 @@ pamsshagentauth_find_authorized_keys(con - { - struct sshbuf *session_id2 = NULL; - Identity *id; -- struct sshkey *key; - AuthenticationConnection *ac; -- char *comment; - uint8_t retval = 0; - uid_t uid = getpwnam(ruser)->pw_uid; -+ struct ssh_identitylist *idlist; -+ int r; -+ unsigned int i; - - OpenSSL_add_all_digests(); - pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); - - if ((ac = ssh_get_authentication_connection_for_uid(uid))) { - verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); -- for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) -- { -- if(key != NULL) { -+ if ((r = ssh_fetch_identitylist(ac->fd, &idlist)) != 0) { -+ if (r != SSH_ERR_AGENT_NO_IDENTITIES) -+ fprintf(stderr, "error fetching identities for " -+ "protocol %d: %s\n", 2, ssh_err(r)); -+ } else { -+ for (i = 0; i < idlist->nkeys; i++) -+ { -+ if (idlist->keys[i] != NULL) { - id = xcalloc(1, sizeof(*id)); -- id->key = key; -- id->filename = comment; -+ id->key = idlist->keys[i]; -+ id->filename = idlist->comments[i]; - id->ac = ac; - if(userauth_pubkey_from_id(ruser, id, session_id2)) { - retval = 1; - } -- free(id->filename); -- key_free(id->key); - free(id); - if(retval == 1) - break; -- } -- } -+ } -+ } -- sshbuf_free(session_id2); -- ssh_close_authentication_connection(ac); -+ sshbuf_free(session_id2); -+ ssh_free_identitylist(idlist); -+ } -+ ssh_close_authentication_socket(ac->fd); -+ free(ac); - } - else { - verbose("No ssh-agent could be contacted"); -diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c ---- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-agent 2017-09-27 14:25:49.420739021 +0200 -+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c 2017-09-27 14:25:49.422739032 +0200 -@@ -84,7 +85,7 @@ 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, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b)) != 0) -+ 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 */ diff --git a/pam_ssh_agent_auth-0.9.3-build.patch b/pam_ssh_agent_auth-0.9.3-build.patch deleted file mode 100644 index 4018c4d..0000000 --- a/pam_ssh_agent_auth-0.9.3-build.patch +++ /dev/null @@ -1,198 +0,0 @@ -diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c ---- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build 2016-11-13 04:24:32.000000000 +0100 -+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-02-07 14:29:41.626116675 +0100 -@@ -43,12 +43,31 @@ - #include - #include "ssh2.h" - #include "misc.h" -+#include "ssh.h" -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include - - #include "userauth_pubkey_from_id.h" - #include "identity.h" - #include "get_command_line.h" - extern char **environ; - -+/* -+ * Added by Jamie Beverly, ensure socket fd points to a socket owned by the user -+ * A cursory check is done, but to avoid race conditions, it is necessary -+ * to drop effective UID when connecting to the socket. -+ * -+ * If the cause of error is EACCES, because we verified we would not have that -+ * problem initially, we can safely assume that somebody is attempting to find a -+ * race condition; so a more "direct" log message is generated. -+ */ -+ - static char * - log_action(char ** action, size_t count) - { -@@ -85,7 +104,7 @@ void - pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user, - const char * ruser, const char * servicename) - { -- char *cookie = NULL; -+ u_char *cookie = NULL; - uint8_t i = 0; - uint32_t rnd = 0; - uint8_t cookie_len; -@@ -112,7 +131,7 @@ pamsshagentauth_session_id2_gen(Buffer * - if (i % 4 == 0) { - rnd = pamsshagentauth_arc4random(); - } -- cookie[i] = (char) rnd; -+ cookie[i] = (u_char) rnd; - rnd >>= 8; - } - -@@ -177,6 +196,86 @@ pamsshagentauth_session_id2_gen(Buffer * - } - - int -+ssh_get_authentication_socket_for_uid(uid_t uid) -+{ -+ const char *authsocket; -+ int sock; -+ struct sockaddr_un sunaddr; -+ struct stat sock_st; -+ -+ authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); -+ if (!authsocket) -+ return -1; -+ -+ /* Advisory only; seteuid ensures no race condition; but will only log if we see EACCES */ -+ if( stat(authsocket,&sock_st) == 0) { -+ if(uid != 0 && sock_st.st_uid != uid) { -+ fatal("uid %lu attempted to open an agent socket owned by uid %lu", (unsigned long) uid, (unsigned long) sock_st.st_uid); -+ return -1; -+ } -+ } -+ -+ /* -+ * Ensures that the EACCES tested for below can _only_ happen if somebody -+ * is attempting to race the stat above to bypass authentication. -+ */ -+ if( (sock_st.st_mode & S_IWUSR) != S_IWUSR || (sock_st.st_mode & S_IRUSR) != S_IRUSR) { -+ error("ssh-agent socket has incorrect permissions for owner"); -+ return -1; -+ } -+ -+ sunaddr.sun_family = AF_UNIX; -+ strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); -+ -+ sock = socket(AF_UNIX, SOCK_STREAM, 0); -+ if (sock < 0) -+ return -1; -+ -+ /* close on exec */ -+ if (fcntl(sock, F_SETFD, 1) == -1) { -+ close(sock); -+ return -1; -+ } -+ -+ errno = 0; -+ seteuid(uid); /* To ensure a race condition is not used to circumvent the stat -+ above, we will temporarily drop UID to the caller */ -+ if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) { -+ close(sock); -+ if(errno == EACCES) -+ fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid); -+ return -1; -+ } -+ -+ seteuid(0); /* we now continue the regularly scheduled programming */ -+ -+ return sock; -+} -+ -+AuthenticationConnection * -+ssh_get_authentication_connection_for_uid(uid_t uid) -+{ -+ AuthenticationConnection *auth; -+ int sock; -+ -+ sock = ssh_get_authentication_socket_for_uid(uid); -+ -+ /* -+ * Fail if we couldn't obtain a connection. This happens if we -+ * exited due to a timeout. -+ */ -+ if (sock < 0) -+ return NULL; -+ -+ auth = xmalloc(sizeof(*auth)); -+ auth->fd = sock; -+ buffer_init(&auth->identities); -+ auth->howmany = 0; -+ -+ return auth; -+} -+ -+int - pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename) - { - Buffer session_id2 = { 0 }; -@@ -190,7 +289,7 @@ pamsshagentauth_find_authorized_keys(con - OpenSSL_add_all_digests(); - pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); - -- if ((ac = ssh_get_authentication_connection(uid))) { -+ if ((ac = ssh_get_authentication_connection_for_uid(uid))) { - pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); - for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2)) - { -diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in ---- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build 2016-11-13 04:24:32.000000000 +0100 -+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in 2017-02-07 14:40:14.407566921 +0100 -@@ -52,7 +52,7 @@ PATHS= - CC=@CC@ - LD=@LD@ - CFLAGS=@CFLAGS@ --CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ -+CPPFLAGS=-I.. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ - LIBS=@LIBS@ - AR=@AR@ - AWK=@AWK@ -@@ -61,8 +61,8 @@ INSTALL=@INSTALL@ - PERL=@PERL@ - SED=@SED@ - ENT=@ENT@ --LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ --LDFLAGS_SHARED = @LDFLAGS_SHARED@ -+LDFLAGS=-L.. -L../openbsd-compat/ @LDFLAGS@ -+LDFLAGS_SHARED =-Wl,-z,defs @LDFLAGS_SHARED@ - EXEEXT=@EXEEXT@ - - INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ -@@ -74,7 +74,7 @@ SSHOBJS=xmalloc.o atomicio.o authfd.o bu - - ED25519OBJS=ed25519-donna/ed25519.o - --PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o userauth_pubkey_from_pam.o -+PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o userauth_pubkey_from_pam.o secure_filename.o - - - MANPAGES_IN = pam_ssh_agent_auth.pod -@@ -94,13 +94,13 @@ $(PAM_MODULES): Makefile.in config.h - .c.o: - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ - --LIBCOMPAT=openbsd-compat/libopenbsd-compat.a -+LIBCOMPAT=../openbsd-compat/libopenbsd-compat.a - $(LIBCOMPAT): always - (cd openbsd-compat && $(MAKE)) - always: - --pam_ssh_agent_auth.so: $(LIBCOMPAT) $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o -- $(LD) $(LDFLAGS_SHARED) -o $@ $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lopenbsd-compat pam_ssh_agent_auth.o $(LIBS) -lpam -+pam_ssh_agent_auth.so: $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o ../uidswap.o ../ssh-sk-client.o -+ $(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) ../ssh-sk-client.o $(LDFLAGS) -lssh -lopenbsd-compat pam_ssh_agent_auth.o ../uidswap.o $(LIBS) -lpam - - $(MANPAGES): $(MANPAGES_IN) - pod2man --section=8 --release=v0.10.3 --name=pam_ssh_agent_auth --official --center "PAM" pam_ssh_agent_auth.pod > pam_ssh_agent_auth.8 diff --git a/sources b/sources index b273b63..e88b6d9 100644 --- a/sources +++ b/sources @@ -1,4 +1,3 @@ SHA512 (openssh-9.9p1.tar.gz) = 3cc0ed97f3e29ecbd882eca79239f02eb5a1606fce4f3119ddc3c5e86128aa3ff12dc85000879fccc87b60e7d651cfe37376607ac66075fede2118deaa685d6d SHA512 (openssh-9.9p1.tar.gz.asc) = 916e975c54eb68c0b2f0b0006522b241cbe54c4caa88d31537a6278490c93d9d732c2ab3a080ac084bf75cbdd5402901ec68583cbe7c7cde4a8e40e7a8b78c28 -SHA512 (pam_ssh_agent_auth-0.10.4.tar.gz) = caccf72174d15e43f4c86a459ac6448682e62116557cf1e1e828955f3d1731595b238df42adec57860e7f341e92daf5d8285020bcb5018f3b8a5145aa32ee1c2 SHA512 (gpgkey-736060BA.gpg) = df44f3fdbcd1d596705348c7f5aed3f738c5f626a55955e0642f7c6c082995cf36a1b1891bb41b8715cb2aff34fef1c877e0eff0d3507dd00a055ba695757a21 From 18a4ac4c5c896df8d2367bfbd5444a8ed7ba6ff3 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 27 Jan 2025 13:42:31 +0100 Subject: [PATCH 55/80] Fix regression of Match directive processing Resolves: rhbz#2341769 --- openssh-9.9p1-match-regression.patch | 463 +++++++++++++++++++++++++++ 1 file changed, 463 insertions(+) create mode 100644 openssh-9.9p1-match-regression.patch diff --git a/openssh-9.9p1-match-regression.patch b/openssh-9.9p1-match-regression.patch new file mode 100644 index 0000000..d724401 --- /dev/null +++ b/openssh-9.9p1-match-regression.patch @@ -0,0 +1,463 @@ +diff --git a/misc.c b/misc.c +index afdf5142..1b4b55c5 100644 +--- a/misc.c ++++ b/misc.c +@@ -107,6 +107,27 @@ rtrim(char *s) + } + } + ++/* ++ * returns pointer to character after 'prefix' in 's' or otherwise NULL ++ * if the prefix is not present. ++ */ ++const char * ++strprefix(const char *s, const char *prefix, int ignorecase) ++{ ++ size_t prefixlen; ++ ++ if ((prefixlen = strlen(prefix)) == 0) ++ return s; ++ if (ignorecase) { ++ if (strncasecmp(s, prefix, prefixlen) != 0) ++ return NULL; ++ } else { ++ if (strncmp(s, prefix, prefixlen) != 0) ++ return NULL; ++ } ++ return s + prefixlen; ++} ++ + /* set/unset filedescriptor to non-blocking */ + int + set_nonblock(int fd) +diff --git a/misc.h b/misc.h +index 11340389..efecdf1a 100644 +--- a/misc.h ++++ b/misc.h +@@ -56,6 +56,7 @@ struct ForwardOptions { + char *chop(char *); + void rtrim(char *); + void skip_space(char **); ++const char *strprefix(const char *, const char *, int); + char *strdelim(char **); + char *strdelimw(char **); + int set_nonblock(int); +diff --git a/readconf.c b/readconf.c +index 3d9cc6db..9f559269 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -710,7 +710,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, + struct passwd *pw, const char *host_arg, const char *original_host, + int final_pass, int *want_final_pass, const char *filename, int linenum) + { +- char *arg, *oattrib, *attrib, *cmd, *host, *criteria; ++ char *arg, *oattrib = NULL, *attrib = NULL, *cmd, *host, *criteria; + const char *ruser; + int r, this_result, result = 1, attributes = 0, negate; + +@@ -731,7 +731,8 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, + + debug2("checking match for '%s' host %s originally %s", + full_line, host, original_host); +- while ((oattrib = attrib = argv_next(acp, avp)) != NULL) { ++ while ((attrib = argv_next(acp, avp)) != NULL) { ++ attrib = oattrib = xstrdup(attrib); + /* Terminate on comment */ + if (*attrib == '#') { + argv_consume(acp); +@@ -777,9 +778,23 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, + this_result ? "" : "not ", oattrib); + continue; + } ++ ++ /* Keep this list in sync with below */ ++ if (strprefix(attrib, "host=", 1) != NULL || ++ strprefix(attrib, "originalhost=", 1) != NULL || ++ strprefix(attrib, "user=", 1) != NULL || ++ strprefix(attrib, "localuser=", 1) != NULL || ++ strprefix(attrib, "localnetwork=", 1) != NULL || ++ strprefix(attrib, "tagged=", 1) != NULL || ++ strprefix(attrib, "exec=", 1) != NULL) { ++ arg = strchr(attrib, '='); ++ *(arg++) = '\0'; ++ } else { ++ arg = argv_next(acp, avp); ++ } ++ + /* All other criteria require an argument */ +- if ((arg = argv_next(acp, avp)) == NULL || +- *arg == '\0' || *arg == '#') { ++ if (arg == NULL || *arg == '\0' || *arg == '#') { + error("Missing Match criteria for %s", attrib); + result = -1; + goto out; +@@ -856,6 +871,8 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, + criteria == NULL ? "" : criteria, + criteria == NULL ? "" : "\""); + free(criteria); ++ free(oattrib); ++ oattrib = attrib = NULL; + } + if (attributes == 0) { + error("One or more attributes required for Match"); +@@ -865,6 +882,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, + out: + if (result != -1) + debug2("match %sfound", result ? "" : "not "); ++ free(oattrib); + free(host); + return result; + } +diff --git a/servconf.c b/servconf.c +index 89b8413e..dd774f46 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -1,4 +1,4 @@ +-/* $OpenBSD: servconf.c,v 1.418 2024/09/15 03:09:44 djm Exp $ */ ++/* $OpenBSD: servconf.c,v 1.419 2024/09/25 01:24:04 djm Exp $ */ + /* + * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland + * All rights reserved +@@ -1033,7 +1033,7 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, + int line, struct connection_info *ci) + { + int result = 1, attributes = 0, port; +- char *arg, *attrib; ++ char *arg, *attrib = NULL, *oattrib; + + if (ci == NULL) + debug3("checking syntax for 'Match %s'", full_line); +@@ -1047,7 +1047,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, + ci->laddress ? ci->laddress : "(null)", ci->lport); + } + +- while ((attrib = argv_next(acp, avp)) != NULL) { ++ while ((oattrib = argv_next(acp, avp)) != NULL) { ++ attrib = xstrdup(oattrib); + /* Terminate on comment */ + if (*attrib == '#') { + argv_consume(acp); /* mark all arguments consumed */ +@@ -1062,11 +1063,13 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, + *arg != '\0' && *arg != '#')) { + error("'all' cannot be combined with other " + "Match attributes"); +- return -1; ++ result = -1; ++ goto out; + } + if (arg != NULL && *arg == '#') + argv_consume(acp); /* consume remaining args */ +- return 1; ++ result = 1; ++ goto out; + } + /* Criterion "invalid-user" also has no argument */ + if (strcasecmp(attrib, "invalid-user") == 0) { +@@ -1078,11 +1081,26 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, + debug("matched invalid-user at line %d", line); + continue; + } ++ ++ /* Keep this list in sync with below */ ++ if (strprefix(attrib, "user=", 1) != NULL || ++ strprefix(attrib, "group=", 1) != NULL || ++ strprefix(attrib, "host=", 1) != NULL || ++ strprefix(attrib, "address=", 1) != NULL || ++ strprefix(attrib, "localaddress=", 1) != NULL || ++ strprefix(attrib, "localport=", 1) != NULL || ++ strprefix(attrib, "rdomain=", 1) != NULL) { ++ arg = strchr(attrib, '='); ++ *(arg++) = '\0'; ++ } else { ++ arg = argv_next(acp, avp); ++ } ++ + /* All other criteria require an argument */ +- if ((arg = argv_next(acp, avp)) == NULL || +- *arg == '\0' || *arg == '#') { ++ if (arg == NULL || *arg == '\0' || *arg == '#') { + error("Missing Match criteria for %s", attrib); +- return -1; ++ result = -1; ++ goto out; + } + if (strcasecmp(attrib, "user") == 0) { + if (ci == NULL || (ci->test && ci->user == NULL)) { +@@ -1105,7 +1123,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, + match_test_missing_fatal("Group", "user"); + switch (match_cfg_line_group(arg, line, ci->user)) { + case -1: +- return -1; ++ result = -1; ++ goto out; + case 0: + result = 0; + } +@@ -1141,7 +1160,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, + result = 0; + break; + case -2: +- return -1; ++ result = -1; ++ goto out; + } + } else if (strcasecmp(attrib, "localaddress") == 0){ + if (ci == NULL || (ci->test && ci->laddress == NULL)) { +@@ -1166,13 +1186,15 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, + result = 0; + break; + case -2: +- return -1; ++ result = -1; ++ goto out; + } + } else if (strcasecmp(attrib, "localport") == 0) { + if ((port = a2port(arg)) == -1) { + error("Invalid LocalPort '%s' on Match line", + arg); +- return -1; ++ result = -1; ++ goto out; + } + if (ci == NULL || (ci->test && ci->lport == -1)) { + result = 0; +@@ -1200,16 +1222,21 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, + debug("user %.100s matched 'RDomain %.100s' at " + "line %d", ci->rdomain, arg, line); + } else { +- error("Unsupported Match attribute %s", attrib); +- return -1; ++ error("Unsupported Match attribute %s", oattrib); ++ result = -1; ++ goto out; + } ++ free(attrib); ++ attrib = NULL; + } + if (attributes == 0) { + error("One or more attributes required for Match"); + return -1; + } +- if (ci != NULL) ++ out: ++ if (ci != NULL && result != -1) + debug3("match %sfound", result ? "" : "not "); ++ free(attrib); + return result; + } + +diff --git a/regress/cfginclude.sh b/regress/cfginclude.sh +index d442cdd6..97fd816f 100644 +--- a/regress/cfginclude.sh ++++ b/regress/cfginclude.sh +@@ -1,4 +1,4 @@ +-# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $ ++# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm Exp $ + # Placed in the Public Domain. + + tid="config include" +@@ -10,7 +10,7 @@ cat > $OBJ/ssh_config.i << _EOF + Match host a + Hostname aa + +-Match host b # comment ++Match host=b # comment + Hostname bb + Include $OBJ/ssh_config.i.* + +@@ -18,7 +18,7 @@ Match host c + Include $OBJ/ssh_config.i.* + Hostname cc + +-Match host m ++Match host=m !user xxxyfake + Include $OBJ/ssh_config.i.* # comment + + Host d +@@ -41,7 +41,7 @@ Match host xxxxxx + _EOF + + cat > $OBJ/ssh_config.i.1 << _EOF +-Match host a ++Match host=a + Hostname aaa + + Match host b +@@ -64,10 +64,10 @@ cat > $OBJ/ssh_config.i.2 << _EOF + Match host a + Hostname aaaa + +-Match host b ++Match host=b !user blahblahfake + Hostname bbbb + +-Match host c ++Match host=c + Hostname cccc + + Host d +@@ -142,7 +142,7 @@ trial a aa + + # cleanup + rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out +-# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $ ++# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm Exp $ + # Placed in the Public Domain. + + tid="config include" +diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh +index 05a66685..2737a5f9 100644 +--- a/regress/cfgmatch.sh ++++ b/regress/cfgmatch.sh +@@ -1,4 +1,4 @@ +-# $OpenBSD: cfgmatch.sh,v 1.13 2021/06/08 06:52:43 djm Exp $ ++# $OpenBSD: cfgmatch.sh,v 1.14 2024/09/27 01:05:54 djm Exp $ + # Placed in the Public Domain. + + tid="sshd_config match" +@@ -26,7 +26,7 @@ start_client() + kill $client_pid + fatal "timeout waiting for background ssh" + fi +- done ++ done + } + + stop_client() +@@ -119,40 +119,42 @@ stop_client + # requires knowledge of actual group memberships user running the test). + params="user:user:u1 host:host:h1 address:addr:1.2.3.4 \ + localaddress:laddr:5.6.7.8 rdomain:rdomain:rdom1" +-cp $OBJ/sshd_proxy_bak $OBJ/sshd_config +-echo 'Banner /nomatch' >>$OBJ/sshd_config +-for i in $params; do +- config=`echo $i | cut -f1 -d:` +- criteria=`echo $i | cut -f2 -d:` +- value=`echo $i | cut -f3 -d:` +- cat >>$OBJ/sshd_config </dev/null || \ ++ fail "validate config for w/out spec" ++ ++ # Test matching each criteria. ++ for i in $params; do ++ testcriteria=`echo $i | cut -f2 -d:` ++ expected=/`echo $i | cut -f3 -d:` ++ spec="" ++ for j in $params; do ++ config=`echo $j | cut -f1 -d:` ++ criteria=`echo $j | cut -f2 -d:` ++ value=`echo $j | cut -f3 -d:` ++ if [ "$criteria" = "$testcriteria" ]; then ++ spec="$criteria=$value,$spec" ++ else ++ spec="$criteria=1$value,$spec" ++ fi ++ done ++ trace "test spec $spec" ++ result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \ ++ awk '$1=="banner"{print $2}'` ++ if [ "$result" != "$expected" ]; then ++ fail "match $config expected $expected got $result" + fi + done +- trace "test spec $spec" +- result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \ +- awk '$1=="banner"{print $2}'` +- if [ "$result" != "$expected" ]; then +- fail "match $config expected $expected got $result" +- fi + done +diff --git a/regress/servcfginclude.sh b/regress/servcfginclude.sh +index 518a703d..f67c3caa 100644 +--- a/regress/servcfginclude.sh ++++ b/regress/servcfginclude.sh +@@ -4,14 +4,14 @@ tid="server config include" + + cat > $OBJ/sshd_config.i << _EOF + HostKey $OBJ/host.ssh-ed25519 +-Match host a ++Match host=a + Banner /aa + + Match host b + Banner /bb + Include $OBJ/sshd_config.i.* # comment + +-Match host c ++Match host=c + Include $OBJ/sshd_config.i.* # comment + Banner /cc + +@@ -25,7 +25,7 @@ Match Host e + Banner /ee + Include $OBJ/sshd_config.i.* + +-Match Host f ++Match Host=f + Include $OBJ/sshd_config.i.* + Banner /ff + +@@ -47,13 +47,13 @@ Match host b + Match host c + Banner /ccc + +-Match Host d ++Match Host=d + Banner /ddd + + Match Host e + Banner /eee + +-Match Host f ++Match Host=f + Banner /fff + _EOF + +@@ -61,13 +61,13 @@ cat > $OBJ/sshd_config.i.2 << _EOF + Match host a + Banner /aaaa + +-Match host b ++Match host=b + Banner /bbbb + + Match host c # comment + Banner /cccc + +-Match Host d ++Match Host=d + Banner /dddd + + Match Host e From 4446a8fec22fb0ddc4e2f6f80b436cd76ab3f508 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 27 Jan 2025 13:44:40 +0100 Subject: [PATCH 56/80] Fix regression of Match directive processing Resolves: rhbz#2341769 --- openssh.spec | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/openssh.spec b/openssh.spec index fba7b89..5c536cf 100644 --- a/openssh.spec +++ b/openssh.spec @@ -39,12 +39,12 @@ %{?static_openssl:%global static_libcrypto 1} %global openssh_ver 9.9p1 -%global openssh_rel 6 +%global openssh_rel 7 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.1 +Release: %{openssh_rel}%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -197,6 +197,9 @@ Patch1016: openssh-9.9p1-separate-keysign.patch # upstream cf3e48ee8ba1beeccddd2f203b558fa102be67a2 # upstream 0c3927c45f8a57b511c874c4d51a8c89414f74ef Patch1017: openssh-9.9p1-mlkembe.patch +# upstream 3f02368e8e9121847727c46b280efc280e5eb615 +# upstream 67a115e7a56dbdc3f5a58c64b29231151f3670f5 +Patch1020: openssh-9.9p1-match-regression.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -380,6 +383,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch -P 1015 -p1 -b .pam-rhost %patch -P 1016 -p1 -b .sep-keysign %patch -P 1017 -p1 -b .mlkembe +%patch -P 1020 -p1 -b .match %patch -P 100 -p1 -b .coverity @@ -658,6 +662,10 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Mon Jan 27 2025 Dmitry Belyavskiy - 9.9p1-7 +- Fix regression of Match directive processing + Resolves: rhbz#2341769 + * Mon Jan 27 2025 Dmitry Belyavskiy - 9.9p1-6 - Remove pam-ssh-agent subcomponent Resolves: rhbz#2338440 From 4329e4cd9e0a0f09fa5a78f028bd106eb2bf28d9 Mon Sep 17 00:00:00 2001 From: "FeRD (Frank Dana)" Date: Wed, 29 Jan 2025 04:41:26 -0500 Subject: [PATCH 57/80] Update redhat sshd config The ChallengeResponseAuthentication setting was deprecated in favor of KbdInteractiveAuthentication, in OpenSSH 8.7. --- openssh-7.7p1-redhat.patch => openssh-8.7p1-redhat.patch | 2 +- openssh.spec | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) rename openssh-7.7p1-redhat.patch => openssh-8.7p1-redhat.patch (99%) diff --git a/openssh-7.7p1-redhat.patch b/openssh-8.7p1-redhat.patch similarity index 99% rename from openssh-7.7p1-redhat.patch rename to openssh-8.7p1-redhat.patch index 1d77f90..4e9d108 100644 --- a/openssh-7.7p1-redhat.patch +++ b/openssh-8.7p1-redhat.patch @@ -83,7 +83,7 @@ diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat @@ -0,0 +1,15 @@ +SyslogFacility AUTHPRIV + -+ChallengeResponseAuthentication no ++KbdInteractiveAuthentication no + +GSSAPIAuthentication yes +GSSAPICleanupCredentials no diff --git a/openssh.spec b/openssh.spec index 5c536cf..8c48231 100644 --- a/openssh.spec +++ b/openssh.spec @@ -39,7 +39,7 @@ %{?static_openssl:%global static_libcrypto 1} %global openssh_ver 9.9p1 -%global openssh_rel 7 +%global openssh_rel 8 Summary: An open source implementation of SSH protocol version 2 Name: openssh @@ -101,7 +101,7 @@ Patch702: openssh-5.1p1-askpass-progress.patch #https://bugzilla.redhat.com/show_bug.cgi?id=198332 Patch703: openssh-4.3p2-askpass-grab-info.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX) -Patch707: openssh-7.7p1-redhat.patch +Patch707: openssh-8.7p1-redhat.patch # warn users for unsupported UsePAM=no (#757545) Patch711: openssh-7.8p1-UsePAM-warning.patch @@ -662,6 +662,10 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Wed Jan 29 2025 FeRD (Frank Dana) - 9.9p1-8 +- Replace deprecated (since 8.7) ChallengeResponseAuthentication + with KbdInteractiveAuthentication, in redhat sshd config + * Mon Jan 27 2025 Dmitry Belyavskiy - 9.9p1-7 - Fix regression of Match directive processing Resolves: rhbz#2341769 From d195a5f6f704af579b3031c79600ffe93b631bbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Esser?= Date: Sat, 1 Feb 2025 19:56:17 +0100 Subject: [PATCH 58/80] Add explicit BR: libxcrypt-devel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Esser --- openssh.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/openssh.spec b/openssh.spec index 8c48231..bf5e0e6 100644 --- a/openssh.spec +++ b/openssh.spec @@ -44,7 +44,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist} +Release: %{openssh_rel}%{?dist}.1 URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -224,6 +224,7 @@ BuildRequires: systemd-rpm-macros BuildRequires: gcc make BuildRequires: p11-kit-devel BuildRequires: libfido2-devel +BuildRequires: libxcrypt-devel Recommends: p11-kit Obsoletes: openssh-ldap < 8.3p1-4 Obsoletes: openssh-cavs < 8.4p1-5 @@ -662,6 +663,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Sat Feb 01 2025 Björn Esser - 9.9p1-8.1 +- Add explicit BR: libxcrypt-devel + * Wed Jan 29 2025 FeRD (Frank Dana) - 9.9p1-8 - Replace deprecated (since 8.7) ChallengeResponseAuthentication with KbdInteractiveAuthentication, in redhat sshd config From 03a941c07910cec7cff8b955f0b31fdc8177c23e Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Tue, 18 Feb 2025 15:05:43 +0100 Subject: [PATCH 59/80] Fixes for CVE-2025-26465, CVE-2025-26466 and also some minor regressions --- openssh-9.9p1-match-regression.patch | 10 +- openssh-9.9p2-error_processing.patch | 152 +++++++++++++++++++++++++++ openssh.spec | 15 ++- 3 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 openssh-9.9p2-error_processing.patch diff --git a/openssh-9.9p1-match-regression.patch b/openssh-9.9p1-match-regression.patch index d724401..73ea964 100644 --- a/openssh-9.9p1-match-regression.patch +++ b/openssh-9.9p1-match-regression.patch @@ -137,7 +137,7 @@ index 89b8413e..dd774f46 100644 /* Terminate on comment */ if (*attrib == '#') { argv_consume(acp); /* mark all arguments consumed */ -@@ -1062,11 +1063,13 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, +@@ -1062,16 +1063,20 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, *arg != '\0' && *arg != '#')) { error("'all' cannot be combined with other " "Match attributes"); @@ -153,6 +153,14 @@ index 89b8413e..dd774f46 100644 } /* Criterion "invalid-user" also has no argument */ if (strcasecmp(attrib, "invalid-user") == 0) { +- if (ci == NULL) ++ if (ci == NULL) { ++ result = 0; + continue; ++ } + if (ci->user_invalid == 0) + result = 0; + else @@ -1078,11 +1081,26 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, debug("matched invalid-user at line %d", line); continue; diff --git a/openssh-9.9p2-error_processing.patch b/openssh-9.9p2-error_processing.patch new file mode 100644 index 0000000..692c6ac --- /dev/null +++ b/openssh-9.9p2-error_processing.patch @@ -0,0 +1,152 @@ +diff --git a/krl.c b/krl.c +index e2efdf06..0d0f6953 100644 +--- a/krl.c ++++ b/krl.c +@@ -674,6 +674,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) + break; + case KRL_SECTION_CERT_SERIAL_BITMAP: + if (rs->lo - bitmap_start > INT_MAX) { ++ r = SSH_ERR_INVALID_FORMAT; + error_f("insane bitmap gap"); + goto out; + } +@@ -1059,6 +1060,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp) + } + + if ((krl = ssh_krl_init()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; + error_f("alloc failed"); + goto out; + } +diff --git a/packet.c b/packet.c +index 486f8515..9dea2cfc 100644 +--- a/packet.c ++++ b/packet.c +@@ -1864,6 +1864,14 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) + if ((r = sshpkt_get_string_direct(ssh, &d, &len)) != 0) + return r; + DBG(debug("Received SSH2_MSG_PING len %zu", len)); ++ if (!ssh->state->after_authentication) { ++ DBG(debug("Won't reply to PING in preauth")); ++ break; ++ } ++ if (ssh_packet_is_rekeying(ssh)) { ++ DBG(debug("Won't reply to PING during KEX")); ++ break; ++ } + if ((r = sshpkt_start(ssh, SSH2_MSG_PONG)) != 0 || + (r = sshpkt_put_string(ssh, d, len)) != 0 || + (r = sshpkt_send(ssh)) != 0) +diff --git a/ssh-agent.c b/ssh-agent.c +index 48973b2c..c27c5a95 100644 +--- a/ssh-agent.c ++++ b/ssh-agent.c +@@ -1220,6 +1220,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, + "restrict-destination-v00@openssh.com") == 0) { + if (*dcsp != NULL) { + error_f("%s already set", ext_name); ++ r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_froms(m, &b)) != 0) { +@@ -1229,6 +1230,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, + while (sshbuf_len(b) != 0) { + if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) { + error_f("too many %s constraints", ext_name); ++ r = SSH_ERR_INVALID_FORMAT; + goto out; + } + *dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1, +@@ -1246,6 +1248,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, + } + if (*certs != NULL) { + error_f("%s already set", ext_name); ++ r = SSH_ERR_INVALID_FORMAT; + goto out; + } + if ((r = sshbuf_get_u8(m, &v)) != 0 || +@@ -1257,6 +1260,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, + while (sshbuf_len(b) != 0) { + if (*ncerts >= AGENT_MAX_EXT_CERTS) { + error_f("too many %s constraints", ext_name); ++ r = SSH_ERR_INVALID_FORMAT; + goto out; + } + *certs = xrecallocarray(*certs, *ncerts, *ncerts + 1, +@@ -1757,6 +1761,7 @@ process_ext_session_bind(SocketEntry *e) + /* record new key/sid */ + if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) { + error_f("too many session IDs recorded"); ++ r = -1; + goto out; + } + e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids, +diff --git a/ssh-sk-client.c b/ssh-sk-client.c +index 321fe53a..06fad221 100644 +--- a/ssh-sk-client.c ++++ b/ssh-sk-client.c +@@ -439,6 +439,7 @@ sshsk_load_resident(const char *provider_path, const char *device, + } + if ((srk = calloc(1, sizeof(*srk))) == NULL) { + error_f("calloc failed"); ++ r = SSH_ERR_ALLOC_FAIL; + goto out; + } + srk->key = key; +@@ -450,6 +451,7 @@ sshsk_load_resident(const char *provider_path, const char *device, + if ((tmp = recallocarray(srks, nsrks, nsrks + 1, + sizeof(*srks))) == NULL) { + error_f("recallocarray keys failed"); ++ r = SSH_ERR_ALLOC_FAIL; + goto out; + } + debug_f("srks[%zu]: %s %s uidlen %zu", nsrks, +diff --git a/sshconnect2.c b/sshconnect2.c +index a69c4da1..1ee6000a 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -99,7 +99,7 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) + options.required_rsa_size)) != 0) + fatal_r(r, "Bad server host key"); + if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, +- xxx_conn_info) == -1) ++ xxx_conn_info) != 0) + fatal("Host key verification failed."); + return 0; + } +@@ -699,6 +699,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) + + if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { + debug_f("server sent unknown pkalg %s", pkalg); ++ r = SSH_ERR_INVALID_FORMAT; + goto done; + } + if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { +@@ -709,6 +710,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) + error("input_userauth_pk_ok: type mismatch " + "for decoded key (received %d, expected %d)", + key->type, pktype); ++ r = SSH_ERR_INVALID_FORMAT; + goto done; + } + +@@ -728,6 +730,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) + SSH_FP_DEFAULT); + error_f("server replied with unknown key: %s %s", + sshkey_type(key), fp == NULL ? "" : fp); ++ r = SSH_ERR_INVALID_FORMAT; + goto done; + } + ident = format_identity(id); +diff --git a/sshsig.c b/sshsig.c +index 6e03c0b0..3da005d6 100644 +--- a/sshsig.c ++++ b/sshsig.c +@@ -879,6 +879,7 @@ cert_filter_principals(const char *path, u_long linenum, + } + if ((principals = sshbuf_dup_string(nprincipals)) == NULL) { + error_f("buffer error"); ++ r = SSH_ERR_ALLOC_FAIL; + goto out; + } + /* success */ diff --git a/openssh.spec b/openssh.spec index bf5e0e6..f6df528 100644 --- a/openssh.spec +++ b/openssh.spec @@ -39,12 +39,12 @@ %{?static_openssl:%global static_libcrypto 1} %global openssh_ver 9.9p1 -%global openssh_rel 8 +%global openssh_rel 9 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist}.1 +Release: %{openssh_rel}%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -200,6 +200,9 @@ Patch1017: openssh-9.9p1-mlkembe.patch # upstream 3f02368e8e9121847727c46b280efc280e5eb615 # upstream 67a115e7a56dbdc3f5a58c64b29231151f3670f5 Patch1020: openssh-9.9p1-match-regression.patch +# upstream 6ce00f0c2ecbb9f75023dbe627ee6460bcec78c2 +# upstream 0832aac79517611dd4de93ad0a83577994d9c907 +Patch1021: openssh-9.9p2-error_processing.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -357,7 +360,6 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch -P 951 -p1 -b .pkcs11-uri %patch -P 953 -p1 -b .scp-ipv6 %patch -P 962 -p1 -b .crypto-policies -#%patch -P 963 -p1 -b .openssl-evp %patch -P 964 -p1 -b .openssl-kdf %patch -P 965 -p1 -b .visibility %patch -P 966 -p1 -b .x11-ipv6 @@ -385,6 +387,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch -P 1016 -p1 -b .sep-keysign %patch -P 1017 -p1 -b .mlkembe %patch -P 1020 -p1 -b .match +%patch -P 1021 -p1 -b .errcode_set %patch -P 100 -p1 -b .coverity @@ -663,6 +666,12 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Tue Feb 18 2025 Dmitry Belyavskiy - 9.9p1-9 +- Fix regression of Match directive processing +- Fix missing error codes set and invalid error code checks in OpenSSH. It + prevents memory exhaustion attack and a MITM attack when VerifyHostKeyDNS + is on (CVE-2025-26465, CVE-2025-26466). + * Sat Feb 01 2025 Björn Esser - 9.9p1-8.1 - Add explicit BR: libxcrypt-devel From ea9f68c17152b4cc0a43c768b39945e468ed18c5 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Tue, 25 Feb 2025 12:34:18 +0100 Subject: [PATCH 60/80] Some minor fixes from Rocky Linux https://www.openwall.com/lists/oss-security/2025/02/22/1 --- openssh-7.7p1-gssapi-new-unique.patch | 5 +++-- openssh-9.9p2-error_processing.patch | 9 +++++++++ openssh.spec | 7 ++++++- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/openssh-7.7p1-gssapi-new-unique.patch b/openssh-7.7p1-gssapi-new-unique.patch index 0b8ab02..34b9b9d 100644 --- a/openssh-7.7p1-gssapi-new-unique.patch +++ b/openssh-7.7p1-gssapi-new-unique.patch @@ -126,7 +126,7 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c if (authctxt->krb5_user) { krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); authctxt->krb5_user = NULL; -@@ -238,36 +281,188 @@ krb5_cleanup_proc(Authctxt *authctxt) +@@ -238,36 +281,189 @@ krb5_cleanup_proc(Authctxt *authctxt) } } @@ -149,7 +149,8 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c + old = *dsc; + + i = asprintf(dsc, "%s%s", *dsc, src); -+ if (i == -1 || src == NULL) { ++ if (i == -1) { ++ *dsc = old; + free(src); + return -1; + } diff --git a/openssh-9.9p2-error_processing.patch b/openssh-9.9p2-error_processing.patch index 692c6ac..dd71716 100644 --- a/openssh-9.9p2-error_processing.patch +++ b/openssh-9.9p2-error_processing.patch @@ -73,6 +73,15 @@ index 48973b2c..c27c5a95 100644 goto out; } *certs = xrecallocarray(*certs, *ncerts, *ncerts + 1, +@@ -1360,6 +1360,8 @@ process_add_identity(SocketEntry *e) + if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || + k == NULL || + (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { ++ if (!r) /* k == NULL */ ++ r = SSH_ERR_INTERNAL_ERROR; + error_fr(r, "parse"); + goto out; + } @@ -1757,6 +1761,7 @@ process_ext_session_bind(SocketEntry *e) /* record new key/sid */ if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) { diff --git a/openssh.spec b/openssh.spec index f6df528..9f2e014 100644 --- a/openssh.spec +++ b/openssh.spec @@ -39,7 +39,7 @@ %{?static_openssl:%global static_libcrypto 1} %global openssh_ver 9.9p1 -%global openssh_rel 9 +%global openssh_rel 10 Summary: An open source implementation of SSH protocol version 2 Name: openssh @@ -202,6 +202,7 @@ Patch1017: openssh-9.9p1-mlkembe.patch Patch1020: openssh-9.9p1-match-regression.patch # upstream 6ce00f0c2ecbb9f75023dbe627ee6460bcec78c2 # upstream 0832aac79517611dd4de93ad0a83577994d9c907 +# added https://www.openwall.com/lists/oss-security/2025/02/22/1 Patch1021: openssh-9.9p2-error_processing.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant @@ -666,6 +667,10 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Tue Feb 25 2025 Dmitry Belyavskiy - 9.9p1-9.1 +- Some minor fixes from Rocky Linux + https://www.openwall.com/lists/oss-security/2025/02/22/1 + * Tue Feb 18 2025 Dmitry Belyavskiy - 9.9p1-9 - Fix regression of Match directive processing - Fix missing error codes set and invalid error code checks in OpenSSH. It From 300222035ecd9530f61f9357dcbcbd12c2db93d5 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 5 Mar 2025 15:04:36 +0100 Subject: [PATCH 61/80] Use OpenSSL ML-KEM implementation instead of the native one --- openssh-9.9p1-openssl-mlkem.patch | 385 ++++++++++++++++++++++++++++++ openssh.spec | 15 +- 2 files changed, 396 insertions(+), 4 deletions(-) create mode 100644 openssh-9.9p1-openssl-mlkem.patch diff --git a/openssh-9.9p1-openssl-mlkem.patch b/openssh-9.9p1-openssl-mlkem.patch new file mode 100644 index 0000000..e39bb67 --- /dev/null +++ b/openssh-9.9p1-openssl-mlkem.patch @@ -0,0 +1,385 @@ +diff --git a/kex-names.c b/kex-names.c +index ec840c1f..c0d3be11 100644 +--- a/kex-names.c ++++ b/kex-names.c +@@ -90,6 +90,19 @@ static const struct kexalg kexalgs[] = { + { NULL, 0, -1, -1}, + }; + ++static int is_mlkem768_available() ++{ ++ static int is_fetched = -1; ++ ++ if (is_fetched == -1) { ++ EVP_KEM *mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", NULL); ++ is_fetched = mlkem768 != NULL ? 1 : 0; ++ EVP_KEM_free(mlkem768); ++ } ++ ++ return is_fetched; ++} ++ + static char * + kex_alg_list_internal(char sep, const struct kexalg *algs) + { +@@ -98,6 +111,9 @@ kex_alg_list_internal(char sep, const struct kexalg *algs) + const struct kexalg *k; + + for (k = algs; k->name != NULL; k++) { ++ if (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0 ++ && !is_mlkem768_available()) ++ continue; + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(k->name); +@@ -117,6 +133,10 @@ kex_alg_by_name(const char *name) + { + const struct kexalg *k; + ++ if (strcmp(name, KEX_MLKEM768X25519_SHA256) == 0 ++ && !is_mlkem768_available()) ++ return NULL; ++ + for (k = kexalgs; k->name != NULL; k++) { + if (strcmp(k->name, name) == 0) + return k; +diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c +index 2b5d3960..670049dc 100644 +--- a/kexmlkem768x25519.c ++++ b/kexmlkem768x25519.c +@@ -48,10 +48,127 @@ + #ifdef USE_MLKEM768X25519 + + #include "libcrux_mlkem768_sha3.h" ++#include ++#include ++#include ++ ++static int ++mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) ++{ ++ EVP_PKEY_CTX *ctx = NULL; ++ EVP_PKEY *pkey = NULL; ++ int ret = SSH_ERR_INTERNAL_ERROR; ++ size_t pubkey_size = crypto_kem_mlkem768_PUBLICKEYBYTES, privkey_size = crypto_kem_mlkem768_SECRETKEYBYTES; ++ ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, "mlkem768", NULL); ++ if (ctx == NULL) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ ++ if (EVP_PKEY_keygen_init(ctx) <= 0 ++ || EVP_PKEY_keygen(ctx, &pkey) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ ++ if (EVP_PKEY_get_raw_public_key(pkey, pubkeybuf, &pubkey_size) <= 0 ++ || EVP_PKEY_get_raw_private_key(pkey, privkeybuf, &privkey_size) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ ++ if (privkey_size != crypto_kem_mlkem768_SECRETKEYBYTES ++ || pubkey_size != crypto_kem_mlkem768_PUBLICKEYBYTES) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ ret = 0; ++ ++ err: ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(ctx); ++ if (ret == SSH_ERR_LIBCRYPTO_ERROR) ++ ERR_print_errors_fp(stderr); ++ return ret; ++} ++ ++static int ++mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) ++{ ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ int r = SSH_ERR_INTERNAL_ERROR; ++ size_t outlen = crypto_kem_mlkem768_CIPHERTEXTBYTES, ++ secretlen = crypto_kem_mlkem768_BYTES; ++ ++ pkey = EVP_PKEY_new_raw_public_key_ex(NULL, "mlkem768", NULL, ++ pubkeybuf, crypto_kem_mlkem768_PUBLICKEYBYTES); ++ if (pkey == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ ++ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); ++ if (ctx == NULL ++ || EVP_PKEY_encapsulate_init(ctx, NULL) <= 0 ++ || EVP_PKEY_encapsulate(ctx, out, &outlen, secret, &secretlen) <= 0 ++ || secretlen != crypto_kem_mlkem768_BYTES ++ || outlen != crypto_kem_mlkem768_CIPHERTEXTBYTES) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ r = 0; ++ ++ err: ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(ctx); ++ if (r == SSH_ERR_LIBCRYPTO_ERROR) ++ ERR_print_errors_fp(stderr); ++ ++ return r; ++} ++ ++static int ++mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *secret) ++{ ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ int r = SSH_ERR_INTERNAL_ERROR; ++ size_t wrappedlen = crypto_kem_mlkem768_CIPHERTEXTBYTES, ++ secretlen = crypto_kem_mlkem768_BYTES; ++ ++ pkey = EVP_PKEY_new_raw_private_key_ex(NULL, "mlkem768", NULL, ++ privkeybuf, crypto_kem_mlkem768_SECRETKEYBYTES); ++ if (pkey == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ ++ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); ++ if (ctx == NULL ++ || EVP_PKEY_decapsulate_init(ctx, NULL) <= 0 ++ || EVP_PKEY_decapsulate(ctx, secret, &secretlen, wrapped, wrappedlen) <= 0 ++ || secretlen != crypto_kem_mlkem768_BYTES) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ r = 0; ++ ++ err: ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_CTX_free(ctx); ++ ++ if (r == SSH_ERR_LIBCRYPTO_ERROR) ++ ERR_print_errors_fp(stderr); ++ ++ return r; ++} + + int + kex_kem_mlkem768x25519_keypair(struct kex *kex) + { ++#if 0 + struct sshbuf *buf = NULL; + u_char rnd[LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN], *cp = NULL; + size_t need; +@@ -86,6 +203,36 @@ kex_kem_mlkem768x25519_keypair(struct kex *kex) + explicit_bzero(rnd, sizeof(rnd)); + sshbuf_free(buf); + return r; ++#else ++ struct sshbuf *buf = NULL; ++ u_char *cp = NULL; ++ size_t need; ++ int r = SSH_ERR_INTERNAL_ERROR; ++ ++ if ((buf = sshbuf_new()) == NULL) ++ return SSH_ERR_ALLOC_FAIL; ++ need = crypto_kem_mlkem768_PUBLICKEYBYTES + CURVE25519_SIZE; ++ if ((r = sshbuf_reserve(buf, need, &cp)) != 0) ++ goto out; ++ if ((r = mlkem768_keypair_gen(cp, kex->mlkem768_client_key)) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("client public key mlkem768:", cp, ++ crypto_kem_mlkem768_PUBLICKEYBYTES); ++#endif ++ cp += crypto_kem_mlkem768_PUBLICKEYBYTES; ++ kexc25519_keygen(kex->c25519_client_key, cp); ++#ifdef DEBUG_KEXECDH ++ dump_digest("client public key c25519:", cp, CURVE25519_SIZE); ++#endif ++ /* success */ ++ r = 0; ++ kex->client_pub = buf; ++ buf = NULL; ++ out: ++ sshbuf_free(buf); ++ return r; ++#endif + } + + int +@@ -93,6 +240,7 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, + const struct sshbuf *client_blob, struct sshbuf **server_blobp, + struct sshbuf **shared_secretp) + { ++#if 0 + struct sshbuf *server_blob = NULL; + struct sshbuf *buf = NULL; + const u_char *client_pub; +@@ -185,12 +333,97 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, + sshbuf_free(server_blob); + sshbuf_free(buf); + return r; ++#else ++ struct sshbuf *server_blob = NULL; ++ struct sshbuf *buf = NULL; ++ const u_char *client_pub; ++ u_char server_pub[CURVE25519_SIZE], server_key[CURVE25519_SIZE]; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t need; ++ int r = SSH_ERR_INTERNAL_ERROR; ++ struct libcrux_mlkem768_enc_result enc; /* FIXME */ ++ ++ *server_blobp = NULL; ++ *shared_secretp = NULL; ++ ++ /* client_blob contains both KEM and ECDH client pubkeys */ ++ need = crypto_kem_mlkem768_PUBLICKEYBYTES + CURVE25519_SIZE; ++ if (sshbuf_len(client_blob) != need) { ++ r = SSH_ERR_SIGNATURE_INVALID; ++ goto out; ++ } ++ client_pub = sshbuf_ptr(client_blob); ++#ifdef DEBUG_KEXECDH ++ dump_digest("client public key mlkem768:", client_pub, ++ crypto_kem_mlkem768_PUBLICKEYBYTES); ++ dump_digest("client public key 25519:", ++ client_pub + crypto_kem_mlkem768_PUBLICKEYBYTES, ++ CURVE25519_SIZE); ++#endif ++ ++ /* allocate buffer for concatenation of KEM key and ECDH shared key */ ++ /* the buffer will be hashed and the result is the shared secret */ ++ if ((buf = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ /* allocate space for encrypted KEM key and ECDH pub key */ ++ if ((server_blob = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (mlkem768_encap_secret(client_pub, enc.snd, enc.fst.value) != 0) ++ goto out; ++ ++ /* generate ECDH key pair, store server pubkey after ciphertext */ ++ kexc25519_keygen(server_key, server_pub); ++ if ((r = sshbuf_put(buf, enc.snd, sizeof(enc.snd))) != 0 || ++ (r = sshbuf_put(server_blob, enc.fst.value, sizeof(enc.fst.value))) != 0 || ++ (r = sshbuf_put(server_blob, server_pub, sizeof(server_pub))) != 0) ++ goto out; ++ /* append ECDH shared key */ ++ client_pub += crypto_kem_mlkem768_PUBLICKEYBYTES; ++ if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0) ++ goto out; ++ if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE); ++ dump_digest("server cipher text:", ++ enc.fst.value, sizeof(enc.fst.value)); ++ dump_digest("server kem key:", enc.snd, sizeof(enc.snd)); ++ dump_digest("concatenation of KEM key and ECDH shared key:", ++ sshbuf_ptr(buf), sshbuf_len(buf)); ++#endif ++ /* string-encoded hash is resulting shared secret */ ++ sshbuf_reset(buf); ++ if ((r = sshbuf_put_string(buf, hash, ++ ssh_digest_bytes(kex->hash_alg))) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); ++#endif ++ /* success */ ++ r = 0; ++ *server_blobp = server_blob; ++ *shared_secretp = buf; ++ server_blob = NULL; ++ buf = NULL; ++ out: ++ explicit_bzero(hash, sizeof(hash)); ++ explicit_bzero(server_key, sizeof(server_key)); ++ explicit_bzero(&enc, sizeof(enc)); ++ sshbuf_free(server_blob); ++ sshbuf_free(buf); ++ return r; ++#endif + } + + int + kex_kem_mlkem768x25519_dec(struct kex *kex, + const struct sshbuf *server_blob, struct sshbuf **shared_secretp) + { ++#if 0 + struct sshbuf *buf = NULL; + u_char mlkem_key[crypto_kem_mlkem768_BYTES]; + const u_char *ciphertext, *server_pub; +@@ -258,6 +491,64 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, + explicit_bzero(mlkem_key, sizeof(mlkem_key)); + sshbuf_free(buf); + return r; ++#else ++ struct sshbuf *buf = NULL; ++ const u_char *ciphertext, *server_pub; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ u_char decap[crypto_kem_mlkem768_BYTES]; ++ size_t need; ++ int r; ++ ++ *shared_secretp = NULL; ++ ++ need = crypto_kem_mlkem768_CIPHERTEXTBYTES + CURVE25519_SIZE; ++ if (sshbuf_len(server_blob) != need) { ++ r = SSH_ERR_SIGNATURE_INVALID; ++ goto out; ++ } ++ ciphertext = sshbuf_ptr(server_blob); ++ server_pub = ciphertext + crypto_kem_mlkem768_CIPHERTEXTBYTES; ++ /* hash concatenation of KEM key and ECDH shared key */ ++ if ((buf = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++#ifdef DEBUG_KEXECDH ++ dump_digest("server cipher text:", ciphertext, crypto_kem_mlkem768_CIPHERTEXTBYTES); ++ dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE); ++#endif ++ if ((r = mlkem768_decap_secret(kex->mlkem768_client_key, ciphertext, decap)) != 0) ++ goto out; ++ if ((r = sshbuf_put(buf, decap, sizeof(decap))) != 0) ++ goto out; ++ if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub, ++ buf, 1)) < 0) ++ goto out; ++ if ((r = ssh_digest_buffer(kex->hash_alg, buf, ++ hash, sizeof(hash))) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("client kem key:", decap, sizeof(decap)); ++ dump_digest("concatenation of KEM key and ECDH shared key:", ++ sshbuf_ptr(buf), sshbuf_len(buf)); ++#endif ++ sshbuf_reset(buf); ++ if ((r = sshbuf_put_string(buf, hash, ++ ssh_digest_bytes(kex->hash_alg))) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); ++#endif ++ /* success */ ++ r = 0; ++ *shared_secretp = buf; ++ buf = NULL; ++ out: ++ explicit_bzero(hash, sizeof(hash)); ++ explicit_bzero(decap, sizeof(decap)); ++ sshbuf_free(buf); ++ return r; ++#endif + } + #else /* USE_MLKEM768X25519 */ + int diff --git a/openssh.spec b/openssh.spec index 9f2e014..25d1cbd 100644 --- a/openssh.spec +++ b/openssh.spec @@ -39,12 +39,11 @@ %{?static_openssl:%global static_libcrypto 1} %global openssh_ver 9.9p1 -%global openssh_rel 10 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: %{openssh_rel}%{?dist} +Release: 11%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -204,6 +203,8 @@ Patch1020: openssh-9.9p1-match-regression.patch # upstream 0832aac79517611dd4de93ad0a83577994d9c907 # added https://www.openwall.com/lists/oss-security/2025/02/22/1 Patch1021: openssh-9.9p2-error_processing.patch +# Downstream patch, OpenSSL based MLKEM implementation +Patch1022: openssh-9.9p1-openssl-mlkem.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -229,6 +230,7 @@ BuildRequires: gcc make BuildRequires: p11-kit-devel BuildRequires: libfido2-devel BuildRequires: libxcrypt-devel +BuildRequires: oqsprovider Recommends: p11-kit Obsoletes: openssh-ldap < 8.3p1-4 Obsoletes: openssh-cavs < 8.4p1-5 @@ -389,6 +391,7 @@ gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %patch -P 1017 -p1 -b .mlkembe %patch -P 1020 -p1 -b .match %patch -P 1021 -p1 -b .errcode_set +%patch -P 1022 -p1 -b .openssl-mlkem %patch -P 100 -p1 -b .coverity @@ -486,7 +489,8 @@ popd %endif %check -OPENSSL_CONF=/dev/null %{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile +%{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile +#make tests %install rm -rf $RPM_BUILD_ROOT @@ -667,7 +671,10 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog -* Tue Feb 25 2025 Dmitry Belyavskiy - 9.9p1-9.1 +* Wed Mar 05 2025 Dmitry Belyavskiy - 9.9p1-11 +- Use OpenSSL ML-KEM implementation instead of the native one + +* Tue Feb 25 2025 Dmitry Belyavskiy - 9.9p1-10 - Some minor fixes from Rocky Linux https://www.openwall.com/lists/oss-security/2025/02/22/1 From 691ab72ad816bd315c49b3d9bea2eee8e2f25052 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 6 Mar 2025 12:15:40 +0100 Subject: [PATCH 62/80] Update ssh-keysign permission for RPM linter --- openssh.rpmlintrc | 4 +--- openssh.spec | 5 ++++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/openssh.rpmlintrc b/openssh.rpmlintrc index 2404235..7031b2b 100644 --- a/openssh.rpmlintrc +++ b/openssh.rpmlintrc @@ -2,9 +2,7 @@ addFilter(r'openssh-askpass.x86_64: W: non-conffile-in-etc /etc/profile.d/gnome-ssh-askpass.c?sh') # The ssh-keysign is not supposed to have standard permissions -addFilter(r'openssh.x86_64: E: non-standard-executable-perm /usr/libexec/openssh/ssh-keysign 2555') -addFilter(r'openssh.x86_64: E: setgid-binary /usr/libexec/openssh/ssh-keysign ssh_keys 2555') -addFilter(r'openssh.x86_64: W: non-standard-gid /usr/libexec/openssh/ssh-keysign ssh_keys') +addFilter(r'openssh.x86_64: E: non-standard-executable-perm /usr/libexec/openssh/ssh-keysign 4555') # The -cavs subpackage is internal without documentation # The -askpass is not intended to be used directly so it is missing documentation diff --git a/openssh.spec b/openssh.spec index 25d1cbd..8285335 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 11%{?dist} +Release: 12%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -671,6 +671,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Thu Mar 06 2025 Dmitry Belyavskiy - 9.9p1-12 +- Update ssh-keysign permission for RPM linter + * Wed Mar 05 2025 Dmitry Belyavskiy - 9.9p1-11 - Use OpenSSL ML-KEM implementation instead of the native one From db6cd22c3fee813b385c978b32e2b3aafa6c31d4 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Tue, 18 Mar 2025 16:28:02 +0100 Subject: [PATCH 63/80] Usability adjustments - Remove /usr/sbin from the default path Resolves: rhbz#2352387 - Export and accept COLORTERM Resolves: rhbz#2352653 --- openssh-8.7p1-redhat.patch | 10 ++++++++-- openssh.spec | 12 +++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/openssh-8.7p1-redhat.patch b/openssh-8.7p1-redhat.patch index 4e9d108..a4c11b5 100644 --- a/openssh-8.7p1-redhat.patch +++ b/openssh-8.7p1-redhat.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,15 @@ +@@ -0,0 +1,18 @@ +# 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,6 +29,9 @@ diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat +# mode correctly we set this to yes. + ForwardX11Trusted yes + ++# rhbz#2352653 - export COLORTERM ++ SendEnv COLORTERM ++ +# Uncomment this if you want to use .local domain +# Host *.local diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0 @@ -80,7 +83,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,15 @@ +@@ -0,0 +1,18 @@ +SyslogFacility AUTHPRIV + +KbdInteractiveAuthentication no @@ -92,6 +95,9 @@ diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat + +X11Forwarding yes + ++# rhbz#2352653 - accept COLORTERM ++ AcceptEnv COLORTERM ++ +# It is recommended to use pam_motd in /etc/pam.d/sshd instead of PrintMotd, +# as it is more configurable and versatile than the built-in version. +PrintMotd no diff --git a/openssh.spec b/openssh.spec index 8285335..df2a8a4 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 12%{?dist} +Release: 13%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -432,8 +432,8 @@ fi --sysconfdir=%{_sysconfdir}/ssh \ --libexecdir=%{_libexecdir}/openssh \ --datadir=%{_datadir}/openssh \ - --with-default-path=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \ - --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \ + --with-default-path=/usr/local/bin:/usr/bin:/usr/local/sbin \ + --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/bin \ --with-privsep-path=%{_datadir}/empty.sshd \ --disable-strip \ --without-zlib-version-check \ @@ -671,6 +671,12 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Tue Mar 18 2025 Dmitry Belyavskiy - 9.9p1-13 +- Remove /usr/sbin from the default path + Resolves: rhbz#2352387 +- Export and accept COLORTERM + Resolves: rhbz#2352653 + * Thu Mar 06 2025 Dmitry Belyavskiy - 9.9p1-12 - Update ssh-keysign permission for RPM linter From 9ef6367bc1866800b3cb1bef12a64f74edadcf90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 18 Mar 2025 21:32:06 +0100 Subject: [PATCH 64/80] Drop /usr/local/sbin from the default path too On systems with merged sbin, both /usr/local/sbin and /usr/sbin are symlinks, so /usr/local/sbin should be dropped from the default path too. --- openssh.spec | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/openssh.spec b/openssh.spec index df2a8a4..401520e 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 13%{?dist} +Release: 14%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -432,8 +432,8 @@ fi --sysconfdir=%{_sysconfdir}/ssh \ --libexecdir=%{_libexecdir}/openssh \ --datadir=%{_datadir}/openssh \ - --with-default-path=/usr/local/bin:/usr/bin:/usr/local/sbin \ - --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/bin \ + --with-default-path=/usr/local/bin:/usr/bin \ + --with-superuser-path=/usr/local/bin:/usr/bin \ --with-privsep-path=%{_datadir}/empty.sshd \ --disable-strip \ --without-zlib-version-check \ @@ -671,6 +671,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Tue Mar 18 2025 Zbigniew Jędrzejewski-Szmek - 9.9p1-14 +- Remove /usr/local/sbin from the default path too + * Tue Mar 18 2025 Dmitry Belyavskiy - 9.9p1-13 - Remove /usr/sbin from the default path Resolves: rhbz#2352387 From dd7f8b6993e382689912b01975d3afd4aa063393 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 17 Apr 2025 12:07:36 +0200 Subject: [PATCH 65/80] Require OpenSSL 3.5 to support PQ crypto Also suppress systemd warning on restart sshd --- openssh.spec | 12 ++++++++---- sshd.sysconfig | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/openssh.spec b/openssh.spec index 401520e..ffa1fa7 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 14%{?dist} +Release: 15%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -208,6 +208,7 @@ Patch1022: openssh-9.9p1-openssl-mlkem.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin +Requires: openssl-libs >= 3.5.0 %if ! %{no_gnome_askpass} BuildRequires: libX11-devel @@ -222,7 +223,7 @@ BuildRequires: autoconf, automake, perl-interpreter, perl-generators, zlib-devel BuildRequires: audit-libs-devel >= 2.0.5 BuildRequires: util-linux, groff BuildRequires: pam-devel -BuildRequires: openssl-devel >= 0.9.8j +BuildRequires: openssl-devel >= 3.5.0 BuildRequires: perl-podlators BuildRequires: systemd-devel BuildRequires: systemd-rpm-macros @@ -230,7 +231,6 @@ BuildRequires: gcc make BuildRequires: p11-kit-devel BuildRequires: libfido2-devel BuildRequires: libxcrypt-devel -BuildRequires: oqsprovider Recommends: p11-kit Obsoletes: openssh-ldap < 8.3p1-4 Obsoletes: openssh-cavs < 8.4p1-5 @@ -489,7 +489,7 @@ popd %endif %check -%{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile +OPENSSL_CONF=/dev/null %{SOURCE22} %{SOURCE23} # ./parallel_tests.sh parallel_tests.Makefile #make tests %install @@ -671,6 +671,10 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Thu Apr 17 2025 Dmitry Belyavskiy - 9.9p1-15 +- Require OpenSSL 3.5 to support PQ crypto +- Suppress systemd warning on restart sshd + * Tue Mar 18 2025 Zbigniew Jędrzejewski-Szmek - 9.9p1-14 - Remove /usr/local/sbin from the default path too diff --git a/sshd.sysconfig b/sshd.sysconfig index ee44ae6..be40d08 100644 --- a/sshd.sysconfig +++ b/sshd.sysconfig @@ -8,3 +8,4 @@ #SSH_RSA_BITS=3072 #SSH_ECDSA_BITS=256 +OPTIONS="" From 6330768ca86ff2194758a9fb37c0d7b4114abeb5 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 16 May 2025 14:45:32 +0200 Subject: [PATCH 66/80] Rebasing to 10.0p1 --- .gitignore | 2 + ...patch => 0001-openssh-7.8p1-role-mls.patch | 445 ++- ...> 0002-openssh-6.6p1-privsep-selinux.patch | 94 +- ...t.patch => 0003-openssh-6.6p1-keycat.patch | 226 +- ... => 0004-openssh-6.6p1-allow-ip-opts.patch | 21 +- ....patch => 0005-openssh-5.9p1-ipv6man.patch | 31 +- 0006-openssh-5.8p2-sigpipe.patch | 26 + ...-x11.patch => 0007-openssh-7.2p2-x11.patch | 31 +- ... 0008-openssh-5.1p1-askpass-progress.patch | 41 +- ...0009-openssh-4.3p2-askpass-grab-info.patch | 21 +- ...t.patch => 0010-openssh-8.7p1-redhat.patch | 109 +- ...=> 0011-openssh-7.8p1-UsePAM-warning.patch | 31 +- ...h => 0012-openssh-9.6p1-gssapi-keyex.patch | 2232 ++++++------ ...atch => 0013-openssh-6.6p1-force_krb.patch | 39 +- ...0014-openssh-7.7p1-gssapi-new-unique.patch | 316 +- ...0015-openssh-7.2p2-k5login_directory.patch | 31 +- ....patch => 0016-openssh-6.6p1-kuserok.patch | 135 +- 0017-openssh-6.4p1-fromto-remote.patch | 28 + ...018-openssh-6.6.1p1-selinux-contexts.patch | 50 +- ...> 0019-openssh-6.6.1p1-log-in-chroot.patch | 178 +- ...h-6.6.1p1-scp-non-existing-directory.patch | 27 + ...21-openssh-6.6p1-GSSAPIEnablek5users.patch | 107 +- 0022-openssh-6.8p1-sshdT-output.patch | 25 + ...-openssh-6.7p1-sftp-force-permission.patch | 41 +- ...=> 0024-openssh-7.2p2-s390-closefrom.patch | 22 +- ... 0025-openssh-7.3p1-x11-max-displays.patch | 152 +- ...> 0026-openssh-7.6p1-cleanup-selinux.patch | 169 +- 0027-openssh-7.5p1-sandbox.patch | 58 + ...tch => 0028-openssh-8.0p1-pkcs11-uri.patch | 3216 +++++++++-------- ...patch => 0029-openssh-7.8p1-scp-ipv6.patch | 15 +- ...> 0030-openssh-8.0p1-crypto-policies.patch | 92 +- ...ch => 0031-openssh-8.0p1-openssl-kdf.patch | 26 +- ...tch => 0032-openssh-8.2p1-visibility.patch | 22 +- ... 0033-openssh-8.2p1-x11-without-ipv6.patch | 25 +- ...34-openssh-8.0p1-preserve-pam-errors.patch | 29 +- ...> 0035-openssh-8.7p1-scp-kill-switch.patch | 39 +- ... => 0036-openssh-8.7p1-recursive-scp.patch | 86 +- ...tch => 0037-openssh-8.7p1-minrsabits.patch | 27 +- 0038-openssh-8.7p1-ibmca.patch | 25 + ...it.patch => 0039-openssh-7.6p1-audit.patch | 1030 +++--- ...0-openssh-7.1p2-audit-race-condition.patch | 59 +- ...atch => 0041-openssh-9.0p1-audit-log.patch | 127 +- ...ips.patch => 0042-openssh-7.7p1-fips.patch | 781 ++-- 0043-openssh-8.7p1-ssh-manpage.patch | 47 + ...enssh-8.7p1-negotiate-supported-algs.patch | 41 +- ...h => 0045-openssh-9.0p1-evp-fips-kex.patch | 109 +- ...> 0046-openssh-8.7p1-nohostsha1proof.patch | 161 +- 0047-openssh-9.6p1-pam-rhost.patch | 25 + 0048-openssh-9.9p1-separate-keysign.patch | 25 + ... => 0049-openssh-9.9p1-openssl-mlkem.patch | 21 +- 0050-openssh-9.9p2-error_processing.patch | 25 + 1000-openssh-coverity.patch | 257 ++ openssh-5.8p2-sigpipe.patch | 14 - openssh-6.4p1-fromto-remote.patch | 16 - ...h-6.6.1p1-scp-non-existing-directory.patch | 14 - openssh-6.7p1-coverity.patch | 248 -- openssh-6.8p1-sshdT-output.patch | 12 - openssh-7.5p1-sandbox.patch | 86 - openssh-8.0p1-keygen-strip-doseol.patch | 12 - openssh-8.7p1-ibmca.patch | 11 - openssh-8.7p1-ssh-manpage.patch | 53 - openssh-9.6p1-pam-rhost.patch | 32 - openssh-9.9p1-match-regression.patch | 471 --- openssh-9.9p1-mlkembe.patch | 98 - openssh-9.9p1-separate-keysign.patch | 12 - openssh-9.9p2-error_processing.patch | 161 - openssh.spec | 224 +- sources | 4 +- 68 files changed, 6264 insertions(+), 6202 deletions(-) rename openssh-7.8p1-role-mls.patch => 0001-openssh-7.8p1-role-mls.patch (80%) rename openssh-6.6p1-privsep-selinux.patch => 0002-openssh-6.6p1-privsep-selinux.patch (52%) rename openssh-6.6p1-keycat.patch => 0003-openssh-6.6p1-keycat.patch (77%) rename openssh-6.6p1-allow-ip-opts.patch => 0004-openssh-6.6p1-allow-ip-opts.patch (68%) rename openssh-5.9p1-ipv6man.patch => 0005-openssh-5.9p1-ipv6man.patch (54%) create mode 100644 0006-openssh-5.8p2-sigpipe.patch rename openssh-7.2p2-x11.patch => 0007-openssh-7.2p2-x11.patch (71%) rename openssh-5.1p1-askpass-progress.patch => 0008-openssh-5.1p1-askpass-progress.patch (66%) rename openssh-4.3p2-askpass-grab-info.patch => 0009-openssh-4.3p2-askpass-grab-info.patch (53%) rename openssh-8.7p1-redhat.patch => 0010-openssh-8.7p1-redhat.patch (67%) rename openssh-7.8p1-UsePAM-warning.patch => 0011-openssh-7.8p1-UsePAM-warning.patch (50%) rename openssh-9.6p1-gssapi-keyex.patch => 0012-openssh-9.6p1-gssapi-keyex.patch (89%) rename openssh-6.6p1-force_krb.patch => 0013-openssh-6.6p1-force_krb.patch (88%) rename openssh-7.7p1-gssapi-new-unique.patch => 0014-openssh-7.7p1-gssapi-new-unique.patch (79%) rename openssh-7.2p2-k5login_directory.patch => 0015-openssh-7.2p2-k5login_directory.patch (74%) rename openssh-6.6p1-kuserok.patch => 0016-openssh-6.6p1-kuserok.patch (80%) create mode 100644 0017-openssh-6.4p1-fromto-remote.patch rename openssh-6.6.1p1-selinux-contexts.patch => 0018-openssh-6.6.1p1-selinux-contexts.patch (73%) rename openssh-6.6.1p1-log-in-chroot.patch => 0019-openssh-6.6.1p1-log-in-chroot.patch (54%) create mode 100644 0020-openssh-6.6.1p1-scp-non-existing-directory.patch rename openssh-6.6p1-GSSAPIEnablek5users.patch => 0021-openssh-6.6p1-GSSAPIEnablek5users.patch (61%) create mode 100644 0022-openssh-6.8p1-sshdT-output.patch rename openssh-6.7p1-sftp-force-permission.patch => 0023-openssh-6.7p1-sftp-force-permission.patch (72%) rename openssh-7.2p2-s390-closefrom.patch => 0024-openssh-7.2p2-s390-closefrom.patch (66%) rename openssh-7.3p1-x11-max-displays.patch => 0025-openssh-7.3p1-x11-max-displays.patch (53%) rename openssh-7.6p1-cleanup-selinux.patch => 0026-openssh-7.6p1-cleanup-selinux.patch (65%) create mode 100644 0027-openssh-7.5p1-sandbox.patch rename openssh-8.0p1-pkcs11-uri.patch => 0028-openssh-8.0p1-pkcs11-uri.patch (90%) rename openssh-7.8p1-scp-ipv6.patch => 0029-openssh-7.8p1-scp-ipv6.patch (51%) rename openssh-8.0p1-crypto-policies.patch => 0030-openssh-8.0p1-crypto-policies.patch (90%) rename openssh-8.0p1-openssl-kdf.patch => 0031-openssh-8.0p1-openssl-kdf.patch (84%) rename openssh-8.2p1-visibility.patch => 0032-openssh-8.2p1-visibility.patch (62%) rename openssh-8.2p1-x11-without-ipv6.patch => 0033-openssh-8.2p1-x11-without-ipv6.patch (55%) rename openssh-8.0p1-preserve-pam-errors.patch => 0034-openssh-8.0p1-preserve-pam-errors.patch (67%) rename openssh-8.7p1-scp-kill-switch.patch => 0035-openssh-8.7p1-scp-kill-switch.patch (57%) rename openssh-8.7p1-recursive-scp.patch => 0036-openssh-8.7p1-recursive-scp.patch (73%) rename openssh-8.7p1-minrsabits.patch => 0037-openssh-8.7p1-minrsabits.patch (63%) create mode 100644 0038-openssh-8.7p1-ibmca.patch rename openssh-7.6p1-audit.patch => 0039-openssh-7.6p1-audit.patch (83%) rename openssh-7.1p2-audit-race-condition.patch => 0040-openssh-7.1p2-audit-race-condition.patch (73%) rename openssh-9.0p1-audit-log.patch => 0041-openssh-9.0p1-audit-log.patch (85%) rename openssh-7.7p1-fips.patch => 0042-openssh-7.7p1-fips.patch (77%) create mode 100644 0043-openssh-8.7p1-ssh-manpage.patch rename openssh-8.7p1-negotiate-supported-algs.patch => 0044-openssh-8.7p1-negotiate-supported-algs.patch (74%) rename openssh-9.0p1-evp-fips-kex.patch => 0045-openssh-9.0p1-evp-fips-kex.patch (90%) rename openssh-8.7p1-nohostsha1proof.patch => 0046-openssh-8.7p1-nohostsha1proof.patch (69%) create mode 100644 0047-openssh-9.6p1-pam-rhost.patch create mode 100644 0048-openssh-9.9p1-separate-keysign.patch rename openssh-9.9p1-openssl-mlkem.patch => 0049-openssh-9.9p1-openssl-mlkem.patch (94%) create mode 100644 0050-openssh-9.9p2-error_processing.patch create mode 100644 1000-openssh-coverity.patch delete mode 100644 openssh-5.8p2-sigpipe.patch delete mode 100644 openssh-6.4p1-fromto-remote.patch delete mode 100644 openssh-6.6.1p1-scp-non-existing-directory.patch delete mode 100644 openssh-6.7p1-coverity.patch delete mode 100644 openssh-6.8p1-sshdT-output.patch delete mode 100644 openssh-7.5p1-sandbox.patch delete mode 100644 openssh-8.0p1-keygen-strip-doseol.patch delete mode 100644 openssh-8.7p1-ibmca.patch delete mode 100644 openssh-8.7p1-ssh-manpage.patch delete mode 100644 openssh-9.6p1-pam-rhost.patch delete mode 100644 openssh-9.9p1-match-regression.patch delete mode 100644 openssh-9.9p1-mlkembe.patch delete mode 100644 openssh-9.9p1-separate-keysign.patch delete mode 100644 openssh-9.9p2-error_processing.patch diff --git a/.gitignore b/.gitignore index 7004cb5..c400ff6 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,5 @@ pam_ssh_agent_auth-0.9.2.tar.bz2 /openssh-9.8p1.tar.gz.asc /openssh-9.9p1.tar.gz /openssh-9.9p1.tar.gz.asc +/openssh-10.0p1.tar.gz +/openssh-10.0p1.tar.gz.asc diff --git a/openssh-7.8p1-role-mls.patch b/0001-openssh-7.8p1-role-mls.patch similarity index 80% rename from openssh-7.8p1-role-mls.patch rename to 0001-openssh-7.8p1-role-mls.patch index 7c6d0ca..c08e414 100644 --- a/openssh-7.8p1-role-mls.patch +++ b/0001-openssh-7.8p1-role-mls.patch @@ -1,46 +1,75 @@ -diff -up openssh/auth2.c.role-mls openssh/auth2.c ---- openssh/auth2.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/auth2.c 2018-08-22 11:14:56.815430916 +0200 -@@ -256,6 +256,9 @@ input_userauth_request(int type, u_int32 - Authctxt *authctxt = ssh->authctxt; - Authmethod *m = NULL; - char *user = NULL, *service = NULL, *method = NULL, *style = NULL; +From 95f4e30195382c3df7104c2ad3e5e9953f8ad554 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 01/50] openssh-7.8p1-role-mls + +--- + auth-pam.c | 2 +- + auth-pam.h | 2 +- + auth.h | 3 + + auth2-gss.c | 11 +- + auth2-hostbased.c | 9 + + auth2-pubkey.c | 11 +- + auth2.c | 14 ++ + misc.c | 8 + + monitor.c | 37 ++- + monitor.h | 4 + + monitor_wrap.c | 21 ++ + monitor_wrap.h | 3 + + openbsd-compat/Makefile.in | 3 +- + openbsd-compat/port-linux-sshd.c | 420 +++++++++++++++++++++++++++++++ + openbsd-compat/port-linux.c | 37 +-- + openbsd-compat/port-linux.h | 3 +- + platform.c | 2 +- + sshd-session.c | 3 + + 18 files changed, 551 insertions(+), 42 deletions(-) + create mode 100644 openbsd-compat/port-linux-sshd.c + +diff --git a/auth-pam.c b/auth-pam.c +index 13c0a792..b4100ea1 100644 +--- a/auth-pam.c ++++ b/auth-pam.c +@@ -1238,7 +1238,7 @@ is_pam_session_open(void) + * during the ssh authentication process. + */ + int +-do_pam_putenv(char *name, char *value) ++do_pam_putenv(char *name, const char *value) + { + int ret = 1; + char *compound; +diff --git a/auth-pam.h b/auth-pam.h +index 8d801c68..9dd7ae07 100644 +--- a/auth-pam.h ++++ b/auth-pam.h +@@ -33,7 +33,7 @@ u_int do_pam_account(void); + void do_pam_session(struct ssh *); + void do_pam_setcred(void); + void do_pam_chauthtok(void); +-int do_pam_putenv(char *, char *); ++int do_pam_putenv(char *, const char *); + char ** fetch_pam_environment(void); + char ** fetch_pam_child_environment(void); + void free_pam_environment(char **); +diff --git a/auth.h b/auth.h +index 98bb23d4..83d07ae8 100644 +--- a/auth.h ++++ b/auth.h +@@ -65,6 +65,9 @@ struct Authctxt { + char *service; + struct passwd *pw; /* set if 'valid' */ + char *style; +#ifdef WITH_SELINUX -+ char *role = NULL; ++ char *role; +#endif - int r, authenticated = 0; - double tstart = monotime_double(); -@@ -268,6 +271,11 @@ input_userauth_request(int type, u_int32 - debug("userauth-request for user %s service %s method %s", user, service, method); - debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); - -+#ifdef WITH_SELINUX -+ if ((role = strchr(user, '/')) != NULL) -+ *role++ = 0; -+#endif -+ - if ((style = strchr(user, ':')) != NULL) - *style++ = 0; - -@@ -314,7 +314,13 @@ input_userauth_request(int type, u_int32 - setproctitle("%s [net]", authctxt->valid ? user : "unknown"); - authctxt->service = xstrdup(service); - authctxt->style = style ? xstrdup(style) : NULL; -+#ifdef WITH_SELINUX -+ authctxt->role = role ? xstrdup(role) : NULL; -+#endif - mm_inform_authserv(service, style); -+#ifdef WITH_SELINUX -+ mm_inform_authrole(role); -+#endif - userauth_banner(ssh); - if ((r = kex_server_update_ext_info(ssh)) != 0) - fatal_fr(r, "kex_server_update_ext_info failed"); -diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c ---- openssh/auth2-gss.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/auth2-gss.c 2018-08-22 11:15:42.459799171 +0200 -@@ -281,6 +281,7 @@ input_gssapi_mic(int type, u_int32_t ple + /* Method lists for multiple authentication */ + char **auth_methods; /* modified from server config */ +diff --git a/auth2-gss.c b/auth2-gss.c +index 75eb4e3a..f7898ab3 100644 +--- a/auth2-gss.c ++++ b/auth2-gss.c +@@ -284,6 +284,7 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) Authctxt *authctxt = ssh->authctxt; Gssctxt *gssctxt; int r, authenticated = 0; @@ -48,7 +77,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c struct sshbuf *b; gss_buffer_desc mic, gssbuf; u_char *p; -@@ -298,7 +299,13 @@ input_gssapi_mic(int type, u_int32_t ple +@@ -300,7 +301,13 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) fatal_f("sshbuf_new failed"); mic.value = p; mic.length = len; @@ -63,7 +92,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c "gssapi-with-mic", ssh->kex->session_id); if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) -@@ -311,6 +318,8 @@ input_gssapi_mic(int type, u_int32_t ple +@@ -313,6 +320,8 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) logit("GSSAPI MIC check failed"); sshbuf_free(b); @@ -72,10 +101,11 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c free(mic.value); authctxt->postponed = 0; -diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c ---- openssh/auth2-hostbased.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/auth2-hostbased.c 2018-08-22 11:14:56.816430924 +0200 -@@ -123,7 +123,16 @@ userauth_hostbased(struct ssh *ssh) +diff --git a/auth2-hostbased.c b/auth2-hostbased.c +index eb21479a..a3be6e49 100644 +--- a/auth2-hostbased.c ++++ b/auth2-hostbased.c +@@ -129,7 +129,16 @@ userauth_hostbased(struct ssh *ssh, const char *method) /* reconstruct packet */ if ((r = sshbuf_put_stringb(b, ssh->kex->session_id)) != 0 || (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || @@ -92,10 +122,11 @@ diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || (r = sshbuf_put_cstring(b, method)) != 0 || (r = sshbuf_put_string(b, pkalg, alen)) != 0 || -diff -up openssh/auth2-pubkey.c.role-mls openssh/auth2-pubkey.c ---- openssh/auth2-pubkey.c.role-mls 2018-08-22 11:14:56.816430924 +0200 -+++ openssh/auth2-pubkey.c 2018-08-22 11:17:07.331483958 +0200 -@@ -169,9 +169,16 @@ userauth_pubkey(struct ssh *ssh) +diff --git a/auth2-pubkey.c b/auth2-pubkey.c +index aa24fda0..267a27d2 100644 +--- a/auth2-pubkey.c ++++ b/auth2-pubkey.c +@@ -206,9 +206,16 @@ userauth_pubkey(struct ssh *ssh, const char *method) goto done; } /* reconstruct packet */ @@ -114,47 +145,51 @@ diff -up openssh/auth2-pubkey.c.role-mls openssh/auth2-pubkey.c if ((r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_REQUEST)) != 0 || (r = sshbuf_put_cstring(b, userstyle)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || -diff -up openssh/auth.h.role-mls openssh/auth.h ---- openssh/auth.h.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/auth.h 2018-08-22 11:14:56.816430924 +0200 -@@ -65,6 +65,9 @@ struct Authctxt { - char *service; - struct passwd *pw; /* set if 'valid' */ - char *style; +diff --git a/auth2.c b/auth2.c +index 82f6e621..5ba45c12 100644 +--- a/auth2.c ++++ b/auth2.c +@@ -271,6 +271,9 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) + Authctxt *authctxt = ssh->authctxt; + Authmethod *m = NULL; + char *user = NULL, *service = NULL, *method = NULL, *style = NULL; +#ifdef WITH_SELINUX -+ char *role; ++ char *role = NULL; +#endif + int r, authenticated = 0; + double tstart = monotime_double(); - /* Method lists for multiple authentication */ - char **auth_methods; /* modified from server config */ -diff -up openssh/auth-pam.c.role-mls openssh/auth-pam.c ---- openssh/auth-pam.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/auth-pam.c 2018-08-22 11:14:56.816430924 +0200 -@@ -1172,7 +1172,7 @@ is_pam_session_open(void) - * during the ssh authentication process. - */ - int --do_pam_putenv(char *name, char *value) -+do_pam_putenv(char *name, const char *value) - { - int ret = 1; - char *compound; -diff -up openssh/auth-pam.h.role-mls openssh/auth-pam.h ---- openssh/auth-pam.h.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/auth-pam.h 2018-08-22 11:14:56.817430932 +0200 -@@ -33,7 +33,7 @@ u_int do_pam_account(void); - void do_pam_session(struct ssh *); - void do_pam_setcred(void); - void do_pam_chauthtok(void); --int do_pam_putenv(char *, char *); -+int do_pam_putenv(char *, const char *); - char ** fetch_pam_environment(void); - char ** fetch_pam_child_environment(void); - void free_pam_environment(char **); -diff -up openssh/misc.c.role-mls openssh/misc.c ---- openssh/misc.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/misc.c 2018-08-22 11:14:56.817430932 +0200 -@@ -542,6 +542,7 @@ char * +@@ -284,6 +287,11 @@ 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); + ++#ifdef WITH_SELINUX ++ if ((role = strchr(user, '/')) != NULL) ++ *role++ = 0; ++#endif ++ + if ((style = strchr(user, ':')) != NULL) + *style++ = 0; + +@@ -313,7 +321,13 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) + setproctitle("%s [net]", authctxt->valid ? user : "unknown"); + authctxt->service = xstrdup(service); + authctxt->style = style ? xstrdup(style) : NULL; ++#ifdef WITH_SELINUX ++ authctxt->role = role ? xstrdup(role) : NULL; ++#endif + mm_inform_authserv(service, style); ++#ifdef WITH_SELINUX ++ mm_inform_authrole(role); ++#endif + userauth_banner(ssh); + if ((r = kex_server_update_ext_info(ssh)) != 0) + fatal_fr(r, "kex_server_update_ext_info failed"); +diff --git a/misc.c b/misc.c +index dd0bd032..c932f9bb 100644 +--- a/misc.c ++++ b/misc.c +@@ -806,6 +806,7 @@ char * colon(char *cp) { int flag = 0; @@ -162,7 +197,7 @@ diff -up openssh/misc.c.role-mls openssh/misc.c if (*cp == ':') /* Leading colon is part of file name. */ return NULL; -@@ -557,6 +558,13 @@ colon(char *cp) +@@ -821,6 +822,13 @@ colon(char *cp) return (cp); if (*cp == '/') return NULL; @@ -176,10 +211,11 @@ diff -up openssh/misc.c.role-mls openssh/misc.c } return NULL; } -diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c ---- openssh-8.6p1/monitor.c.role-mls 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/monitor.c 2021-05-21 14:21:56.719414087 +0200 -@@ -117,6 +117,9 @@ int mm_answer_sign(struct ssh *, int, st +diff --git a/monitor.c b/monitor.c +index 2179553d..02b3eaaa 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -120,6 +120,9 @@ int mm_answer_sign(struct ssh *, int, struct sshbuf *); int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); int mm_answer_authserv(struct ssh *, int, struct sshbuf *); @@ -189,7 +225,7 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); -@@ -195,6 +198,9 @@ struct mon_table mon_dispatch_proto20[] +@@ -194,6 +197,9 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, @@ -199,7 +235,7 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM -@@ -803,6 +809,9 @@ mm_answer_pwnamallow(struct ssh *ssh, in +@@ -912,6 +918,9 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) /* Allow service/style information on the auth context */ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); @@ -209,7 +245,7 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); #ifdef USE_PAM -@@ -877,6 +886,26 @@ key_base_type_match(const char *method, +@@ -986,6 +995,26 @@ key_base_type_match(const char *method, const struct sshkey *key, return found; } @@ -236,16 +272,16 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c int mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) { -@@ -1251,7 +1280,7 @@ monitor_valid_userblob(struct ssh *ssh, +@@ -1358,7 +1387,7 @@ monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) struct sshbuf *b; - struct sshkey *hostkey = NULL; + struct sshkey *hostkey = NULL; const u_char *p; - char *userstyle, *cp; + char *userstyle, *s, *cp; size_t len; u_char type; int hostbound = 0, r, fail = 0; -@@ -1282,6 +1311,8 @@ monitor_valid_userblob(struct ssh *ssh, +@@ -1389,6 +1418,8 @@ monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse userstyle"); @@ -254,7 +290,7 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); -@@ -1317,7 +1348,7 @@ monitor_valid_hostbasedblob(const u_char +@@ -1439,7 +1470,7 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen, { struct sshbuf *b; const u_char *p; @@ -263,7 +299,7 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c size_t len; int r, fail = 0; u_char type; -@@ -1338,6 +1370,8 @@ monitor_valid_hostbasedblob(const u_char +@@ -1460,6 +1491,8 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen, fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse userstyle"); @@ -272,12 +308,13 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); -diff -up openssh/monitor.h.role-mls openssh/monitor.h ---- openssh/monitor.h.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/monitor.h 2018-08-22 11:14:56.818430941 +0200 -@@ -55,6 +55,10 @@ enum monitor_reqtype { - MONITOR_REQ_GSSCHECKMIC = 48, MONITOR_ANS_GSSCHECKMIC = 49, +diff --git a/monitor.h b/monitor.h +index 3f8a9bea..9dcd9c29 100644 +--- a/monitor.h ++++ b/monitor.h +@@ -56,6 +56,10 @@ enum monitor_reqtype { MONITOR_REQ_TERM = 50, + MONITOR_REQ_STATE = 51, MONITOR_ANS_STATE = 52, +#ifdef WITH_SELINUX + MONITOR_REQ_AUTHROLE = 80, @@ -286,10 +323,11 @@ diff -up openssh/monitor.h.role-mls openssh/monitor.h MONITOR_REQ_PAM_START = 100, MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105, -diff -up openssh/monitor_wrap.c.role-mls openssh/monitor_wrap.c ---- openssh/monitor_wrap.c.role-mls 2018-08-22 11:14:56.818430941 +0200 -+++ openssh/monitor_wrap.c 2018-08-22 11:21:47.938747968 +0200 -@@ -390,6 +390,27 @@ mm_inform_authserv(char *service, char * +diff --git a/monitor_wrap.c b/monitor_wrap.c +index bd900b2f..ef3ab1b1 100644 +--- a/monitor_wrap.c ++++ b/monitor_wrap.c +@@ -442,6 +442,27 @@ mm_inform_authserv(char *service, char *style) sshbuf_free(m); } @@ -317,10 +355,11 @@ diff -up openssh/monitor_wrap.c.role-mls openssh/monitor_wrap.c /* Do the password authentication */ int mm_auth_password(struct ssh *ssh, char *password) -diff -up openssh/monitor_wrap.h.role-mls openssh/monitor_wrap.h ---- openssh/monitor_wrap.h.role-mls 2018-08-22 11:14:56.818430941 +0200 -+++ openssh/monitor_wrap.h 2018-08-22 11:22:10.439929513 +0200 -@@ -44,6 +44,9 @@ DH *mm_choose_dh(int, int, int); +diff --git a/monitor_wrap.h b/monitor_wrap.h +index 7134afee..38a280c8 100644 +--- a/monitor_wrap.h ++++ b/monitor_wrap.h +@@ -46,6 +46,9 @@ int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *, const char *, const char *, u_int compat); void mm_inform_authserv(char *, char *); @@ -330,10 +369,11 @@ diff -up openssh/monitor_wrap.h.role-mls openssh/monitor_wrap.h struct passwd *mm_getpwnamallow(struct ssh *, const char *); char *mm_auth2_read_banner(void); int mm_auth_password(struct ssh *, char *); -diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Makefile.in ---- openssh/openbsd-compat/Makefile.in.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/openbsd-compat/Makefile.in 2018-08-22 11:14:56.819430949 +0200 -@@ -92,7 +92,8 @@ PORTS= port-aix.o \ +diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in +index 1d549954..78e6fa5b 100644 +--- a/openbsd-compat/Makefile.in ++++ b/openbsd-compat/Makefile.in +@@ -100,7 +100,8 @@ PORTS= port-aix.o \ port-prngd.o \ port-solaris.o \ port-net.o \ @@ -343,78 +383,11 @@ diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Make .c.o: $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< -diff -up openssh/openbsd-compat/port-linux.c.role-mls openssh/openbsd-compat/port-linux.c ---- openssh/openbsd-compat/port-linux.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/openbsd-compat/port-linux.c 2018-08-22 11:14:56.819430949 +0200 -@@ -100,37 +100,6 @@ ssh_selinux_getctxbyname(char *pwname) - return sc; - } - --/* Set the execution context to the default for the specified user */ --void --ssh_selinux_setup_exec_context(char *pwname) --{ -- char *user_ctx = NULL; -- -- if (!ssh_selinux_enabled()) -- return; -- -- debug3("%s: setting execution context", __func__); -- -- user_ctx = ssh_selinux_getctxbyname(pwname); -- if (setexeccon(user_ctx) != 0) { -- switch (security_getenforce()) { -- case -1: -- fatal("%s: security_getenforce() failed", __func__); -- case 0: -- error("%s: Failed to set SELinux execution " -- "context for %s", __func__, pwname); -- break; -- default: -- fatal("%s: Failed to set SELinux execution context " -- "for %s (in enforcing mode)", __func__, pwname); -- } -- } -- if (user_ctx != NULL) -- freecon(user_ctx); -- -- debug3("%s: done", __func__); --} -- - /* Set the TTY context for the specified user */ - void - ssh_selinux_setup_pty(char *pwname, const char *tty) -@@ -145,7 +114,11 @@ ssh_selinux_setup_pty(char *pwname, cons - - debug3("%s: setting TTY context on %s", __func__, tty); - -- user_ctx = ssh_selinux_getctxbyname(pwname); -+ if (getexeccon(&user_ctx) != 0) { -+ error_f("getexeccon: %s", strerror(errno)); -+ goto out; -+ } -+ - - /* XXX: should these calls fatal() upon failure in enforcing mode? */ - -diff -up openssh/openbsd-compat/port-linux.h.role-mls openssh/openbsd-compat/port-linux.h ---- openssh/openbsd-compat/port-linux.h.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/openbsd-compat/port-linux.h 2018-08-22 11:14:56.819430949 +0200 -@@ -20,9 +20,10 @@ - #ifdef WITH_SELINUX - int ssh_selinux_enabled(void); - void ssh_selinux_setup_pty(char *, const char *); --void ssh_selinux_setup_exec_context(char *); - void ssh_selinux_change_context(const char *); - void ssh_selinux_setfscreatecon(const char *); -+ -+void sshd_selinux_setup_exec_context(char *); - #endif - - #ifdef LINUX_OOM_ADJUST -diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compat/port-linux-sshd.c ---- openssh/openbsd-compat/port-linux-sshd.c.role-mls 2018-08-22 11:14:56.819430949 +0200 -+++ openssh/openbsd-compat/port-linux-sshd.c 2018-08-22 11:14:56.819430949 +0200 +diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c +new file mode 100644 +index 00000000..b9fbe38b +--- /dev/null ++++ b/openbsd-compat/port-linux-sshd.c @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2005 Daniel Walsh @@ -836,10 +809,82 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa +#endif +#endif + -diff -up openssh/platform.c.role-mls openssh/platform.c ---- openssh/platform.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/platform.c 2018-08-22 11:14:56.819430949 +0200 -@@ -183,7 +183,7 @@ platform_setusercontext_post_groups(stru +diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c +index c1d54f38..7426f6f7 100644 +--- a/openbsd-compat/port-linux.c ++++ b/openbsd-compat/port-linux.c +@@ -109,37 +109,6 @@ ssh_selinux_getctxbyname(char *pwname) + return sc; + } + +-/* Set the execution context to the default for the specified user */ +-void +-ssh_selinux_setup_exec_context(char *pwname) +-{ +- char *user_ctx = NULL; +- +- if (!ssh_selinux_enabled()) +- return; +- +- debug3("%s: setting execution context", __func__); +- +- user_ctx = ssh_selinux_getctxbyname(pwname); +- if (setexeccon(user_ctx) != 0) { +- switch (security_getenforce()) { +- case -1: +- fatal("%s: security_getenforce() failed", __func__); +- case 0: +- error("%s: Failed to set SELinux execution " +- "context for %s", __func__, pwname); +- break; +- default: +- fatal("%s: Failed to set SELinux execution context " +- "for %s (in enforcing mode)", __func__, pwname); +- } +- } +- if (user_ctx != NULL) +- freecon(user_ctx); +- +- debug3("%s: done", __func__); +-} +- + /* Set the TTY context for the specified user */ + void + ssh_selinux_setup_pty(char *pwname, const char *tty) +@@ -152,7 +121,11 @@ ssh_selinux_setup_pty(char *pwname, const char *tty) + + debug3("%s: setting TTY context on %s", __func__, tty); + +- user_ctx = ssh_selinux_getctxbyname(pwname); ++ if (getexeccon(&user_ctx) != 0) { ++ error_f("getexeccon: %s", strerror(errno)); ++ goto out; ++ } ++ + + /* XXX: should these calls fatal() upon failure in enforcing mode? */ + +diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h +index 959430de..055c825e 100644 +--- a/openbsd-compat/port-linux.h ++++ b/openbsd-compat/port-linux.h +@@ -20,9 +20,10 @@ + #ifdef WITH_SELINUX + int ssh_selinux_enabled(void); + void ssh_selinux_setup_pty(char *, const char *); +-void ssh_selinux_setup_exec_context(char *); + void ssh_selinux_change_context(const char *); + void ssh_selinux_setfscreatecon(const char *); ++ ++void sshd_selinux_setup_exec_context(char *); + #endif + + #ifdef LINUX_OOM_ADJUST +diff --git a/platform.c b/platform.c +index 4c4fe57e..1bfb4bea 100644 +--- a/platform.c ++++ b/platform.c +@@ -140,7 +140,7 @@ platform_setusercontext_post_groups(struct passwd *pw) } #endif /* HAVE_SETPCRED */ #ifdef WITH_SELINUX @@ -848,10 +893,11 @@ diff -up openssh/platform.c.role-mls openssh/platform.c #endif } -diff -up openssh/sshd.c.role-mls openssh/sshd.c ---- openssh/sshd-session.c.role-mls 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/sshd-session.c 2018-08-22 11:14:56.820430957 +0200 -@@ -2186,6 +2186,9 @@ main(int ac, char **av) +diff --git a/sshd-session.c b/sshd-session.c +index c64eb29f..74d2cbc7 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -1328,6 +1328,9 @@ main(int ac, char **av) restore_uid(); } #endif @@ -861,3 +907,6 @@ diff -up openssh/sshd.c.role-mls openssh/sshd.c #ifdef USE_PAM if (options.use_pam) { do_pam_setcred(); +-- +2.49.0 + diff --git a/openssh-6.6p1-privsep-selinux.patch b/0002-openssh-6.6p1-privsep-selinux.patch similarity index 52% rename from openssh-6.6p1-privsep-selinux.patch rename to 0002-openssh-6.6p1-privsep-selinux.patch index 16d98cd..32d3c64 100644 --- a/openssh-6.6p1-privsep-selinux.patch +++ b/0002-openssh-6.6p1-privsep-selinux.patch @@ -1,18 +1,21 @@ -diff -up openssh-7.4p1/openbsd-compat/port-linux.h.privsep-selinux openssh-7.4p1/openbsd-compat/port-linux.h ---- openssh-7.4p1/openbsd-compat/port-linux.h.privsep-selinux 2016-12-23 18:58:52.972122201 +0100 -+++ openssh-7.4p1/openbsd-compat/port-linux.h 2016-12-23 18:58:52.974122201 +0100 -@@ -23,6 +23,7 @@ void ssh_selinux_setup_pty(char *, const - void ssh_selinux_change_context(const char *); - void ssh_selinux_setfscreatecon(const char *); - -+void sshd_selinux_copy_context(void); - void sshd_selinux_setup_exec_context(char *); - #endif - -diff -up openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux openssh-7.4p1/openbsd-compat/port-linux-sshd.c ---- openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100 -+++ openssh-7.4p1/openbsd-compat/port-linux-sshd.c 2016-12-23 18:58:52.974122201 +0100 -@@ -419,6 +419,28 @@ sshd_selinux_setup_exec_context(char *pw +From 99d8e250514023d3b88a1c9eb724c4898aba9827 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 02/50] openssh-6.6p1-privsep-selinux + +--- + openbsd-compat/port-linux-sshd.c | 22 ++++++++++++++++++++++ + openbsd-compat/port-linux.h | 1 + + session.c | 16 +++++++++------- + sshd-auth.c | 4 ++++ + sshd-session.c | 2 +- + 5 files changed, 37 insertions(+), 8 deletions(-) + +diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c +index b9fbe38b..dfafc622 100644 +--- a/openbsd-compat/port-linux-sshd.c ++++ b/openbsd-compat/port-linux-sshd.c +@@ -415,6 +415,28 @@ sshd_selinux_setup_exec_context(char *pwname) debug3_f("done"); } @@ -41,10 +44,23 @@ diff -up openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux openssh- #endif #endif -diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c ---- openssh-7.4p1/session.c.privsep-selinux 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/session.c 2016-12-23 18:58:52.974122201 +0100 -@@ -1331,7 +1331,7 @@ do_setusercontext(struct passwd *pw) +diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h +index 055c825e..498d242a 100644 +--- a/openbsd-compat/port-linux.h ++++ b/openbsd-compat/port-linux.h +@@ -23,6 +23,7 @@ void ssh_selinux_setup_pty(char *, const char *); + void ssh_selinux_change_context(const char *); + void ssh_selinux_setfscreatecon(const char *); + ++void sshd_selinux_copy_context(void); + void sshd_selinux_setup_exec_context(char *); + #endif + +diff --git a/session.c b/session.c +index 6444c77f..e4657cef 100644 +--- a/session.c ++++ b/session.c +@@ -1350,7 +1350,7 @@ do_setusercontext(struct passwd *pw) platform_setusercontext(pw); @@ -53,17 +69,17 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c #ifdef HAVE_LOGIN_CAP if (setusercontext(lc, pw, pw->pw_uid, (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { -@@ -1361,6 +1361,9 @@ do_setusercontext(struct passwd *pw) - (unsigned long long)pw->pw_uid); - chroot_path = percent_expand(tmp, "h", pw->pw_dir, - "u", pw->pw_name, "U", uidstr, (char *)NULL); +@@ -1382,6 +1382,9 @@ do_setusercontext(struct passwd *pw) + (unsigned long long)pw->pw_uid); + chroot_path = percent_expand(tmp, "h", pw->pw_dir, + "u", pw->pw_name, "U", uidstr, (char *)NULL); +#ifdef WITH_SELINUX + sshd_selinux_copy_context(); +#endif safely_chroot(chroot_path, pw->pw_uid); free(tmp); free(chroot_path); -@@ -1396,6 +1399,11 @@ do_setusercontext(struct passwd *pw) +@@ -1417,6 +1420,11 @@ do_setusercontext(struct passwd *pw) /* Permanently switch to the desired uid. */ permanently_set_uid(pw); #endif @@ -75,17 +91,17 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c } else if (options.chroot_directory != NULL && strcasecmp(options.chroot_directory, "none") != 0) { fatal("server lacks privileges to chroot to ChrootDirectory"); -@@ -1413,9 +1421,6 @@ do_pwchange(Session *s) +@@ -1434,9 +1442,6 @@ do_pwchange(Session *s) if (s->ttyfd != -1) { fprintf(stderr, - "You must change your password now and login again!\n"); + "You must change your password now and log in again!\n"); -#ifdef WITH_SELINUX - setexeccon(NULL); -#endif #ifdef PASSWD_NEEDS_USERNAME execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name, (char *)NULL); -@@ -1625,9 +1630,6 @@ do_child(Session *s, const char *command +@@ -1649,9 +1654,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) argv[i] = NULL; optind = optreset = 1; __progname = argv[0]; @@ -95,13 +111,14 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c exit(sftp_server_main(i, argv, s->pw)); } -diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c ---- openssh-7.4p1/sshd-session.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100 -+++ openssh-7.4p1/sshd-session.c 2016-12-23 18:59:13.808124269 +0100 -@@ -540,6 +540,10 @@ privsep_preauth_child(void) - /* Demote the private keys to public keys. */ - demote_sensitive_data(); - +diff --git a/sshd-auth.c b/sshd-auth.c +index 30eecd8a..f957dc22 100644 +--- a/sshd-auth.c ++++ b/sshd-auth.c +@@ -187,6 +187,10 @@ privsep_child_demote(void) + if ((box = ssh_sandbox_init(pmonitor)) == NULL) + fatal_f("ssh_sandbox_init failed"); + #endif +#ifdef WITH_SELINUX + ssh_selinux_change_context("sshd_net_t"); +#endif @@ -109,7 +126,11 @@ diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c /* Demote the child */ if (privsep_chroot) { /* Change our root directory */ -@@ -403,7 +403,7 @@ privsep_postauth(struct ssh *ssh, Authct +diff --git a/sshd-session.c b/sshd-session.c +index 74d2cbc7..4a148db4 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -432,7 +432,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) * fd passing, as AFAIK PTY allocation on this platform doesn't require * special privileges to begin with. */ @@ -118,3 +139,6 @@ diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c skip_privdrop = 1; #endif +-- +2.49.0 + diff --git a/openssh-6.6p1-keycat.patch b/0003-openssh-6.6p1-keycat.patch similarity index 77% rename from openssh-6.6p1-keycat.patch rename to 0003-openssh-6.6p1-keycat.patch index 4eb0998..b46b378 100644 --- a/openssh-6.6p1-keycat.patch +++ b/0003-openssh-6.6p1-keycat.patch @@ -1,23 +1,26 @@ -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 -@@ -966,6 +966,13 @@ subprocess(const char *tag, struct passw - error("%s: dup2: %s", tag, strerror(errno)); - _exit(1); - } -+#ifdef WITH_SELINUX -+ if (sshd_selinux_setup_env_variables() < 0) { -+ error ("failed to copy environment: %s", -+ strerror(errno)); -+ _exit(127); -+ } -+#endif - if (env != NULL) - execve(av[0], av, env); - else -diff -up openssh/HOWTO.ssh-keycat.keycat openssh/HOWTO.ssh-keycat ---- openssh/HOWTO.ssh-keycat.keycat 2015-06-24 10:57:50.157849608 +0200 -+++ openssh/HOWTO.ssh-keycat 2015-06-24 10:57:50.157849608 +0200 +From 5e35e18a419a5a66b6e1cb2b98beaaf4d9db0dc6 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 03/50] openssh-6.6p1-keycat + +--- + HOWTO.ssh-keycat | 12 ++ + Makefile.in | 8 +- + configure.ac | 6 + + misc.c | 7 + + openbsd-compat/port-linux-sshd.c | 44 +++++- + openbsd-compat/port-linux.h | 2 + + platform.c | 2 +- + ssh-keycat.c | 241 +++++++++++++++++++++++++++++++ + 8 files changed, 314 insertions(+), 8 deletions(-) + create mode 100644 HOWTO.ssh-keycat + create mode 100644 ssh-keycat.c + +diff --git a/HOWTO.ssh-keycat b/HOWTO.ssh-keycat +new file mode 100644 +index 00000000..630ec628 +--- /dev/null ++++ b/HOWTO.ssh-keycat @@ -0,0 +1,12 @@ +The ssh-keycat retrieves the content of the ~/.ssh/authorized_keys +of an user in any environment. This includes environments with @@ -31,35 +34,36 @@ diff -up openssh/HOWTO.ssh-keycat.keycat openssh/HOWTO.ssh-keycat + PubkeyAuthentication yes + + -diff -up openssh/Makefile.in.keycat openssh/Makefile.in ---- openssh/Makefile.in.keycat 2015-06-24 10:57:50.152849621 +0200 -+++ openssh/Makefile.in 2015-06-24 10:57:50.157849608 +0200 -@@ -27,6 +27,7 @@ SFTP_SERVER=$(libexecdir)/sftp-server +diff --git a/Makefile.in b/Makefile.in +index 4617cebc..438efc51 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -23,6 +23,7 @@ SSH_PROGRAM=@bindir@/ssh ASKPASS_PROGRAM=$(libexecdir)/ssh-askpass SFTP_SERVER=$(libexecdir)/sftp-server SSH_KEYSIGN=$(libexecdir)/ssh-keysign +SSH_KEYCAT=$(libexecdir)/ssh-keycat SSHD_SESSION=$(libexecdir)/sshd-session + SSHD_AUTH=$(libexecdir)/sshd-auth SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper - SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper -@@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@ +@@ -57,6 +58,7 @@ CHANNELLIBS=@CHANNELLIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ SSHDLIBS=@SSHDLIBS@ +KEYCATLIBS=@KEYCATLIBS@ LIBEDIT=@LIBEDIT@ LIBFIDO2=@LIBFIDO2@ - AR=@AR@ -@@ -65,7 +66,7 @@ EXEEXT=@EXEEXT@ + LIBWTMPDB=@LIBWTMPDB@ +@@ -74,7 +76,7 @@ MKDIR_P=@MKDIR_P@ .SUFFIXES: .lo --TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) -+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT) +-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) $(SK_STANDALONE) ++TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT) $(SK_STANDALONE) XMSS_OBJS=\ ssh-xmss.o \ -@@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) +@@ -260,6 +262,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS) ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) @@ -69,7 +73,7 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) -@@ -321,6 +325,7 @@ install-files: +@@ -447,6 +452,7 @@ install-files: $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) @@ -77,24 +81,67 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in $(INSTALL) -m 0755 $(STRIP_OPT) sftp$(EXEEXT) $(DESTDIR)$(bindir)/sftp$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -diff -up openssh/openbsd-compat/port-linux.h.keycat openssh/openbsd-compat/port-linux.h ---- openssh/openbsd-compat/port-linux.h.keycat 2015-06-24 10:57:50.150849626 +0200 -+++ openssh/openbsd-compat/port-linux.h 2015-06-24 10:57:50.160849601 +0200 -@@ -25,8 +25,10 @@ void ssh_selinux_setup_pty(char *, const - void ssh_selinux_change_context(const char *); - void ssh_selinux_setfscreatecon(const char *); +diff --git a/configure.ac b/configure.ac +index ee77a048..d546788c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -3566,6 +3566,7 @@ AC_ARG_WITH([pam], + PAM_MSG="yes" -+int sshd_selinux_enabled(void); - void sshd_selinux_copy_context(void); - void sshd_selinux_setup_exec_context(char *); -+int sshd_selinux_setup_env_variables(void); - #endif + SSHDLIBS="$SSHDLIBS -lpam" ++ KEYCATLIBS="$KEYCATLIBS -lpam" + AC_DEFINE([USE_PAM], [1], + [Define if you want to enable PAM support]) - #ifdef LINUX_OOM_ADJUST -diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/port-linux-sshd.c ---- openssh/openbsd-compat/port-linux-sshd.c.keycat 2015-06-24 10:57:50.150849626 +0200 -+++ openssh/openbsd-compat/port-linux-sshd.c 2015-06-24 10:57:50.159849603 +0200 -@@ -54,6 +54,20 @@ extern Authctxt *the_authctxt; +@@ -3576,6 +3577,7 @@ AC_ARG_WITH([pam], + ;; + *) + SSHDLIBS="$SSHDLIBS -ldl" ++ KEYCATLIBS="$KEYCATLIBS -ldl" + ;; + esac + fi +@@ -4801,6 +4803,7 @@ AC_ARG_WITH([selinux], + fi ] + ) + AC_SUBST([SSHDLIBS]) ++AC_SUBST([KEYCATLIBS]) + + # Check whether user wants Kerberos 5 support + KRB5_MSG="no" +@@ -5812,6 +5815,9 @@ fi + if test ! -z "${SSHDLIBS}"; then + echo " +for sshd: ${SSHDLIBS}" + fi ++if test ! -z "${KEYCATLIBS}"; then ++echo " +for ssh-keycat: ${KEYCATLIBS}" ++fi + + echo "" + +diff --git a/misc.c b/misc.c +index c932f9bb..1e31acc9 100644 +--- a/misc.c ++++ b/misc.c +@@ -2897,6 +2897,13 @@ subprocess(const char *tag, const char *command, + error("%s: dup2: %s", tag, strerror(errno)); + _exit(1); + } ++#ifdef WITH_SELINUX ++ if (sshd_selinux_setup_env_variables() < 0) { ++ error ("failed to copy environment: %s", ++ strerror(errno)); ++ _exit(127); ++ } ++#endif + if (env != NULL) + execve(av[0], av, env); + else +diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c +index dfafc622..8c5fc1fe 100644 +--- a/openbsd-compat/port-linux-sshd.c ++++ b/openbsd-compat/port-linux-sshd.c +@@ -52,6 +52,20 @@ extern ServerOptions options; extern Authctxt *the_authctxt; extern int inetd_flag; @@ -115,7 +162,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ /* Send audit message */ static int sshd_selinux_send_audit_message(int success, security_context_t default_context, -@@ -308,7 +322,7 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -317,7 +331,7 @@ sshd_selinux_getctxbyname(char *pwname, /* Setup environment variables for pam_selinux */ static int @@ -124,7 +171,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ { const char *reqlvl; char *role; -@@ -319,16 +333,16 @@ sshd_selinux_setup_pam_variables(void) +@@ -328,16 +342,16 @@ sshd_selinux_setup_pam_variables(void) ssh_selinux_get_role_level(&role, &reqlvl); @@ -144,7 +191,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ if (role != NULL) free(role); -@@ -336,6 +350,24 @@ sshd_selinux_setup_pam_variables(void) +@@ -345,6 +359,24 @@ sshd_selinux_setup_pam_variables(void) return rv; } @@ -169,7 +216,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ /* Set the execution context to the default for the specified user */ void sshd_selinux_setup_exec_context(char *pwname) -@@ -344,7 +376,7 @@ sshd_selinux_setup_exec_context(char *pw +@@ -353,7 +385,7 @@ sshd_selinux_setup_exec_context(char *pwname) int r = 0; security_context_t default_ctx = NULL; @@ -178,7 +225,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ return; if (options.use_pam) { -@@ -415,7 +447,7 @@ sshd_selinux_copy_context(void) +@@ -420,7 +452,7 @@ sshd_selinux_copy_context(void) { security_context_t *ctx; @@ -187,10 +234,26 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/ return; if (getexeccon((security_context_t *)&ctx) != 0) { -diff -up openssh/platform.c.keycat openssh/platform.c ---- openssh/platform.c.keycat 2015-06-24 10:57:50.147849633 +0200 -+++ openssh/platform.c 2015-06-24 10:57:50.160849601 +0200 -@@ -103,7 +103,7 @@ platform_setusercontext(struct passwd *p +diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h +index 498d242a..1b745a76 100644 +--- a/openbsd-compat/port-linux.h ++++ b/openbsd-compat/port-linux.h +@@ -23,8 +23,10 @@ void ssh_selinux_setup_pty(char *, const char *); + void ssh_selinux_change_context(const char *); + void ssh_selinux_setfscreatecon(const char *); + ++int sshd_selinux_enabled(void); + void sshd_selinux_copy_context(void); + void sshd_selinux_setup_exec_context(char *); ++int sshd_selinux_setup_env_variables(void); + #endif + + #ifdef LINUX_OOM_ADJUST +diff --git a/platform.c b/platform.c +index 1bfb4bea..0d12f311 100644 +--- a/platform.c ++++ b/platform.c +@@ -55,7 +55,7 @@ platform_setusercontext(struct passwd *pw) { #ifdef WITH_SELINUX /* Cache selinux status for later use */ @@ -199,9 +262,11 @@ diff -up openssh/platform.c.keycat openssh/platform.c #endif #ifdef USE_SOLARIS_PROJECTS -diff -up openssh/ssh-keycat.c.keycat openssh/ssh-keycat.c ---- openssh/ssh-keycat.c.keycat 2015-06-24 10:57:50.161849599 +0200 -+++ openssh/ssh-keycat.c 2015-06-24 10:57:50.161849599 +0200 +diff --git a/ssh-keycat.c b/ssh-keycat.c +new file mode 100644 +index 00000000..5678be07 +--- /dev/null ++++ b/ssh-keycat.c @@ -0,0 +1,241 @@ +/* + * Redistribution and use in source and binary forms, with or without @@ -444,41 +509,6 @@ diff -up openssh/ssh-keycat.c.keycat openssh/ssh-keycat.c + } + return ev; +} -diff --git a/configure.ac b/configure.ac -index 3bbccfd..6481f1f 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -2952,6 +2952,7 @@ AC_ARG_WITH([pam], - PAM_MSG="yes" - - SSHDLIBS="$SSHDLIBS -lpam" -+ KEYCATLIBS="$KEYCATLIBS -lpam" - AC_DEFINE([USE_PAM], [1], - [Define if you want to enable PAM support]) - -@@ -3105,6 +3106,7 @@ - ;; - *) - SSHDLIBS="$SSHDLIBS -ldl" -+ KEYCATLIBS="$KEYCATLIBS -ldl" - ;; - esac - fi -@@ -4042,6 +4044,7 @@ AC_ARG_WITH([selinux], - fi ] - ) - AC_SUBST([SSHDLIBS]) -+AC_SUBST([KEYCATLIBS]) - - # Check whether user wants Kerberos 5 support - KRB5_MSG="no" -@@ -5031,6 +5034,9 @@ fi - if test ! -z "${SSHDLIBS}"; then - echo " +for sshd: ${SSHDLIBS}" - fi -+if test ! -z "${KEYCATLIBS}"; then -+echo " +for ssh-keycat: ${KEYCATLIBS}" -+fi - - echo "" - +-- +2.49.0 + diff --git a/openssh-6.6p1-allow-ip-opts.patch b/0004-openssh-6.6p1-allow-ip-opts.patch similarity index 68% rename from openssh-6.6p1-allow-ip-opts.patch rename to 0004-openssh-6.6p1-allow-ip-opts.patch index 995e04e..ef15fbf 100644 --- a/openssh-6.6p1-allow-ip-opts.patch +++ b/0004-openssh-6.6p1-allow-ip-opts.patch @@ -1,7 +1,17 @@ -diff -up openssh/sshd.c.ip-opts openssh/sshd.c ---- openssh/sshd-session.c.ip-opts 2016-07-25 13:58:48.998507834 +0200 -+++ openssh/sshd-session.c 2016-07-25 14:01:28.346469878 +0200 -@@ -1507,12 +1507,32 @@ check_ip_options(struct ssh *ssh) +From 28333f1dfe68b0ffc80c2a4799759587b4c32d3e Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 04/50] openssh-6.6p1-allow-ip-opts + +--- + sshd-session.c | 32 ++++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +diff --git a/sshd-session.c b/sshd-session.c +index 4a148db4..a365f26f 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -778,12 +778,32 @@ check_ip_options(struct ssh *ssh) if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, &option_size) >= 0 && option_size != 0) { @@ -40,3 +50,6 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c } #endif /* IP_OPTIONS */ } +-- +2.49.0 + diff --git a/openssh-5.9p1-ipv6man.patch b/0005-openssh-5.9p1-ipv6man.patch similarity index 54% rename from openssh-5.9p1-ipv6man.patch rename to 0005-openssh-5.9p1-ipv6man.patch index ece1a73..909b988 100644 --- a/openssh-5.9p1-ipv6man.patch +++ b/0005-openssh-5.9p1-ipv6man.patch @@ -1,7 +1,18 @@ -diff -up openssh-5.9p0/ssh.1.ipv6man openssh-5.9p0/ssh.1 ---- openssh-5.9p0/ssh.1.ipv6man 2011-08-05 22:17:32.000000000 +0200 -+++ openssh-5.9p0/ssh.1 2011-08-31 13:08:34.880024485 +0200 -@@ -1400,6 +1400,8 @@ manual page for more information. +From 388be633842a9f3e4b0a76fe40cf7035912a913a Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 05/50] openssh-5.9p1-ipv6man + +--- + ssh.1 | 2 ++ + sshd.8 | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/ssh.1 b/ssh.1 +index 697f4e42..db92ac9a 100644 +--- a/ssh.1 ++++ b/ssh.1 +@@ -1663,6 +1663,8 @@ manual page for more information. .Nm exits with the exit status of the remote command or with 255 if an error occurred. @@ -10,10 +21,11 @@ diff -up openssh-5.9p0/ssh.1.ipv6man openssh-5.9p0/ssh.1 .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , -diff -up openssh-5.9p0/sshd.8.ipv6man openssh-5.9p0/sshd.8 ---- openssh-5.9p0/sshd.8.ipv6man 2011-08-05 22:17:32.000000000 +0200 -+++ openssh-5.9p0/sshd.8 2011-08-31 13:10:34.129039094 +0200 -@@ -940,6 +940,8 @@ concurrently for different ports, this c +diff --git a/sshd.8 b/sshd.8 +index 08ebf53a..2aa73271 100644 +--- a/sshd.8 ++++ b/sshd.8 +@@ -1018,6 +1018,8 @@ concurrently for different ports, this contains the process ID of the one started last). The content of this file is not sensitive; it can be world-readable. .El @@ -22,3 +34,6 @@ diff -up openssh-5.9p0/sshd.8.ipv6man openssh-5.9p0/sshd.8 .Sh SEE ALSO .Xr scp 1 , .Xr sftp 1 , +-- +2.49.0 + diff --git a/0006-openssh-5.8p2-sigpipe.patch b/0006-openssh-5.8p2-sigpipe.patch new file mode 100644 index 0000000..5bf31bc --- /dev/null +++ b/0006-openssh-5.8p2-sigpipe.patch @@ -0,0 +1,26 @@ +From 80359feb76fd8061b5ce18f73451d7b9db0c2477 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 06/50] openssh-5.8p2-sigpipe + +--- + ssh-keyscan.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/ssh-keyscan.c b/ssh-keyscan.c +index 3436c0b5..9f76ad22 100644 +--- a/ssh-keyscan.c ++++ b/ssh-keyscan.c +@@ -798,6 +798,9 @@ main(int argc, char **argv) + if (maxfd > fdlim_get(0)) + fdlim_set(maxfd); + fdcon = xcalloc(maxfd, sizeof(con)); ++ ++ signal(SIGPIPE, SIG_IGN); ++ + read_wait = xcalloc(maxfd, sizeof(struct pollfd)); + for (j = 0; j < maxfd; j++) + read_wait[j].fd = -1; +-- +2.49.0 + diff --git a/openssh-7.2p2-x11.patch b/0007-openssh-7.2p2-x11.patch similarity index 71% rename from openssh-7.2p2-x11.patch rename to 0007-openssh-7.2p2-x11.patch index 6db16be..2f72f9a 100644 --- a/openssh-7.2p2-x11.patch +++ b/0007-openssh-7.2p2-x11.patch @@ -1,22 +1,32 @@ -diff --git a/channels.c b/channels.c ---- a/channels.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/channels.c (date 1703026069921) -@@ -5075,11 +5075,13 @@ - } +From cf6d48305cf6601448ea7a0d96ae825cbbbf0a2c Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 07/50] openssh-7.2p2-x11 +--- + channels.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/channels.c b/channels.c +index bfe2e3b2..d46531ce 100644 +--- a/channels.c ++++ b/channels.c +@@ -5098,11 +5098,13 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, + } + static int -connect_local_xsocket_path(const char *pathname) +connect_local_xsocket_path(const char *pathname, int len) { int sock; struct sockaddr_un addr; - + + if (len <= 0) + return -1; sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock == -1) { error("socket: %.100s", strerror(errno)); -@@ -5087,11 +5089,12 @@ +@@ -5110,11 +5112,12 @@ connect_local_xsocket_path(const char *pathname) } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; @@ -31,8 +41,8 @@ diff --git a/channels.c b/channels.c - error("connect %.100s: %.100s", addr.sun_path, strerror(errno)); return -1; } - -@@ -5099,8 +5102,18 @@ + +@@ -5122,8 +5125,18 @@ static int connect_local_xsocket(u_int dnr) { char buf[1024]; @@ -53,3 +63,6 @@ diff --git a/channels.c b/channels.c } #ifdef __APPLE__ +-- +2.49.0 + diff --git a/openssh-5.1p1-askpass-progress.patch b/0008-openssh-5.1p1-askpass-progress.patch similarity index 66% rename from openssh-5.1p1-askpass-progress.patch rename to 0008-openssh-5.1p1-askpass-progress.patch index ff609da..f7ca382 100644 --- a/openssh-5.1p1-askpass-progress.patch +++ b/0008-openssh-5.1p1-askpass-progress.patch @@ -1,7 +1,17 @@ -diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contrib/gnome-ssh-askpass2.c ---- openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/contrib/gnome-ssh-askpass2.c 2016-12-23 13:31:16.545211926 +0100 -@@ -53,6 +53,7 @@ +From 6b2a33044583e892badb9ac86cd2c6252b1a532f Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 08/50] openssh-5.1p1-askpass-progress + +--- + contrib/gnome-ssh-askpass2.c | 39 +++++++++++++++++++++++++++++++++--- + 1 file changed, 36 insertions(+), 3 deletions(-) + +diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c +index a62f9815..cb7152dc 100644 +--- a/contrib/gnome-ssh-askpass2.c ++++ b/contrib/gnome-ssh-askpass2.c +@@ -58,6 +58,7 @@ #include #include @@ -9,7 +19,7 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr #include #include #include -@@ -81,14 +82,25 @@ ok_dialog(GtkWidget *entry, gpointer dia +@@ -146,6 +147,17 @@ parse_env_hex_color(const char *env, GdkColor *c) return 1; } @@ -27,7 +37,7 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr static int passphrase_dialog(char *message, int prompt_type) { - const char *failed; +@@ -153,7 +165,7 @@ passphrase_dialog(char *message, int prompt_type) char *passphrase, *local; int result, grab_tries, grab_server, grab_pointer; int buttons, default_response; @@ -36,7 +46,7 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr GdkGrabStatus status; GdkColor fg, bg; int fg_set = 0, bg_set = 0; -@@ -104,14 +116,19 @@ passphrase_dialog(char *message) +@@ -199,14 +211,19 @@ passphrase_dialog(char *message, int prompt_type) gtk_widget_modify_bg(dialog, GTK_STATE_NORMAL, &bg); if (prompt_type == PROMPT_ENTRY || prompt_type == PROMPT_NONE) { @@ -45,12 +55,12 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr + FALSE, 0); + gtk_widget_show(hbox); + - entry = gtk_entry_new(); - if (fg_set) - gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg); - if (bg_set) - gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg); - gtk_box_pack_start( + entry = gtk_entry_new(); + if (fg_set) + gtk_widget_modify_fg(entry, GTK_STATE_NORMAL, &fg); + if (bg_set) + gtk_widget_modify_bg(entry, GTK_STATE_NORMAL, &bg); + gtk_box_pack_start( - GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), - entry, FALSE, FALSE, 0); + GTK_BOX(hbox), entry, TRUE, FALSE, 0); @@ -58,7 +68,7 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); gtk_widget_grab_focus(entry); if (prompt_type == PROMPT_ENTRY) { -@@ -130,6 +145,22 @@ passphrase_dialog(char *message) +@@ -225,6 +242,22 @@ passphrase_dialog(char *message, int prompt_type) g_signal_connect(G_OBJECT(entry), "key_press_event", G_CALLBACK(check_none), dialog); } @@ -81,3 +91,6 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr } /* Grab focus */ +-- +2.49.0 + diff --git a/openssh-4.3p2-askpass-grab-info.patch b/0009-openssh-4.3p2-askpass-grab-info.patch similarity index 53% rename from openssh-4.3p2-askpass-grab-info.patch rename to 0009-openssh-4.3p2-askpass-grab-info.patch index 120ed1b..8a7cf9e 100644 --- a/openssh-4.3p2-askpass-grab-info.patch +++ b/0009-openssh-4.3p2-askpass-grab-info.patch @@ -1,7 +1,17 @@ -diff -up openssh-8.6p1/contrib/gnome-ssh-askpass2.c.grab-info openssh-8.6p1/contrib/gnome-ssh-askpass2.c ---- openssh-8.6p1/contrib/gnome-ssh-askpass2.c.grab-info 2021-04-19 13:57:11.720113536 +0200 -+++ openssh-8.6p1/contrib/gnome-ssh-askpass2.c 2021-04-19 13:59:29.842163204 +0200 -@@ -70,8 +70,12 @@ report_failed_grab (GtkWidget *parent_wi +From 710ce53fdf1d32a0629fce2e42fb49d407e2b06c Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 09/50] openssh-4.3p2-askpass-grab-info + +--- + contrib/gnome-ssh-askpass2.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c +index cb7152dc..bbe93d83 100644 +--- a/contrib/gnome-ssh-askpass2.c ++++ b/contrib/gnome-ssh-askpass2.c +@@ -70,8 +70,12 @@ report_failed_grab (GtkWidget *parent_window, const char *what) err = gtk_message_dialog_new(GTK_WINDOW(parent_window), 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, @@ -16,3 +26,6 @@ diff -up openssh-8.6p1/contrib/gnome-ssh-askpass2.c.grab-info openssh-8.6p1/cont gtk_window_set_position(GTK_WINDOW(err), GTK_WIN_POS_CENTER); gtk_dialog_run(GTK_DIALOG(err)); +-- +2.49.0 + diff --git a/openssh-8.7p1-redhat.patch b/0010-openssh-8.7p1-redhat.patch similarity index 67% rename from openssh-8.7p1-redhat.patch rename to 0010-openssh-8.7p1-redhat.patch index a4c11b5..cb3d140 100644 --- a/openssh-8.7p1-redhat.patch +++ b/0010-openssh-8.7p1-redhat.patch @@ -1,7 +1,26 @@ -diff -up openssh/ssh_config.redhat openssh/ssh_config ---- openssh/ssh_config.redhat 2020-02-11 23:28:35.000000000 +0100 -+++ openssh/ssh_config 2020-02-13 18:13:39.180641839 +0100 -@@ -43,3 +43,10 @@ +From 5f21983f6472b26693babea4d6ca6b95a7dc7b05 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 10/50] openssh-8.7p1-redhat + +--- + ssh_config | 7 +++++++ + ssh_config_redhat | 18 ++++++++++++++++++ + sshd_config | 8 ++++++++ + sshd_config.0 | 6 +++--- + sshd_config.5 | 2 +- + sshd_config_redhat | 18 ++++++++++++++++++ + sshd_config_redhat_cp | 7 +++++++ + 7 files changed, 62 insertions(+), 4 deletions(-) + create mode 100644 ssh_config_redhat + create mode 100644 sshd_config_redhat + create mode 100644 sshd_config_redhat_cp + +diff --git a/ssh_config b/ssh_config +index cc566356..18169187 100644 +--- a/ssh_config ++++ b/ssh_config +@@ -44,3 +44,10 @@ # ProxyCommand ssh -q -W %h:%p gateway.example.com # RekeyLimit 1G 1h # UserKnownHostsFile ~/.ssh/known_hosts.d/%k @@ -12,9 +31,11 @@ diff -up openssh/ssh_config.redhat openssh/ssh_config +# included below. For more information, see manual page for +# update-crypto-policies(8) and ssh_config(5). +Include /etc/ssh/ssh_config.d/*.conf -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 +diff --git a/ssh_config_redhat b/ssh_config_redhat +new file mode 100644 +index 00000000..8b1b5902 +--- /dev/null ++++ b/ssh_config_redhat @@ -0,0 +1,18 @@ +# 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 @@ -34,10 +55,30 @@ diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat + +# Uncomment this if you want to use .local domain +# Host *.local -diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0 ---- openssh/sshd_config.0.redhat 2020-02-12 14:30:04.000000000 +0100 -+++ openssh/sshd_config.0 2020-02-13 18:13:39.181641855 +0100 -@@ -970,9 +970,9 @@ DESCRIPTION +diff --git a/sshd_config b/sshd_config +index 0f4a3a72..608203e4 100644 +--- a/sshd_config ++++ b/sshd_config +@@ -10,6 +10,14 @@ + # possible, but leave them commented. Uncommented options override the + # default value. + ++# To modify the system-wide sshd configuration, create a *.conf file under ++# /etc/ssh/sshd_config.d/ which will be automatically included below ++Include /etc/ssh/sshd_config.d/*.conf ++ ++# If you want to change the port on a SELinux system, you have to tell ++# SELinux about this change. ++# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER ++# + #Port 22 + #AddressFamily any + #ListenAddress 0.0.0.0 +diff --git a/sshd_config.0 b/sshd_config.0 +index 2f77b4f4..49349bb3 100644 +--- a/sshd_config.0 ++++ b/sshd_config.0 +@@ -1219,9 +1219,9 @@ DESCRIPTION SyslogFacility Gives the facility code that is used when logging messages from @@ -50,10 +91,11 @@ diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0 TCPKeepAlive Specifies whether the system should send TCP keepalive messages -diff -up openssh/sshd_config.5.redhat openssh/sshd_config.5 ---- openssh/sshd_config.5.redhat 2020-02-11 23:28:35.000000000 +0100 -+++ openssh/sshd_config.5 2020-02-13 18:13:39.181641855 +0100 -@@ -1614,7 +1614,7 @@ By default no subsystems are defined. +diff --git a/sshd_config.5 b/sshd_config.5 +index c0771737..035a50c8 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -1942,7 +1942,7 @@ By default no subsystems are defined. .It Cm SyslogFacility Gives the facility code that is used when logging messages from .Xr sshd 8 . @@ -62,27 +104,11 @@ diff -up openssh/sshd_config.5.redhat openssh/sshd_config.5 LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is AUTH. .It Cm TCPKeepAlive -diff -up openssh/sshd_config.redhat openssh/sshd_config ---- openssh/sshd_config.redhat 2020-02-11 23:28:35.000000000 +0100 -+++ openssh/sshd_config 2020-02-13 18:20:16.349913681 +0100 -@@ -10,6 +10,14 @@ - # possible, but leave them commented. Uncommented options override the - # default value. - -+# To modify the system-wide sshd configuration, create a *.conf file under -+# /etc/ssh/sshd_config.d/ which will be automatically included below -+Include /etc/ssh/sshd_config.d/*.conf -+ -+# If you want to change the port on a SELinux system, you have to tell -+# SELinux about this change. -+# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER -+# - #Port 22 - #AddressFamily any - #ListenAddress 0.0.0.0 -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 +diff --git a/sshd_config_redhat b/sshd_config_redhat +new file mode 100644 +index 00000000..993a28d5 +--- /dev/null ++++ b/sshd_config_redhat @@ -0,0 +1,18 @@ +SyslogFacility AUTHPRIV + @@ -102,9 +128,11 @@ 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 + -diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat ---- openssh/sshd_config_redhat_cp.redhat 2020-02-13 18:14:02.268006439 +0100 -+++ openssh/sshd_config_redhat_cp 2020-02-13 18:19:20.765035947 +0100 +diff --git a/sshd_config_redhat_cp b/sshd_config_redhat_cp +new file mode 100644 +index 00000000..1d592d13 +--- /dev/null ++++ b/sshd_config_redhat_cp @@ -0,0 +1,7 @@ +# This system is following system-wide crypto policy. The changes to +# crypto properties (Ciphers, MACs, ...) will not have any effect in @@ -113,3 +141,6 @@ diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat +# Please, see manual pages for update-crypto-policies(8) and sshd_config(5). +Include /etc/crypto-policies/back-ends/opensshserver.config + +-- +2.49.0 + diff --git a/openssh-7.8p1-UsePAM-warning.patch b/0011-openssh-7.8p1-UsePAM-warning.patch similarity index 50% rename from openssh-7.8p1-UsePAM-warning.patch rename to 0011-openssh-7.8p1-UsePAM-warning.patch index f8d7042..76ee115 100644 --- a/openssh-7.8p1-UsePAM-warning.patch +++ b/0011-openssh-7.8p1-UsePAM-warning.patch @@ -1,7 +1,18 @@ -diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c ---- openssh-8.6p1/sshd-session.c.log-usepam-no 2021-04-19 14:00:45.099735129 +0200 -+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:03:21.140920974 +0200 -@@ -1749,6 +1749,10 @@ main(int ac, char **av) +From 56b8d082bc9e25a77b5227d576f27088446c6fb9 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 11/50] openssh-7.8p1-UsePAM-warning + +--- + sshd-session.c | 4 ++++ + sshd_config | 2 ++ + 2 files changed, 6 insertions(+) + +diff --git a/sshd-session.c b/sshd-session.c +index a365f26f..a70b36c9 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -1127,6 +1127,10 @@ main(int ac, char **av) "enabled authentication methods"); } @@ -12,10 +23,11 @@ diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c #ifdef WITH_OPENSSL if (options.moduli_file != NULL) dh_set_moduli_file(options.moduli_file); -diff -up openssh-8.6p1/sshd_config.log-usepam-no openssh-8.6p1/sshd_config ---- openssh-8.6p1/sshd_config.log-usepam-no 2021-04-19 14:00:45.098735121 +0200 -+++ openssh-8.6p1/sshd_config 2021-04-19 14:00:45.099735129 +0200 -@@ -87,6 +87,8 @@ AuthorizedKeysFile .ssh/authorized_keys +diff --git a/sshd_config b/sshd_config +index 608203e4..48af6321 100644 +--- a/sshd_config ++++ b/sshd_config +@@ -89,6 +89,8 @@ AuthorizedKeysFile .ssh/authorized_keys # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and KbdInteractiveAuthentication to 'no'. @@ -24,3 +36,6 @@ diff -up openssh-8.6p1/sshd_config.log-usepam-no openssh-8.6p1/sshd_config #UsePAM no #AllowAgentForwarding yes +-- +2.49.0 + diff --git a/openssh-9.6p1-gssapi-keyex.patch b/0012-openssh-9.6p1-gssapi-keyex.patch similarity index 89% rename from openssh-9.6p1-gssapi-keyex.patch rename to 0012-openssh-9.6p1-gssapi-keyex.patch index ef1f97e..f5f54f7 100644 --- a/openssh-9.6p1-gssapi-keyex.patch +++ b/0012-openssh-9.6p1-gssapi-keyex.patch @@ -1,25 +1,111 @@ -diff --color -ruNp a/auth2.c b/auth2.c ---- a/auth2.c 2024-09-16 11:45:56.858133241 +0200 -+++ b/auth2.c 2024-09-16 11:46:34.688939755 +0200 -@@ -71,6 +71,7 @@ extern Authmethod method_passwd; - extern Authmethod method_kbdint; - extern Authmethod method_hostbased; - #ifdef GSSAPI -+extern Authmethod method_gsskeyex; - extern Authmethod method_gssapi; - #endif +From 754b023b92aa68742258c55243a6ae8f30ed5a17 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 12/50] openssh-9.6p1-gssapi-keyex + +--- + Makefile.in | 7 +- + auth.c | 3 +- + auth2-gss.c | 52 +++- + auth2-methods.c | 6 + + auth2.c | 2 + + canohost.c | 93 +++++++ + canohost.h | 3 + + clientloop.c | 12 + + configure.ac | 24 ++ + gss-genr.c | 302 ++++++++++++++++++++- + gss-serv-krb5.c | 97 ++++++- + gss-serv.c | 200 ++++++++++++-- + kex-names.c | 62 ++++- + kex.c | 35 ++- + kex.h | 34 +++ + kexdh.c | 10 + + kexgen.c | 2 +- + kexgssc.c | 706 ++++++++++++++++++++++++++++++++++++++++++++++++ + kexgsss.c | 601 +++++++++++++++++++++++++++++++++++++++++ + monitor.c | 147 +++++++++- + 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 | 64 ++++- + ssh.1 | 8 + + ssh.c | 6 +- + ssh_config | 2 + + ssh_config.5 | 58 ++++ + sshconnect2.c | 154 ++++++++++- + sshd-auth.c | 53 ++++ + sshd-session.c | 9 +- + sshd.c | 3 +- + sshd_config | 2 + + sshd_config.5 | 31 +++ + sshkey.c | 72 ++++- + sshkey.h | 1 + + 41 files changed, 2984 insertions(+), 76 deletions(-) + create mode 100644 kexgssc.c + create mode 100644 kexgsss.c + +diff --git a/Makefile.in b/Makefile.in +index 438efc51..78f65948 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -117,6 +117,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexgexc.o kexgexs.o \ + kexsntrup761x25519.o kexmlkem768x25519.o sntrup761.o kexgen.o \ ++ kexgssc.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ + sshbuf-io.o -@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { - &method_none, - &method_pubkey, - #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, - #endif - &method_passwd, -diff --color -ruNp a/auth2-gss.c b/auth2-gss.c ---- a/auth2-gss.c 2024-09-16 11:45:56.858133241 +0200 -+++ b/auth2-gss.c 2024-09-16 11:46:34.689939776 +0200 +@@ -138,7 +139,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rhosts.o auth-passwd.o \ + auth2-chall.o groupaccess.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 \ ++ monitor.o monitor_wrap.o auth-krb5.o kexgsss.o \ + auth2-gss.o gss-serv.o gss-serv-krb5.o \ + loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ + sftp-server.o sftp-common.o \ +@@ -150,7 +151,7 @@ SSHD_AUTH_OBJS=sshd-auth.o \ + serverloop.o auth.o auth2.o auth-options.o session.o auth2-chall.o \ + groupaccess.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ + auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ +- auth2-gss.o gss-serv.o gss-serv-krb5.o \ ++ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \ + monitor_wrap.o auth-krb5.o \ + audit.o audit-bsm.o audit-linux.o platform.o \ + loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ +@@ -563,7 +564,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 --git a/auth.c b/auth.c +index 9a6e5a31..e4578169 100644 +--- a/auth.c ++++ b/auth.c +@@ -356,7 +356,8 @@ auth_root_allowed(struct ssh *ssh, const char *method) + case PERMIT_NO_PASSWD: + if (strcmp(method, "publickey") == 0 || + strcmp(method, "hostbased") == 0 || +- strcmp(method, "gssapi-with-mic") == 0) ++ strcmp(method, "gssapi-with-mic") == 0 || ++ strcmp(method, "gssapi-keyex") == 0) + return 1; + break; + case PERMIT_FORCED_ONLY: +diff --git a/auth2-gss.c b/auth2-gss.c +index f7898ab3..5b1b9cde 100644 +--- a/auth2-gss.c ++++ b/auth2-gss.c @@ -51,6 +51,7 @@ #define SSH_GSSAPI_MAX_MECHS 2048 @@ -28,10 +114,11 @@ diff --color -ruNp a/auth2-gss.c b/auth2-gss.c extern struct authmethod_cfg methodcfg_gssapi; static int input_gssapi_token(int type, u_int32_t plen, struct ssh *ssh); -@@ -59,6 +60,48 @@ static int input_gssapi_exchange_complet +@@ -58,6 +59,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 *); - /* ++/* + * The 'gssapi_keyex' userauth mechanism. + */ +static int @@ -73,11 +160,10 @@ diff --color -ruNp a/auth2-gss.c b/auth2-gss.c + return (authenticated); +} + -+/* + /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) - */ -@@ -267,7 +310,7 @@ input_gssapi_exchange_complete(int type, +@@ -267,7 +310,7 @@ 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"); @@ -86,7 +172,7 @@ diff --color -ruNp a/auth2-gss.c b/auth2-gss.c authctxt->postponed = 0; ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); -@@ -315,7 +358,7 @@ input_gssapi_mic(int type, u_int32_t ple +@@ -315,7 +358,7 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) gssbuf.length = sshbuf_len(b); if (!GSS_ERROR(mm_ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))) @@ -95,7 +181,7 @@ diff --color -ruNp a/auth2-gss.c b/auth2-gss.c else logit("GSSAPI MIC check failed"); -@@ -333,6 +376,11 @@ input_gssapi_mic(int type, u_int32_t ple +@@ -333,6 +376,11 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) return 0; } @@ -107,10 +193,11 @@ diff --color -ruNp a/auth2-gss.c b/auth2-gss.c Authmethod method_gssapi = { &methodcfg_gssapi, userauth_gssapi, -diff --color -ruNp a/auth2-methods.c b/auth2-methods.c ---- a/auth2-methods.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/auth2-methods.c 2024-09-16 11:46:34.689939776 +0200 -@@ -50,6 +50,11 @@ struct authmethod_cfg methodcfg_pubkey = +diff --git a/auth2-methods.c b/auth2-methods.c +index 99637a89..a05908cf 100644 +--- a/auth2-methods.c ++++ b/auth2-methods.c +@@ -50,6 +50,11 @@ struct authmethod_cfg methodcfg_pubkey = { &options.pubkey_authentication }; #ifdef GSSAPI @@ -122,7 +209,7 @@ diff --color -ruNp a/auth2-methods.c b/auth2-methods.c struct authmethod_cfg methodcfg_gssapi = { "gssapi-with-mic", NULL, -@@ -76,6 +81,7 @@ static struct authmethod_cfg *authmethod +@@ -76,6 +81,7 @@ static struct authmethod_cfg *authmethod_cfgs[] = { &methodcfg_none, &methodcfg_pubkey, #ifdef GSSAPI @@ -130,22 +217,30 @@ diff --color -ruNp a/auth2-methods.c b/auth2-methods.c &methodcfg_gssapi, #endif &methodcfg_passwd, -diff --color -ruNp a/auth.c b/auth.c ---- a/auth.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/auth.c 2024-09-16 11:46:34.690939798 +0200 -@@ -356,7 +356,8 @@ auth_root_allowed(struct ssh *ssh, const - case PERMIT_NO_PASSWD: - if (strcmp(method, "publickey") == 0 || - strcmp(method, "hostbased") == 0 || -- strcmp(method, "gssapi-with-mic") == 0) -+ strcmp(method, "gssapi-with-mic") == 0 || -+ strcmp(method, "gssapi-keyex") == 0) - return 1; - break; - case PERMIT_FORCED_ONLY: -diff --color -ruNp a/canohost.c b/canohost.c ---- a/canohost.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/canohost.c 2024-09-16 11:46:34.690939798 +0200 +diff --git a/auth2.c b/auth2.c +index 5ba45c12..8ec41de2 100644 +--- a/auth2.c ++++ b/auth2.c +@@ -71,6 +71,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif + +@@ -78,6 +79,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + &method_passwd, +diff --git a/canohost.c b/canohost.c +index 28f086e5..875805c9 100644 +--- a/canohost.c ++++ b/canohost.c @@ -35,6 +35,99 @@ #include "canohost.h" #include "misc.h" @@ -246,9 +341,10 @@ diff --color -ruNp a/canohost.c b/canohost.c void ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) { -diff --color -ruNp a/canohost.h b/canohost.h ---- a/canohost.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/canohost.h 2024-09-16 11:46:34.690939798 +0200 +diff --git a/canohost.h b/canohost.h +index 26d62855..0cadc9f1 100644 +--- a/canohost.h ++++ b/canohost.h @@ -15,6 +15,9 @@ #ifndef _CANOHOST_H #define _CANOHOST_H @@ -259,9 +355,10 @@ diff --color -ruNp a/canohost.h b/canohost.h char *get_peer_ipaddr(int); int get_peer_port(int); char *get_local_ipaddr(int); -diff --color -ruNp a/clientloop.c b/clientloop.c ---- a/clientloop.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/clientloop.c 2024-09-16 11:46:34.690939798 +0200 +diff --git a/clientloop.c b/clientloop.c +index 916fc077..4655f91f 100644 +--- a/clientloop.c ++++ b/clientloop.c @@ -115,6 +115,10 @@ #include "ssherr.h" #include "hostfile.h" @@ -273,7 +370,7 @@ diff --color -ruNp a/clientloop.c b/clientloop.c /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" -@@ -1590,6 +1594,14 @@ client_loop(struct ssh *ssh, int have_pt +@@ -1591,6 +1595,14 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, /* Do channel operations. */ channel_after_poll(ssh, pfd, npfd_active); @@ -288,10 +385,11 @@ diff --color -ruNp a/clientloop.c b/clientloop.c /* Buffer input from the connection. */ if (conn_in_ready) client_process_net_input(ssh); -diff --color -ruNp a/configure.ac b/configure.ac ---- a/configure.ac 2024-09-16 11:45:56.870133497 +0200 -+++ b/configure.ac 2024-09-16 11:46:34.691939819 +0200 -@@ -774,6 +774,30 @@ int main(void) { if (NSVersionOfRunTimeL +diff --git a/configure.ac b/configure.ac +index d546788c..13c70a98 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -786,6 +786,30 @@ int main(void) { 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]) @@ -322,9 +420,10 @@ diff --color -ruNp a/configure.ac b/configure.ac m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) -diff --color -ruNp a/gss-genr.c b/gss-genr.c ---- a/gss-genr.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/gss-genr.c 2024-09-16 11:46:34.708940181 +0200 +diff --git a/gss-genr.c b/gss-genr.c +index aa34b71c..3034370c 100644 +--- a/gss-genr.c ++++ b/gss-genr.c @@ -42,9 +42,33 @@ #include "sshbuf.h" #include "log.h" @@ -359,7 +458,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c /* 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 +@@ -60,6 +84,159 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) return 0; } @@ -540,7 +639,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c free(*ctx); *ctx = NULL; -@@ -216,7 +400,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de +@@ -216,7 +400,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, } ctx->major = gss_init_sec_context(&ctx->minor, @@ -549,10 +648,11 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -246,8 +430,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con +@@ -245,9 +429,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) + return (ctx->major); } - OM_uint32 ++OM_uint32 +ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) +{ + gss_buffer_desc gssbuf; @@ -583,7 +683,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c + return(ctx->major); +} + -+OM_uint32 + OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { + if (ctx == NULL) @@ -592,7 +692,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); -@@ -255,6 +473,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer +@@ -255,6 +473,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) return (ctx->major); } @@ -612,7 +712,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, const char *context, const struct sshbuf *session_id) -@@ -271,11 +502,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, co +@@ -271,11 +502,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, } int @@ -630,7 +730,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && -@@ -285,6 +521,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx +@@ -285,6 +521,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); @@ -641,7 +741,7 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); -@@ -294,10 +534,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx +@@ -294,10 +534,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) GSS_C_NO_BUFFER); } @@ -709,9 +809,150 @@ diff --color -ruNp a/gss-genr.c b/gss-genr.c +} + #endif /* GSSAPI */ -diff --color -ruNp a/gss-serv.c b/gss-serv.c ---- a/gss-serv.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/gss-serv.c 2024-09-16 11:46:34.692939840 +0200 +diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c +index a151bc1e..8d2b677f 100644 +--- a/gss-serv-krb5.c ++++ b/gss-serv-krb5.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) + krb5_error_code problem; + krb5_principal princ; + OM_uint32 maj_status, min_status; +- int len; ++ const char *new_ccname, *new_cctype; + const char *errmsg; + + if (client->creds == NULL) { +@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) + return; + } + +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_cctype = krb5_cc_get_type(krb_context, ccache); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ if (new_ccname[0] == ':') ++ new_ccname++; ++ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); ++ if (strcmp(new_cctype, "DIR") == 0) { ++ char *p; ++ p = strrchr(client->store.envval, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) ++ client->store.filename = xstrdup(new_ccname); ++#endif + + #ifdef USE_PAM + if (options.use_pam) +@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) + + krb5_cc_close(krb_context, ccache); + ++ client->store.data = krb_context; ++ + return; + } + ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -203,7 +285,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +diff --git a/gss-serv.c b/gss-serv.c +index 025a118f..a5cca797 100644 +--- a/gss-serv.c ++++ b/gss-serv.c @@ -1,7 +1,7 @@ /* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ @@ -721,7 +962,7 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions -@@ -44,17 +44,19 @@ +@@ -45,17 +45,19 @@ #include "session.h" #include "misc.h" #include "servconf.h" @@ -744,10 +985,11 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c #ifdef KRB5 extern ssh_gssapi_mech gssapi_kerberos_mech; -@@ -141,6 +143,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss +@@ -141,6 +143,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) + return (ssh_gssapi_acquire_cred(*ctx)); } - /* Unprivileged */ ++/* Unprivileged */ +char * +ssh_gssapi_server_mechanisms(void) { + if (supported_oids == NULL) @@ -770,11 +1012,10 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c + return (res); +} + -+/* Unprivileged */ + /* Unprivileged */ void ssh_gssapi_supported_oids(gss_OID_set *oidset) - { -@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o +@@ -151,7 +176,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset) gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); @@ -785,7 +1026,7 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, -@@ -276,8 +303,48 @@ OM_uint32 +@@ -277,8 +304,48 @@ OM_uint32 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) { int i = 0; @@ -835,7 +1076,7 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c client->mech = NULL; -@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g +@@ -293,6 +360,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) if (client->mech == NULL) return GSS_S_FAILURE; @@ -849,7 +1090,7 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); -@@ -309,6 +383,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g +@@ -310,6 +384,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) return (ctx->major); } @@ -858,7 +1099,7 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; -@@ -319,11 +395,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g +@@ -320,11 +396,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) void ssh_gssapi_cleanup_creds(void) { @@ -884,7 +1125,7 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c } } -@@ -356,19 +441,23 @@ ssh_gssapi_do_child(char ***envp, u_int +@@ -357,19 +442,23 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep) /* Privileged */ int @@ -911,7 +1152,7 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); -@@ -382,14 +471,85 @@ ssh_gssapi_userok(char *user) +@@ -383,14 +472,85 @@ ssh_gssapi_userok(char *user) return (0); } @@ -1003,148 +1244,114 @@ diff --color -ruNp a/gss-serv.c b/gss-serv.c } /* Privileged */ -diff --color -ruNp a/gss-serv-krb5.c b/gss-serv-krb5.c ---- a/gss-serv-krb5.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/gss-serv-krb5.c 2024-09-16 11:46:34.692939840 +0200 -@@ -1,7 +1,7 @@ - /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ +diff --git a/kex-names.c b/kex-names.c +index ec840c1f..6c0b7c2b 100644 +--- a/kex-names.c ++++ b/kex-names.c +@@ -45,6 +45,10 @@ + #include "ssherr.h" + #include "xmalloc.h" - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - krb5_error_code problem; - krb5_principal princ; - OM_uint32 maj_status, min_status; -- int len; -+ const char *new_ccname, *new_cctype; - const char *errmsg; - - if (client->creds == NULL) { -@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - return; - } - -- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); -+ new_cctype = krb5_cc_get_type(krb_context, ccache); -+ new_ccname = krb5_cc_get_name(krb_context, ccache); -+ - client->store.envvar = "KRB5CCNAME"; -- len = strlen(client->store.filename) + 6; -- client->store.envval = xmalloc(len); -- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); -+#ifdef USE_CCAPI -+ xasprintf(&client->store.envval, "API:%s", new_ccname); -+ client->store.filename = NULL; -+#else -+ if (new_ccname[0] == ':') -+ new_ccname++; -+ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); -+ if (strcmp(new_cctype, "DIR") == 0) { -+ char *p; -+ p = strrchr(client->store.envval, '/'); -+ if (p) -+ *p = '\0'; -+ } -+ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) -+ client->store.filename = xstrdup(new_ccname); ++#ifdef GSSAPI ++#include "ssh-gss.h" +#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - - krb5_cc_close(krb_context, ccache); - -+ client->store.data = krb_context; + - return; + struct kexalg { + char *name; + u_int type; +@@ -89,15 +93,28 @@ static const struct kexalg kexalgs[] = { + #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ + { NULL, 0, -1, -1}, + }; ++static const struct kexalg gss_kexalgs[] = { ++#ifdef GSSAPI ++ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, ++ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, ++ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, ++#endif ++ { NULL, 0, -1, -1}, ++}; + +-char * +-kex_alg_list(char sep) ++static char * ++kex_alg_list_internal(char sep, const struct kexalg *algs) + { + char *ret = NULL, *tmp; + size_t nlen, rlen = 0; + const struct kexalg *k; + +- for (k = kexalgs; k->name != NULL; k++) { ++ for (k = algs; k->name != NULL; k++) { + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(k->name); +@@ -112,6 +129,18 @@ kex_alg_list(char sep) + return ret; } -+int -+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, -+ ssh_gssapi_client *client) ++char * ++kex_alg_list(char sep) +{ -+ krb5_ccache ccache = NULL; -+ krb5_principal principal = NULL; -+ char *name = NULL; -+ krb5_error_code problem; -+ OM_uint32 maj_status, min_status; -+ -+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { -+ logit("krb5_cc_resolve(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ return 0; -+ } -+ -+ /* Find out who the principal in this cache is */ -+ if ((problem = krb5_cc_get_principal(krb_context, ccache, -+ &principal))) { -+ logit("krb5_cc_get_principal(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { -+ logit("krb5_unparse_name(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ -+ if (strcmp(name,client->exportedname.value)!=0) { -+ debug("Name in local credentials cache differs. Not storing"); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ krb5_free_unparsed_name(krb_context, name); -+ return 0; -+ } -+ krb5_free_unparsed_name(krb_context, name); -+ -+ /* Name matches, so lets get on with it! */ -+ -+ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { -+ logit("krb5_cc_initialize(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ krb5_free_principal(krb_context, principal); -+ -+ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, -+ ccache))) { -+ logit("gss_krb5_copy_ccache() failed. Sorry!"); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ return 1; ++ return kex_alg_list_internal(sep, kexalgs); +} + - ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", -@@ -203,7 +285,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { - NULL, - &ssh_gssapi_krb5_userok, - NULL, -- &ssh_gssapi_krb5_storecreds -+ &ssh_gssapi_krb5_storecreds, -+ &ssh_gssapi_krb5_updatecreds - }; ++char * ++kex_gss_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, gss_kexalgs); ++} ++ + static const struct kexalg * + kex_alg_by_name(const char *name) + { +@@ -121,6 +150,10 @@ kex_alg_by_name(const char *name) + if (strcmp(k->name, name) == 0) + return k; + } ++ for (k = gss_kexalgs; k->name != NULL; k++) { ++ if (strncmp(k->name, name, strlen(k->name)) == 0) ++ return k; ++ } + return NULL; + } - #endif /* KRB5 */ -diff --color -ruNp a/kex.c b/kex.c ---- a/kex.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/kex.c 2024-09-16 11:46:34.692939840 +0200 +@@ -334,3 +367,26 @@ kex_assemble_names(char **listp, const char *def, const char *all) + free(ret); + return r; + } ++ ++/* Validate GSS KEX method name list */ ++int ++kex_gss_names_valid(const char *names) ++{ ++ char *s, *cp, *p; ++ ++ if (names == NULL || *names == '\0') ++ return 0; ++ s = cp = xstrdup(names); ++ for ((p = strsep(&cp, ",")); p && *p != '\0'; ++ (p = strsep(&cp, ","))) { ++ if (strncmp(p, "gss-", 4) != 0 ++ || kex_alg_by_name(p) == NULL) { ++ error("Unsupported KEX algorithm \"%.100s\"", p); ++ free(s); ++ return 0; ++ } ++ } ++ debug3("gss kex names ok: [%s]", names); ++ free(s); ++ return 1; ++} +diff --git a/kex.c b/kex.c +index 6b957e5e..19a56e8e 100644 +--- a/kex.c ++++ b/kex.c @@ -297,17 +297,37 @@ static int kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m) { @@ -1199,9 +1406,92 @@ diff --color -ruNp a/kex.c b/kex.c sshbuf_free(kex->initial_sig); sshkey_free(kex->initial_hostkey); free(kex->failed_choice); -diff --color -ruNp a/kexdh.c b/kexdh.c ---- a/kexdh.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/kexdh.c 2024-09-16 11:46:34.693939862 +0200 +diff --git a/kex.h b/kex.h +index d08988b3..0e080ea3 100644 +--- a/kex.h ++++ b/kex.h +@@ -29,6 +29,10 @@ + #include "mac.h" + #include "crypto_api.h" + ++#ifdef GSSAPI ++# include "ssh-gss.h" /* Gssctxt */ ++#endif ++ + #ifdef WITH_OPENSSL + # include + # include +@@ -103,6 +107,15 @@ enum kex_exchange { + KEX_C25519_SHA256, + KEX_KEM_SNTRUP761X25519_SHA512, + KEX_KEM_MLKEM768X25519_SHA256, ++#ifdef GSSAPI ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GRP14_SHA256, ++ KEX_GSS_GRP16_SHA512, ++ KEX_GSS_GEX_SHA1, ++ KEX_GSS_NISTP256_SHA256, ++ KEX_GSS_C25519_SHA256, ++#endif + KEX_MAX + }; + +@@ -165,6 +178,13 @@ struct kex { + u_int flags; + int hash_alg; + int ec_nid; ++#ifdef GSSAPI ++ Gssctxt *gss; ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *failed_choice; + int (*verify_host_key)(struct sshkey *, struct ssh *); + struct sshkey *(*load_host_public_key)(int, int, struct ssh *); +@@ -191,8 +211,10 @@ int kex_hash_from_name(const char *); + int kex_nid_from_name(const char *); + int kex_names_valid(const char *); + char *kex_alg_list(char); ++char *kex_gss_alg_list(char); + char *kex_names_cat(const char *, const char *); + int kex_has_any_alg(const char *, const char *); ++int kex_gss_names_valid(const char *); + int kex_assemble_names(char **, const char *, const char *); + void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], + const char *, const char *, const char *, const char *, const char *); +@@ -226,6 +248,12 @@ int kexgex_client(struct ssh *); + int kexgex_server(struct ssh *); + int kex_gen_client(struct ssh *); + int kex_gen_server(struct ssh *); ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++int kexgssgex_client(struct ssh *); ++int kexgssgex_server(struct ssh *); ++int kexgss_client(struct ssh *); ++int kexgss_server(struct ssh *); ++#endif + + int kex_dh_keypair(struct kex *); + int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, +@@ -264,6 +292,12 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, + const BIGNUM *, const u_char *, size_t, + u_char *, size_t *); + ++int kex_gen_hash(int hash_alg, const struct sshbuf *client_version, ++ const struct sshbuf *server_version, const struct sshbuf *client_kexinit, ++ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob, ++ const struct sshbuf *client_pub, const struct sshbuf *server_pub, ++ const struct sshbuf *shared_secret, u_char *hash, size_t *hashlen); ++ + void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); +diff --git a/kexdh.c b/kexdh.c +index c1084f21..0faab21b 100644 +--- a/kexdh.c ++++ b/kexdh.c @@ -49,13 +49,23 @@ kex_dh_keygen(struct kex *kex) { switch (kex->kex_type) { @@ -1226,9 +1516,10 @@ diff --color -ruNp a/kexdh.c b/kexdh.c kex->dh = dh_new_group16(); break; case KEX_DH_GRP18_SHA512: -diff --color -ruNp a/kexgen.c b/kexgen.c ---- a/kexgen.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/kexgen.c 2024-09-16 11:46:34.693939862 +0200 +diff --git a/kexgen.c b/kexgen.c +index 40d688d6..15df591c 100644 +--- a/kexgen.c ++++ b/kexgen.c @@ -44,7 +44,7 @@ static int input_kex_gen_init(int, u_int32_t, struct ssh *); static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh); @@ -1238,9 +1529,11 @@ diff --color -ruNp a/kexgen.c b/kexgen.c kex_gen_hash( int hash_alg, const struct sshbuf *client_version, -diff --color -ruNp a/kexgssc.c b/kexgssc.c ---- a/kexgssc.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/kexgssc.c 2024-10-14 15:18:02.491798105 +0200 +diff --git a/kexgssc.c b/kexgssc.c +new file mode 100644 +index 00000000..96f7b6f5 +--- /dev/null ++++ b/kexgssc.c @@ -0,0 +1,706 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. @@ -1948,9 +2241,11 @@ diff --color -ruNp a/kexgssc.c b/kexgssc.c +} + +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --color -ruNp a/kexgsss.c b/kexgsss.c ---- a/kexgsss.c 1970-01-01 01:00:00.000000000 +0100 -+++ b/kexgsss.c 2024-10-14 15:18:02.491798105 +0200 +diff --git a/kexgsss.c b/kexgsss.c +new file mode 100644 +index 00000000..8362081e +--- /dev/null ++++ b/kexgsss.c @@ -0,0 +1,601 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. @@ -2553,223 +2848,11 @@ diff --color -ruNp a/kexgsss.c b/kexgsss.c +} + +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ -diff --color -ruNp a/kex.h b/kex.h ---- a/kex.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/kex.h 2024-09-16 11:46:34.710940224 +0200 -@@ -29,6 +29,10 @@ - #include "mac.h" - #include "crypto_api.h" - -+#ifdef GSSAPI -+# include "ssh-gss.h" /* Gssctxt */ -+#endif -+ - #ifdef WITH_OPENSSL - # include - # include -@@ -102,6 +106,15 @@ enum kex_exchange { - KEX_C25519_SHA256, - KEX_KEM_SNTRUP761X25519_SHA512, - KEX_KEM_MLKEM768X25519_SHA256, -+#ifdef GSSAPI -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GRP14_SHA256, -+ KEX_GSS_GRP16_SHA512, -+ KEX_GSS_GEX_SHA1, -+ KEX_GSS_NISTP256_SHA256, -+ KEX_GSS_C25519_SHA256, -+#endif - KEX_MAX - }; - -@@ -164,6 +177,13 @@ struct kex { - u_int flags; - int hash_alg; - int ec_nid; -+#ifdef GSSAPI -+ Gssctxt *gss; -+ int gss_deleg_creds; -+ int gss_trust_dns; -+ char *gss_host; -+ char *gss_client; -+#endif - char *failed_choice; - int (*verify_host_key)(struct sshkey *, struct ssh *); - struct sshkey *(*load_host_public_key)(int, int, struct ssh *); -@@ -189,8 +209,10 @@ int kex_hash_from_name(const char *); - int kex_nid_from_name(const char *); - int kex_names_valid(const char *); - char *kex_alg_list(char); -+char *kex_gss_alg_list(char); - char *kex_names_cat(const char *, const char *); - int kex_has_any_alg(const char *, const char *); -+int kex_gss_names_valid(const char *); - int kex_assemble_names(char **, const char *, const char *); - void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], - const char *, const char *, const char *, const char *, const char *); -@@ -224,6 +246,12 @@ int kexgex_client(struct ssh *); - int kexgex_server(struct ssh *); - int kex_gen_client(struct ssh *); - int kex_gen_server(struct ssh *); -+#if defined(GSSAPI) && defined(WITH_OPENSSL) -+int kexgssgex_client(struct ssh *); -+int kexgssgex_server(struct ssh *); -+int kexgss_client(struct ssh *); -+int kexgss_server(struct ssh *); -+#endif - - int kex_dh_keypair(struct kex *); - int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, -@@ -256,6 +284,12 @@ int kexgex_hash(int, const struct sshbu - const BIGNUM *, const u_char *, size_t, - u_char *, size_t *); - -+int kex_gen_hash(int hash_alg, const struct sshbuf *client_version, -+ const struct sshbuf *server_version, const struct sshbuf *client_kexinit, -+ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob, -+ const struct sshbuf *client_pub, const struct sshbuf *server_pub, -+ const struct sshbuf *shared_secret, u_char *hash, size_t *hashlen); -+ - void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) - __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -diff --color -ruNp a/kex-names.c b/kex-names.c ---- a/kex-names.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/kex-names.c 2024-09-16 11:46:34.694939883 +0200 -@@ -45,6 +45,10 @@ - #include "ssherr.h" - #include "xmalloc.h" - -+#ifdef GSSAPI -+#include "ssh-gss.h" -+#endif -+ - struct kexalg { - char *name; - u_int type; -@@ -83,15 +87,28 @@ static const struct kexalg kexalgs[] = { - #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ - { NULL, 0, -1, -1}, - }; -+static const struct kexalg gss_kexalgs[] = { -+#ifdef GSSAPI -+ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, -+ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, -+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, -+#endif -+ { NULL, 0, -1, -1}, -+}; - --char * --kex_alg_list(char sep) -+static char * -+kex_alg_list_internal(char sep, const struct kexalg *algs) - { - char *ret = NULL, *tmp; - size_t nlen, rlen = 0; - const struct kexalg *k; - -- for (k = kexalgs; k->name != NULL; k++) { -+ for (k = algs; k->name != NULL; k++) { - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(k->name); -@@ -106,6 +123,18 @@ kex_alg_list(char sep) - return ret; - } - -+char * -+kex_alg_list(char sep) -+{ -+ return kex_alg_list_internal(sep, kexalgs); -+} -+ -+char * -+kex_gss_alg_list(char sep) -+{ -+ return kex_alg_list_internal(sep, gss_kexalgs); -+} -+ - static const struct kexalg * - kex_alg_by_name(const char *name) - { -@@ -115,6 +144,10 @@ kex_alg_by_name(const char *name) - if (strcmp(k->name, name) == 0) - return k; - } -+ for (k = gss_kexalgs; k->name != NULL; k++) { -+ if (strncmp(k->name, name, strlen(k->name)) == 0) -+ return k; -+ } - return NULL; - } - -@@ -328,3 +361,26 @@ kex_assemble_names(char **listp, const c - free(ret); - return r; - } -+ -+/* Validate GSS KEX method name list */ -+int -+kex_gss_names_valid(const char *names) -+{ -+ char *s, *cp, *p; -+ -+ if (names == NULL || *names == '\0') -+ return 0; -+ s = cp = xstrdup(names); -+ for ((p = strsep(&cp, ",")); p && *p != '\0'; -+ (p = strsep(&cp, ","))) { -+ if (strncmp(p, "gss-", 4) != 0 -+ || kex_alg_by_name(p) == NULL) { -+ error("Unsupported KEX algorithm \"%.100s\"", p); -+ free(s); -+ return 0; -+ } -+ } -+ debug3("gss kex names ok: [%s]", names); -+ free(s); -+ return 1; -+} -diff --color -ruNp a/Makefile.in b/Makefile.in ---- a/Makefile.in 2024-09-16 11:45:56.868133454 +0200 -+++ b/Makefile.in 2024-09-16 11:46:34.695939904 +0200 -@@ -114,6 +114,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexgexc.o kexgexs.o \ - kexsntrup761x25519.o kexmlkem768x25519.o sntrup761.o kexgen.o \ -+ kexgssc.o \ - sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ - sshbuf-io.o - -@@ -135,7 +136,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rh - auth2-chall.o groupaccess.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 \ -+ monitor.o monitor_wrap.o auth-krb5.o kexgsss.o \ - auth2-gss.o gss-serv.o gss-serv-krb5.o \ - loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ - sftp-server.o sftp-common.o \ -@@ -529,7 +530,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 --color -ruNp a/monitor.c b/monitor.c ---- a/monitor.c 2024-09-16 11:45:56.861133305 +0200 -+++ b/monitor.c 2024-09-16 11:46:34.696939926 +0200 -@@ -143,6 +143,8 @@ int mm_answer_gss_setup_ctx(struct ssh * +diff --git a/monitor.c b/monitor.c +index 02b3eaaa..2ef16cc8 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -147,6 +147,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); @@ -2778,7 +2861,7 @@ diff --color -ruNp a/monitor.c b/monitor.c #endif #ifdef SSH_AUDIT_EVENTS -@@ -219,11 +221,18 @@ struct mon_table mon_dispatch_proto20[] +@@ -224,11 +226,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}, @@ -2794,11 +2877,11 @@ diff --color -ruNp a/monitor.c b/monitor.c + {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, + {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, +#endif + {MONITOR_REQ_STATE, MON_ONCE, mm_answer_state}, #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, - #endif -@@ -292,6 +301,10 @@ monitor_child_preauth(struct ssh *ssh, s - /* Permit requests for moduli and signatures */ +@@ -299,6 +308,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) + monitor_permit(mon_dispatch, MONITOR_REQ_STATE, 1); monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); +#ifdef GSSAPI @@ -2808,7 +2891,7 @@ diff --color -ruNp a/monitor.c b/monitor.c /* The first few requests do not require asynchronous access */ while (!authenticated) { -@@ -344,8 +357,15 @@ monitor_child_preauth(struct ssh *ssh, s +@@ -351,8 +364,15 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { auth_log(ssh, authenticated, partial, auth_method, auth_submethod); @@ -2825,7 +2908,7 @@ diff --color -ruNp a/monitor.c b/monitor.c if (authenticated || partial) { auth2_update_session_info(authctxt, auth_method, auth_submethod); -@@ -413,6 +433,10 @@ monitor_child_postauth(struct ssh *ssh, +@@ -421,6 +441,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); @@ -2836,7 +2919,7 @@ diff --color -ruNp a/monitor.c b/monitor.c if (auth_opts->permit_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); -@@ -1793,6 +1817,17 @@ monitor_apply_keystate(struct ssh *ssh, +@@ -1890,6 +1914,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -2854,7 +2937,7 @@ diff --color -ruNp a/monitor.c b/monitor.c #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; -@@ -1885,8 +1920,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, +@@ -1981,8 +2016,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) u_char *p; int r; @@ -2865,7 +2948,7 @@ diff --color -ruNp a/monitor.c b/monitor.c if ((r = sshbuf_get_string(m, &p, &len)) != 0) fatal_fr(r, "parse"); -@@ -1918,8 +1953,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh +@@ -2014,8 +2049,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) OM_uint32 flags = 0; /* GSI needs this */ int r; @@ -2876,7 +2959,7 @@ diff --color -ruNp a/monitor.c b/monitor.c if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) fatal_fr(r, "ssh_gssapi_get_buffer_desc"); -@@ -1939,6 +1974,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh +@@ -2035,6 +2070,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); @@ -2884,7 +2967,7 @@ diff --color -ruNp a/monitor.c b/monitor.c } return (0); } -@@ -1950,8 +1986,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, +@@ -2046,8 +2082,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) OM_uint32 ret; int r; @@ -2895,7 +2978,7 @@ diff --color -ruNp a/monitor.c b/monitor.c if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) -@@ -1977,13 +2013,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, +@@ -2073,13 +2109,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) { @@ -2907,17 +2990,17 @@ diff --color -ruNp a/monitor.c b/monitor.c - fatal_f("GSSAPI authentication not enabled"); + if (!options.gss_authentication && !options.gss_keyex) + fatal_f("GSSAPI not enabled"); - -- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); ++ + if ((r = sshbuf_get_u32(m, &kex)) != 0) + fatal_fr(r, "buffer error"); -+ + +- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); + authenticated = authctxt->valid && + ssh_gssapi_userok(authctxt->user, authctxt->pw, kex); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) -@@ -1992,7 +2032,11 @@ mm_answer_gss_userok(struct ssh *ssh, in +@@ -2088,7 +2128,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); @@ -2930,7 +3013,7 @@ diff --color -ruNp a/monitor.c b/monitor.c if ((displayname = ssh_gssapi_displayname()) != NULL) auth2_record_info(authctxt, "%s", displayname); -@@ -2000,5 +2044,84 @@ mm_answer_gss_userok(struct ssh *ssh, in +@@ -2096,5 +2140,84 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -3015,10 +3098,11 @@ diff --color -ruNp a/monitor.c b/monitor.c + #endif /* GSSAPI */ -diff --color -ruNp a/monitor.h b/monitor.h ---- a/monitor.h 2024-09-16 11:45:56.861133305 +0200 -+++ b/monitor.h 2024-09-16 11:46:34.696939926 +0200 -@@ -67,6 +67,8 @@ enum monitor_reqtype { +diff --git a/monitor.h b/monitor.h +index 9dcd9c29..dbc7e003 100644 +--- a/monitor.h ++++ b/monitor.h +@@ -68,6 +68,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, @@ -3027,10 +3111,11 @@ diff --color -ruNp a/monitor.h b/monitor.h }; struct ssh; -diff --color -ruNp a/monitor_wrap.c b/monitor_wrap.c ---- a/monitor_wrap.c 2024-09-16 11:45:56.862133326 +0200 -+++ b/monitor_wrap.c 2024-09-16 11:46:34.697939947 +0200 -@@ -1075,13 +1075,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss +diff --git a/monitor_wrap.c b/monitor_wrap.c +index ef3ab1b1..b6e3b3f3 100644 +--- a/monitor_wrap.c ++++ b/monitor_wrap.c +@@ -1131,13 +1131,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) } int @@ -3047,7 +3132,7 @@ diff --color -ruNp a/monitor_wrap.c b/monitor_wrap.c mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, -@@ -1094,6 +1096,59 @@ mm_ssh_gssapi_userok(char *user) +@@ -1150,6 +1152,59 @@ mm_ssh_gssapi_userok(char *user) debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } @@ -3107,10 +3192,11 @@ diff --color -ruNp a/monitor_wrap.c b/monitor_wrap.c #endif /* GSSAPI */ /* -diff --color -ruNp a/monitor_wrap.h b/monitor_wrap.h ---- a/monitor_wrap.h 2024-09-16 11:45:56.862133326 +0200 -+++ b/monitor_wrap.h 2024-09-16 11:46:34.697939947 +0200 -@@ -67,8 +67,10 @@ void mm_decode_activate_server_options(s +diff --git a/monitor_wrap.h b/monitor_wrap.h +index 38a280c8..672dce52 100644 +--- a/monitor_wrap.h ++++ b/monitor_wrap.h +@@ -67,8 +67,10 @@ void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); 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 *); @@ -3122,18 +3208,19 @@ diff --color -ruNp a/monitor_wrap.h b/monitor_wrap.h #endif #ifdef USE_PAM -diff --color -ruNp a/readconf.c b/readconf.c ---- a/readconf.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/readconf.c 2024-09-16 11:46:34.699939990 +0200 -@@ -70,6 +70,7 @@ - #include "uidswap.h" +diff --git a/readconf.c b/readconf.c +index 7cbe7d2c..6c04ed43 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -71,6 +71,7 @@ #include "myproposal.h" #include "digest.h" + #include "version.h" +#include "ssh-gss.h" /* Format of the configuration file: -@@ -164,6 +165,8 @@ typedef enum { +@@ -165,6 +166,8 @@ typedef enum { oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, @@ -3142,7 +3229,7 @@ diff --color -ruNp a/readconf.c b/readconf.c oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, -@@ -210,10 +213,22 @@ static struct { +@@ -212,10 +215,22 @@ static struct { /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, @@ -3165,7 +3252,7 @@ diff --color -ruNp a/readconf.c b/readconf.c #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, -@@ -1227,10 +1242,42 @@ parse_time: +@@ -1320,10 +1335,42 @@ parse_time: intptr = &options->gss_authentication; goto parse_flag; @@ -3208,7 +3295,7 @@ diff --color -ruNp a/readconf.c b/readconf.c case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -2542,7 +2589,13 @@ initialize_options(Options * options) +@@ -2662,7 +2709,13 @@ initialize_options(Options * options) options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; options->gss_authentication = -1; @@ -3222,7 +3309,7 @@ diff --color -ruNp a/readconf.c b/readconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; -@@ -2705,8 +2758,18 @@ fill_default_options(Options * options) +@@ -2826,8 +2879,18 @@ fill_default_options(Options * options) options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3241,7 +3328,7 @@ diff --color -ruNp a/readconf.c b/readconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -3533,7 +3596,14 @@ dump_client_config(Options *o, const cha +@@ -3656,7 +3719,14 @@ dump_client_config(Options *o, const char *host) dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); #ifdef GSSAPI dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); @@ -3256,10 +3343,11 @@ diff --color -ruNp a/readconf.c b/readconf.c #endif /* GSSAPI */ dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); -diff --color -ruNp a/readconf.h b/readconf.h ---- a/readconf.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/readconf.h 2024-09-16 11:46:34.699939990 +0200 -@@ -40,7 +40,13 @@ typedef struct { +diff --git a/readconf.h b/readconf.h +index cd49139b..368523dd 100644 +--- a/readconf.h ++++ b/readconf.h +@@ -39,7 +39,13 @@ typedef struct { int pubkey_authentication; /* Try ssh2 pubkey authentication. */ int hostbased_authentication; /* ssh2's rhosts_rsa */ int gss_authentication; /* Try GSS authentication */ @@ -3273,18 +3361,19 @@ diff --color -ruNp a/readconf.h b/readconf.h int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff --color -ruNp a/servconf.c b/servconf.c ---- a/servconf.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/servconf.c 2024-09-16 11:46:34.700940011 +0200 -@@ -68,6 +68,7 @@ - #include "auth.h" +diff --git a/servconf.c b/servconf.c +index f7bc9237..d4f7fd66 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -69,6 +69,7 @@ #include "myproposal.h" #include "digest.h" + #include "version.h" +#include "ssh-gss.h" #if !defined(SSHD_PAM_SERVICE) # define SSHD_PAM_SERVICE "sshd" -@@ -137,8 +138,11 @@ initialize_server_options(ServerOptions +@@ -138,8 +139,11 @@ initialize_server_options(ServerOptions *options) options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; @@ -3296,7 +3385,7 @@ diff --color -ruNp a/servconf.c b/servconf.c options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; -@@ -376,10 +380,18 @@ fill_default_server_options(ServerOption +@@ -380,10 +384,18 @@ fill_default_server_options(ServerOptions *options) options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3315,7 +3404,7 @@ diff --color -ruNp a/servconf.c b/servconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -558,6 +570,7 @@ typedef enum { +@@ -568,6 +580,7 @@ typedef enum { sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, @@ -3323,7 +3412,7 @@ diff --color -ruNp a/servconf.c b/servconf.c sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -643,12 +656,22 @@ static struct { +@@ -653,12 +666,22 @@ static struct { #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, @@ -3346,7 +3435,7 @@ diff --color -ruNp a/servconf.c b/servconf.c { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ -@@ -1585,6 +1608,10 @@ process_server_config_line_depth(ServerO +@@ -1649,6 +1672,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->gss_authentication; goto parse_flag; @@ -3357,7 +3446,7 @@ diff --color -ruNp a/servconf.c b/servconf.c case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1593,6 +1620,22 @@ process_server_config_line_depth(ServerO +@@ -1657,6 +1684,22 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->gss_strict_acceptor; goto parse_flag; @@ -3380,7 +3469,7 @@ diff --color -ruNp a/servconf.c b/servconf.c case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -3178,6 +3221,10 @@ dump_config(ServerOptions *o) +@@ -3254,6 +3297,10 @@ dump_config(ServerOptions *o) #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); @@ -3391,10 +3480,11 @@ diff --color -ruNp a/servconf.c b/servconf.c #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, -diff --color -ruNp a/servconf.h b/servconf.h ---- a/servconf.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/servconf.h 2024-09-16 11:46:34.700940011 +0200 -@@ -149,8 +149,11 @@ typedef struct { +diff --git a/servconf.h b/servconf.h +index 9beb90fa..c3f50140 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -150,8 +150,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 */ @@ -3406,10 +3496,11 @@ diff --color -ruNp a/servconf.h b/servconf.h int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ -diff --color -ruNp a/session.c b/session.c ---- a/session.c 2024-09-16 11:45:56.866133411 +0200 -+++ b/session.c 2024-09-16 11:46:34.701940032 +0200 -@@ -2674,13 +2674,19 @@ do_cleanup(struct ssh *ssh, Authctxt *au +diff --git a/session.c b/session.c +index e4657cef..cbfbcee8 100644 +--- a/session.c ++++ b/session.c +@@ -2670,13 +2670,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) #ifdef KRB5 if (options.kerberos_ticket_cleanup && @@ -3431,542 +3522,10 @@ diff --color -ruNp a/session.c b/session.c #endif /* remove agent socket */ -diff --color -ruNp a/ssh.1 b/ssh.1 ---- a/ssh.1 2024-09-16 11:45:56.875133603 +0200 -+++ b/ssh.1 2024-09-16 11:46:34.701940032 +0200 -@@ -536,7 +536,13 @@ For full details of the options listed b - .It GatewayPorts - .It GlobalKnownHostsFile - .It GSSAPIAuthentication -+.It GSSAPIKeyExchange -+.It GSSAPIClientIdentity - .It GSSAPIDelegateCredentials -+.It GSSAPIKexAlgorithms -+.It GSSAPIRenewalForcesRekey -+.It GSSAPIServerIdentity -+.It GSSAPITrustDns - .It HashKnownHosts - .It Host - .It HostbasedAcceptedAlgorithms -@@ -624,6 +630,8 @@ flag), - (supported message integrity codes), - .Ar kex - (key exchange algorithms), -+.Ar kex-gss -+(GSSAPI key exchange algorithms), - .Ar key - (key types), - .Ar key-ca-sign -diff --color -ruNp a/ssh.c b/ssh.c ---- a/ssh.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/ssh.c 2024-09-16 11:46:34.702940054 +0200 -@@ -827,6 +827,8 @@ main(int ac, char **av) - else if (strcmp(optarg, "kex") == 0 || - strcasecmp(optarg, "KexAlgorithms") == 0) - cp = kex_alg_list('\n'); -+ else if (strcmp(optarg, "kex-gss") == 0) -+ cp = kex_gss_alg_list('\n'); - else if (strcmp(optarg, "key") == 0) - cp = sshkey_alg_list(0, 0, 0, '\n'); - else if (strcmp(optarg, "key-cert") == 0) -@@ -857,8 +859,8 @@ main(int ac, char **av) - } else if (strcmp(optarg, "help") == 0) { - cp = xstrdup( - "cipher\ncipher-auth\ncompression\nkex\n" -- "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" -- "protocol-version\nsig"); -+ "kex-gss\nkey\nkey-cert\nkey-plain\n" -+ "key-sig\nmac\nprotocol-version\nsig"); - } - if (cp == NULL) - fatal("Unsupported query \"%s\"", optarg); -diff --color -ruNp a/ssh_config b/ssh_config ---- a/ssh_config 2024-09-16 11:45:56.884133795 +0200 -+++ b/ssh_config 2024-09-16 11:46:34.702940054 +0200 -@@ -24,6 +24,8 @@ - # HostbasedAuthentication no - # GSSAPIAuthentication no - # GSSAPIDelegateCredentials no -+# GSSAPIKeyExchange no -+# GSSAPITrustDNS no - # BatchMode no - # CheckHostIP no - # AddressFamily any -diff --color -ruNp a/ssh_config.5 b/ssh_config.5 ---- a/ssh_config.5 2024-07-01 06:36:28.000000000 +0200 -+++ b/ssh_config.5 2024-09-16 11:46:34.703940075 +0200 -@@ -938,10 +938,68 @@ The default is - Specifies whether user authentication based on GSSAPI is allowed. - The default is - .Cm no . -+.It Cm GSSAPIClientIdentity -+If set, specifies the GSSAPI client identity that ssh should use when -+connecting to the server. The default is unset, which means that the default -+identity will be used. - .It Cm GSSAPIDelegateCredentials - Forward (delegate) credentials to the server. - The default is - .Cm no . -+.It Cm GSSAPIKeyExchange -+Specifies whether key exchange based on GSSAPI may be used. When using -+GSSAPI key exchange the server need not have a host key. -+The default is -+.Dq no . -+.It Cm GSSAPIRenewalForcesRekey -+If set to -+.Dq yes -+then renewal of the client's GSSAPI credentials will force the rekeying of the -+ssh connection. With a compatible server, this will delegate the renewed -+credentials to a session on the server. -+.Pp -+Checks are made to ensure that credentials are only propagated when the new -+credentials match the old ones on the originating client and where the -+receiving server still has the old set in its cache. -+.Pp -+The default is -+.Dq no . -+.Pp -+For this to work -+.Cm GSSAPIKeyExchange -+needs to be enabled in the server and also used by the client. -+.It Cm GSSAPIServerIdentity -+If set, specifies the GSSAPI server identity that ssh should expect when -+connecting to the server. The default is unset, which means that the -+expected GSSAPI server identity will be determined from the target -+hostname. -+.It Cm GSSAPITrustDns -+Set to -+.Dq yes -+to indicate that the DNS is trusted to securely canonicalize -+the name of the host being connected to. If -+.Dq no , -+the hostname entered on the -+command line will be passed untouched to the GSSAPI library. -+The default is -+.Dq no . -+.It Cm GSSAPIKexAlgorithms -+The list of key exchange algorithms that are offered for GSSAPI -+key exchange. Possible values are -+.Bd -literal -offset 3n -+gss-gex-sha1-, -+gss-group1-sha1-, -+gss-group14-sha1-, -+gss-group14-sha256-, -+gss-group16-sha512-, -+gss-nistp256-sha256-, -+gss-curve25519-sha256- -+.Ed -+.Pp -+The default is -+.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, -+gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . -+This option only applies to connections using GSSAPI. - .It Cm HashKnownHosts - Indicates that - .Xr ssh 1 -diff --color -ruNp a/sshconnect2.c b/sshconnect2.c ---- a/sshconnect2.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/sshconnect2.c 2024-09-16 11:46:34.703940075 +0200 -@@ -222,6 +222,11 @@ ssh_kex2(struct ssh *ssh, char *host, st - char *all_key, *hkalgs = NULL; - int r, use_known_hosts_order = 0; - -+#if defined(GSSAPI) && defined(WITH_OPENSSL) -+ char *orig = NULL, *gss = NULL; -+ char *gss_host = NULL; -+#endif -+ - xxx_host = host; - xxx_hostaddr = hostaddr; - xxx_conn_info = cinfo; -@@ -255,6 +260,42 @@ ssh_kex2(struct ssh *ssh, char *host, st - 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 -+ * client to the key exchange algorithm proposal */ -+ orig = myproposal[PROPOSAL_KEX_ALGS]; -+ -+ if (options.gss_server_identity) { -+ gss_host = xstrdup(options.gss_server_identity); -+ } else if (options.gss_trust_dns) { -+ gss_host = remote_hostname(ssh); -+ /* Fall back to specified host if we are using proxy command -+ * and can not use DNS on that socket */ -+ if (strcmp(gss_host, "UNKNOWN") == 0) { -+ free(gss_host); -+ gss_host = xstrdup(host); -+ } -+ } else { -+ gss_host = xstrdup(host); -+ } -+ -+ gss = ssh_gssapi_client_mechanisms(gss_host, -+ options.gss_client_identity, options.gss_kex_algorithms); -+ if (gss) { -+ debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -+ "%s,%s", gss, orig); -+ -+ /* If we've got GSSAPI algorithms, then we also support the -+ * 'null' hostkey, as a last resort */ -+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; -+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "%s,null", orig); -+ } -+ } -+#endif -+ - free(hkalgs); - - /* start key exchange */ -@@ -271,15 +312,45 @@ ssh_kex2(struct ssh *ssh, char *host, st - # ifdef OPENSSL_HAS_ECC - ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; - # endif --#endif -+# ifdef GSSAPI -+ if (options.gss_keyex) { -+ ssh->kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; -+ ssh->kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; -+ ssh->kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client; -+ ssh->kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client; -+ ssh->kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_client; -+ ssh->kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_client; -+ ssh->kex->kex[KEX_GSS_C25519_SHA256] = kexgss_client; -+ } -+# 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_MLKEM768X25519_SHA256] = kex_gen_client; - ssh->kex->verify_host_key=&verify_host_key_callback; - -+#if defined(GSSAPI) && defined(WITH_OPENSSL) -+ if (options.gss_keyex) { -+ ssh->kex->gss_deleg_creds = options.gss_deleg_creds; -+ ssh->kex->gss_trust_dns = options.gss_trust_dns; -+ ssh->kex->gss_client = options.gss_client_identity; -+ ssh->kex->gss_host = gss_host; -+ } -+#endif -+ - ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); - kex_proposal_free_entries(myproposal); - -+#if defined(GSSAPI) && defined(WITH_OPENSSL) -+ /* repair myproposal after it was crumpled by the */ -+ /* ext-info removal above */ -+ if (gss) { -+ orig = myproposal[PROPOSAL_KEX_ALGS]; -+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -+ "%s,%s", gss, orig); -+ free(gss); -+ } -+#endif - #ifdef DEBUG_KEXDH - /* send 1st encrypted/maced/compressed message */ - if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || -@@ -368,6 +439,7 @@ static int input_gssapi_response(int typ - 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 *); -+static int userauth_gsskeyex(struct ssh *); - #endif - - void userauth(struct ssh *, char *); -@@ -384,6 +456,11 @@ static char *authmethods_get(void); - - Authmethod authmethods[] = { - #ifdef GSSAPI -+ {"gssapi-keyex", -+ userauth_gsskeyex, -+ NULL, -+ &options.gss_keyex, -+ NULL}, - {"gssapi-with-mic", - userauth_gssapi, - userauth_gssapi_cleanup, -@@ -755,12 +832,32 @@ userauth_gssapi(struct ssh *ssh) - OM_uint32 min; - int r, ok = 0; - gss_OID mech = NULL; -+ char *gss_host = NULL; -+ -+ if (options.gss_server_identity) { -+ gss_host = xstrdup(options.gss_server_identity); -+ } else if (options.gss_trust_dns) { -+ gss_host = remote_hostname(ssh); -+ /* Fall back to specified host if we are using proxy command -+ * and can not use DNS on that socket */ -+ if (strcmp(gss_host, "UNKNOWN") == 0) { -+ free(gss_host); -+ gss_host = xstrdup(authctxt->host); -+ } -+ } else { -+ gss_host = xstrdup(authctxt->host); -+ } - - /* Try one GSSAPI method at a time, rather than sending them all at - * once. */ - - if (authctxt->gss_supported_mechs == NULL) -- gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); -+ if (GSS_ERROR(gss_indicate_mechs(&min, -+ &authctxt->gss_supported_mechs))) { -+ authctxt->gss_supported_mechs = NULL; -+ free(gss_host); -+ return 0; -+ } - - /* Check to see whether the mechanism is usable before we offer it */ - while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && -@@ -769,13 +866,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, -- mech, authctxt->host)) { -+ mech, gss_host, options.gss_client_identity)) { - ok = 1; /* Mechanism works */ - } else { - authctxt->mech_tried++; - } - } - -+ free(gss_host); -+ - if (!ok || mech == NULL) - return 0; - -@@ -1009,6 +1108,55 @@ input_gssapi_error(int type, u_int32_t p - free(lang); - return r; - } -+ -+int -+userauth_gsskeyex(struct ssh *ssh) -+{ -+ struct sshbuf *b = NULL; -+ Authctxt *authctxt = ssh->authctxt; -+ gss_buffer_desc gssbuf; -+ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; -+ OM_uint32 ms; -+ int r; -+ -+ static int attempt = 0; -+ if (attempt++ >= 1) -+ return (0); -+ -+ if (gss_kex_context == NULL) { -+ debug("No valid Key exchange context"); -+ return (0); -+ } -+ -+ if ((b = sshbuf_new()) == NULL) -+ fatal_f("sshbuf_new failed"); -+ -+ ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, -+ "gssapi-keyex", ssh->kex->session_id); -+ -+ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) -+ fatal_f("sshbuf_mutable_ptr failed"); -+ gssbuf.length = sshbuf_len(b); -+ -+ if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { -+ sshbuf_free(b); -+ return (0); -+ } -+ -+ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || -+ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || -+ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || -+ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || -+ (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || -+ (r = sshpkt_send(ssh)) != 0) -+ fatal_fr(r, "parsing"); -+ -+ sshbuf_free(b); -+ gss_release_buffer(&ms, &mic); -+ -+ return (1); -+} -+ - #endif /* GSSAPI */ - - static int -diff --color -ruNp a/sshd.c b/sshd.c ---- a/sshd.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/sshd.c 2024-09-16 11:46:34.704940096 +0200 -@@ -1551,7 +1551,8 @@ main(int ac, char **av) - free(fp); - } - accumulate_host_timing_secret(cfg, NULL); -- if (!sensitive_data.have_ssh2_key) { -+ /* The GSSAPI key exchange can run without a host key */ -+ if (!sensitive_data.have_ssh2_key && !options.gss_keyex) { - logit("sshd: no hostkeys available -- exiting."); - exit(1); - } -diff --color -ruNp a/sshd_config b/sshd_config ---- a/sshd_config 2024-09-16 11:45:56.888133880 +0200 -+++ b/sshd_config 2024-09-16 11:46:34.704940096 +0200 -@@ -77,6 +77,8 @@ AuthorizedKeysFile .ssh/authorized_keys - # GSSAPI options - #GSSAPIAuthentication no - #GSSAPICleanupCredentials yes -+#GSSAPIStrictAcceptorCheck yes -+#GSSAPIKeyExchange no - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -diff --color -ruNp a/sshd_config.5 b/sshd_config.5 ---- a/sshd_config.5 2024-09-16 11:45:56.885133816 +0200 -+++ b/sshd_config.5 2024-09-16 11:46:34.704940096 +0200 -@@ -739,6 +739,11 @@ Specifies whether to automatically destr - on logout. - The default is - .Cm yes . -+.It Cm GSSAPIKeyExchange -+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange -+doesn't rely on ssh keys to verify host identity. -+The default is -+.Cm no . - .It Cm GSSAPIStrictAcceptorCheck - Determines whether to be strict about the identity of the GSSAPI acceptor - a client authenticates against. -@@ -753,6 +758,32 @@ machine's default store. - This facility is provided to assist with operation on multi homed machines. - The default is - .Cm yes . -+.It Cm GSSAPIStoreCredentialsOnRekey -+Controls whether the user's GSSAPI credentials should be updated following a -+successful connection rekeying. This option can be used to accepted renewed -+or updated credentials from a compatible client. The default is -+.Dq no . -+.Pp -+For this to work -+.Cm GSSAPIKeyExchange -+needs to be enabled in the server and also used by the client. -+.It Cm GSSAPIKexAlgorithms -+The list of key exchange algorithms that are accepted by GSSAPI -+key exchange. Possible values are -+.Bd -literal -offset 3n -+gss-gex-sha1-, -+gss-group1-sha1-, -+gss-group14-sha1-, -+gss-group14-sha256-, -+gss-group16-sha512-, -+gss-nistp256-sha256-, -+gss-curve25519-sha256- -+.Ed -+.Pp -+The default is -+.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, -+gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . -+This option only applies to connections using GSSAPI. - .It Cm HostbasedAcceptedAlgorithms - Specifies the signature algorithms that will be accepted for hostbased - authentication as a list of comma-separated patterns. -diff --color -ruNp a/sshd-session.c b/sshd-session.c ---- a/sshd-session.c 2024-09-16 11:45:56.888133880 +0200 -+++ b/sshd-session.c 2024-09-16 11:46:34.705940118 +0200 -@@ -660,8 +660,8 @@ notify_hostkeys(struct ssh *ssh) - } - debug3_f("sent %u hostkeys", nkeys); - if (nkeys == 0) -- fatal_f("no hostkeys"); -- if ((r = sshpkt_send(ssh)) != 0) -+ debug3_f("no hostkeys"); -+ else if ((r = sshpkt_send(ssh)) != 0) - sshpkt_fatal(ssh, r, "%s: send", __func__); - sshbuf_free(buf); - } -@@ -1180,8 +1180,9 @@ main(int ac, char **av) - break; - } - } -- if (!have_key) -- fatal("internal error: monitor received no hostkeys"); -+ /* The GSSAPI key exchange can run without a host key */ -+ if (!have_key && !options.gss_keyex) -+ fatal("internal error: monitor received no hostkeys and GSS KEX is not configured"); - - /* Ensure that umask disallows at least group and world write */ - new_umask = umask(0077) | 0022; -@@ -1462,6 +1463,48 @@ do_ssh2_kex(struct ssh *ssh) - - free(hkalgs); - -+#if defined(GSSAPI) && defined(WITH_OPENSSL) -+ { -+ char *orig; -+ char *gss = NULL; -+ char *newstr = NULL; -+ 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 (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) -+ orig = NULL; -+ -+ if (options.gss_keyex) -+ gss = ssh_gssapi_server_mechanisms(); -+ else -+ gss = NULL; -+ -+ if (gss && orig) -+ xasprintf(&newstr, "%s,%s", gss, orig); -+ else if (gss) -+ xasprintf(&newstr, "%s,%s", gss, "kex-strict-s-v00@openssh.com"); -+ else if (orig) -+ 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 (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xstrdup("null"); -+ -+ if (newstr) -+ myproposal[PROPOSAL_KEX_ALGS] = newstr; -+ else -+ fatal("No supported key exchange algorithms"); -+ } -+#endif -+ - /* start key exchange */ - if ((r = kex_setup(ssh, myproposal)) != 0) - fatal_r(r, "kex_setup"); -@@ -1479,7 +1522,18 @@ do_ssh2_kex(struct ssh *ssh) - #ifdef OPENSSL_HAS_ECC - kex->kex[KEX_ECDH_SHA2] = kex_gen_server; - #endif --#endif -+# ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; -+ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; -+ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; -+ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; -+ } -+# endif -+#endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kex_gen_server; - kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; - kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; -diff --color -ruNp a/ssh-gss.h b/ssh-gss.h ---- a/ssh-gss.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/ssh-gss.h 2024-09-16 11:46:34.710940224 +0200 +diff --git a/ssh-gss.h b/ssh-gss.h +index 7b14e74a..8ec45192 100644 +--- a/ssh-gss.h ++++ b/ssh-gss.h @@ -61,10 +61,36 @@ #define SSH_GSS_OIDTYPE 0x06 @@ -4047,7 +3606,7 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -108,6 +149,7 @@ OM_uint32 ssh_gssapi_test_oid_supported( +@@ -108,6 +149,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 *); @@ -4091,10 +3650,557 @@ diff --color -ruNp a/ssh-gss.h b/ssh-gss.h #endif /* GSSAPI */ #endif /* _SSH_GSS_H */ -diff --color -ruNp a/sshkey.c b/sshkey.c ---- a/sshkey.c 2024-07-01 06:36:28.000000000 +0200 -+++ b/sshkey.c 2024-09-16 11:46:34.706940139 +0200 -@@ -131,6 +131,75 @@ extern const struct sshkey_impl sshkey_x +diff --git a/ssh.1 b/ssh.1 +index db92ac9a..6a9fbdc5 100644 +--- a/ssh.1 ++++ b/ssh.1 +@@ -539,9 +539,15 @@ For full details of the options listed below, and their possible values, see + .It ForwardX11Timeout + .It ForwardX11Trusted + .It GSSAPIAuthentication ++.It GSSAPIKeyExchange ++.It GSSAPIClientIdentity + .It GSSAPIDelegateCredentials + .It GatewayPorts + .It GlobalKnownHostsFile ++.It GSSAPIKexAlgorithms ++.It GSSAPIRenewalForcesRekey ++.It GSSAPIServerIdentity ++.It GSSAPITrustDns + .It HashKnownHosts + .It Host + .It HostKeyAlgorithms +@@ -636,6 +642,8 @@ flag), + (supported message integrity codes), + .Ar kex + (key exchange algorithms), ++.Ar kex-gss ++(GSSAPI key exchange algorithms), + .Ar key + (key types), + .Ar key-ca-sign +diff --git a/ssh.c b/ssh.c +index dc4886d0..c23d3b9e 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -835,6 +835,8 @@ main(int ac, char **av) + else if (strcmp(optarg, "kex") == 0 || + strcasecmp(optarg, "KexAlgorithms") == 0) + cp = kex_alg_list('\n'); ++ else if (strcmp(optarg, "kex-gss") == 0) ++ cp = kex_gss_alg_list('\n'); + else if (strcmp(optarg, "key") == 0) + cp = sshkey_alg_list(0, 0, 0, '\n'); + else if (strcmp(optarg, "key-cert") == 0) +@@ -865,8 +867,8 @@ main(int ac, char **av) + } else if (strcmp(optarg, "help") == 0) { + cp = xstrdup( + "cipher\ncipher-auth\ncompression\nkex\n" +- "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" +- "protocol-version\nsig"); ++ "kex-gss\nkey\nkey-cert\nkey-plain\n" ++ "key-sig\nmac\nprotocol-version\nsig"); + } + if (cp == NULL) + fatal("Unsupported query \"%s\"", optarg); +diff --git a/ssh_config b/ssh_config +index 18169187..209248d6 100644 +--- a/ssh_config ++++ b/ssh_config +@@ -24,6 +24,8 @@ + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP no + # AddressFamily any +diff --git a/ssh_config.5 b/ssh_config.5 +index 894d7383..3a8e246c 100644 +--- a/ssh_config.5 ++++ b/ssh_config.5 +@@ -976,10 +976,68 @@ The default is + Specifies whether user authentication based on GSSAPI is allowed. + The default is + .Cm no . ++.It Cm GSSAPIClientIdentity ++If set, specifies the GSSAPI client identity that ssh should use when ++connecting to the server. The default is unset, which means that the default ++identity will be used. + .It Cm GSSAPIDelegateCredentials + Forward (delegate) credentials to the server. + The default is + .Cm no . ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI may be used. When using ++GSSAPI key exchange the server need not have a host key. ++The default is ++.Dq no . ++.It Cm GSSAPIRenewalForcesRekey ++If set to ++.Dq yes ++then renewal of the client's GSSAPI credentials will force the rekeying of the ++ssh connection. With a compatible server, this will delegate the renewed ++credentials to a session on the server. ++.Pp ++Checks are made to ensure that credentials are only propagated when the new ++credentials match the old ones on the originating client and where the ++receiving server still has the old set in its cache. ++.Pp ++The default is ++.Dq no . ++.Pp ++For this to work ++.Cm GSSAPIKeyExchange ++needs to be enabled in the server and also used by the client. ++.It Cm GSSAPIServerIdentity ++If set, specifies the GSSAPI server identity that ssh should expect when ++connecting to the server. The default is unset, which means that the ++expected GSSAPI server identity will be determined from the target ++hostname. ++.It Cm GSSAPITrustDns ++Set to ++.Dq yes ++to indicate that the DNS is trusted to securely canonicalize ++the name of the host being connected to. If ++.Dq no , ++the hostname entered on the ++command line will be passed untouched to the GSSAPI library. ++The default is ++.Dq no . ++.It Cm GSSAPIKexAlgorithms ++The list of key exchange algorithms that are offered for GSSAPI ++key exchange. Possible values are ++.Bd -literal -offset 3n ++gss-gex-sha1-, ++gss-group1-sha1-, ++gss-group14-sha1-, ++gss-group14-sha256-, ++gss-group16-sha512-, ++gss-nistp256-sha256-, ++gss-curve25519-sha256- ++.Ed ++.Pp ++The default is ++.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, ++gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . ++This option only applies to connections using GSSAPI. + .It Cm HashKnownHosts + Indicates that + .Xr ssh 1 +diff --git a/sshconnect2.c b/sshconnect2.c +index 1ee6000a..0af15bcc 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -222,6 +222,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, + char *all_key, *hkalgs = NULL; + int r, use_known_hosts_order = 0; + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ char *orig = NULL, *gss = NULL; ++ char *gss_host = NULL; ++#endif ++ + xxx_host = host; + xxx_hostaddr = hostaddr; + xxx_conn_info = cinfo; +@@ -255,6 +260,42 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, + 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 ++ * client to the key exchange algorithm proposal */ ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ ++ if (options.gss_server_identity) { ++ gss_host = xstrdup(options.gss_server_identity); ++ } else if (options.gss_trust_dns) { ++ gss_host = remote_hostname(ssh); ++ /* Fall back to specified host if we are using proxy command ++ * and can not use DNS on that socket */ ++ if (strcmp(gss_host, "UNKNOWN") == 0) { ++ free(gss_host); ++ gss_host = xstrdup(host); ++ } ++ } else { ++ gss_host = xstrdup(host); ++ } ++ ++ gss = ssh_gssapi_client_mechanisms(gss_host, ++ options.gss_client_identity, options.gss_kex_algorithms); ++ if (gss) { ++ debug("Offering GSSAPI proposal: %s", gss); ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ ++ /* If we've got GSSAPI algorithms, then we also support the ++ * 'null' hostkey, as a last resort */ ++ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "%s,null", orig); ++ } ++ } ++#endif ++ + free(hkalgs); + + /* start key exchange */ +@@ -271,15 +312,45 @@ 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 +-#endif ++# ifdef GSSAPI ++ if (options.gss_keyex) { ++ ssh->kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_client; ++ ssh->kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_C25519_SHA256] = kexgss_client; ++ } ++# 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_MLKEM768X25519_SHA256] = kex_gen_client; + ssh->kex->verify_host_key=&verify_host_key_callback; + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ if (options.gss_keyex) { ++ ssh->kex->gss_deleg_creds = options.gss_deleg_creds; ++ ssh->kex->gss_trust_dns = options.gss_trust_dns; ++ ssh->kex->gss_client = options.gss_client_identity; ++ ssh->kex->gss_host = gss_host; ++ } ++#endif ++ + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); + kex_proposal_free_entries(myproposal); + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ /* repair myproposal after it was crumpled by the */ ++ /* ext-info removal above */ ++ if (gss) { ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ free(gss); ++ } ++#endif + #ifdef DEBUG_KEXDH + /* send 1st encrypted/maced/compressed message */ + if ((r = sshpkt_start(ssh, SSH2_MSG_IGNORE)) != 0 || +@@ -369,6 +440,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 *); ++static int userauth_gsskeyex(struct ssh *); + #endif + + void userauth(struct ssh *, char *); +@@ -385,6 +457,11 @@ static char *authmethods_get(void); + + Authmethod authmethods[] = { + #ifdef GSSAPI ++ {"gssapi-keyex", ++ userauth_gsskeyex, ++ NULL, ++ &options.gss_keyex, ++ NULL}, + {"gssapi-with-mic", + userauth_gssapi, + userauth_gssapi_cleanup, +@@ -759,12 +836,32 @@ userauth_gssapi(struct ssh *ssh) + OM_uint32 min; + int r, ok = 0; + gss_OID mech = NULL; ++ char *gss_host = NULL; ++ ++ if (options.gss_server_identity) { ++ gss_host = xstrdup(options.gss_server_identity); ++ } else if (options.gss_trust_dns) { ++ gss_host = remote_hostname(ssh); ++ /* Fall back to specified host if we are using proxy command ++ * and can not use DNS on that socket */ ++ if (strcmp(gss_host, "UNKNOWN") == 0) { ++ free(gss_host); ++ gss_host = xstrdup(authctxt->host); ++ } ++ } else { ++ gss_host = xstrdup(authctxt->host); ++ } + + /* Try one GSSAPI method at a time, rather than sending them all at + * once. */ + + if (authctxt->gss_supported_mechs == NULL) +- gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); ++ if (GSS_ERROR(gss_indicate_mechs(&min, ++ &authctxt->gss_supported_mechs))) { ++ authctxt->gss_supported_mechs = NULL; ++ free(gss_host); ++ return 0; ++ } + + /* Check to see whether the mechanism is usable before we offer it */ + while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && +@@ -773,13 +870,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, +- mech, authctxt->host)) { ++ mech, gss_host, options.gss_client_identity)) { + ok = 1; /* Mechanism works */ + } else { + authctxt->mech_tried++; + } + } + ++ free(gss_host); ++ + if (!ok || mech == NULL) + return 0; + +@@ -1013,6 +1112,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) + free(lang); + return r; + } ++ ++int ++userauth_gsskeyex(struct ssh *ssh) ++{ ++ struct sshbuf *b = NULL; ++ Authctxt *authctxt = ssh->authctxt; ++ gss_buffer_desc gssbuf; ++ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; ++ OM_uint32 ms; ++ int r; ++ ++ static int attempt = 0; ++ if (attempt++ >= 1) ++ return (0); ++ ++ if (gss_kex_context == NULL) { ++ debug("No valid Key exchange context"); ++ return (0); ++ } ++ ++ if ((b = sshbuf_new()) == NULL) ++ fatal_f("sshbuf_new failed"); ++ ++ ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, ++ "gssapi-keyex", ssh->kex->session_id); ++ ++ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) ++ fatal_f("sshbuf_mutable_ptr failed"); ++ gssbuf.length = sshbuf_len(b); ++ ++ if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { ++ sshbuf_free(b); ++ return (0); ++ } ++ ++ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || ++ (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal_fr(r, "parsing"); ++ ++ sshbuf_free(b); ++ gss_release_buffer(&ms, &mic); ++ ++ return (1); ++} ++ + #endif /* GSSAPI */ + + static int +diff --git a/sshd-auth.c b/sshd-auth.c +index f957dc22..d51e4636 100644 +--- a/sshd-auth.c ++++ b/sshd-auth.c +@@ -844,6 +844,48 @@ do_ssh2_kex(struct ssh *ssh) + + free(hkalgs); + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ { ++ char *orig; ++ char *gss = NULL; ++ char *newstr = NULL; ++ 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 (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) ++ orig = NULL; ++ ++ if (options.gss_keyex) ++ gss = ssh_gssapi_server_mechanisms(); ++ else ++ gss = NULL; ++ ++ if (gss && orig) ++ xasprintf(&newstr, "%s,%s", gss, orig); ++ else if (gss) ++ xasprintf(&newstr, "%s,%s", gss, "kex-strict-s-v00@openssh.com"); ++ else if (orig) ++ 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 (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) ++ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = xstrdup("null"); ++ ++ if (newstr) ++ myproposal[PROPOSAL_KEX_ALGS] = newstr; ++ else ++ fatal("No supported key exchange algorithms"); ++ } ++#endif ++ + /* start key exchange */ + if ((r = kex_setup(ssh, myproposal)) != 0) + fatal_r(r, "kex_setup"); +@@ -861,6 +903,17 @@ do_ssh2_kex(struct ssh *ssh) + # ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; + # endif /* OPENSSL_HAS_ECC */ ++# ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; ++ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; ++ } ++# endif + #endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; +diff --git a/sshd-session.c b/sshd-session.c +index a70b36c9..f8c8a797 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -616,8 +616,8 @@ notify_hostkeys(struct ssh *ssh) + } + debug3_f("sent %u hostkeys", nkeys); + if (nkeys == 0) +- fatal_f("no hostkeys"); +- if ((r = sshpkt_send(ssh)) != 0) ++ debug3_f("no hostkeys"); ++ else if ((r = sshpkt_send(ssh)) != 0) + sshpkt_fatal(ssh, r, "%s: send", __func__); + sshbuf_free(buf); + } +@@ -1159,8 +1159,9 @@ main(int ac, char **av) + break; + } + } +- if (!have_key) +- fatal("internal error: monitor received no hostkeys"); ++ /* The GSSAPI key exchange can run without a host key */ ++ if (!have_key && !options.gss_keyex) ++ fatal("internal error: monitor received no hostkeys and GSS KEX is not configured"); + + /* Ensure that umask disallows at least group and world write */ + new_umask = umask(0077) | 0022; +diff --git a/sshd.c b/sshd.c +index 4a93e29e..c9ea8e38 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -1676,7 +1676,8 @@ main(int ac, char **av) + free(fp); + } + accumulate_host_timing_secret(cfg, NULL); +- if (!sensitive_data.have_ssh2_key) { ++ /* The GSSAPI key exchange can run without a host key */ ++ if (!sensitive_data.have_ssh2_key && !options.gss_keyex) { + logit("sshd: no hostkeys available -- exiting."); + exit(1); + } +diff --git a/sshd_config b/sshd_config +index 48af6321..8db9f0fb 100644 +--- a/sshd_config ++++ b/sshd_config +@@ -79,6 +79,8 @@ AuthorizedKeysFile .ssh/authorized_keys + # GSSAPI options + #GSSAPIAuthentication no + #GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # 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 035a50c8..8bc6586e 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -739,6 +739,11 @@ Specifies whether to automatically destroy the user's credentials cache + on logout. + The default is + .Cm yes . ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange ++doesn't rely on ssh keys to verify host identity. ++The default is ++.Cm no . + .It Cm GSSAPIStrictAcceptorCheck + Determines whether to be strict about the identity of the GSSAPI acceptor + a client authenticates against. +@@ -753,6 +758,32 @@ machine's default store. + This facility is provided to assist with operation on multi homed machines. + The default is + .Cm yes . ++.It Cm GSSAPIStoreCredentialsOnRekey ++Controls whether the user's GSSAPI credentials should be updated following a ++successful connection rekeying. This option can be used to accepted renewed ++or updated credentials from a compatible client. The default is ++.Dq no . ++.Pp ++For this to work ++.Cm GSSAPIKeyExchange ++needs to be enabled in the server and also used by the client. ++.It Cm GSSAPIKexAlgorithms ++The list of key exchange algorithms that are accepted by GSSAPI ++key exchange. Possible values are ++.Bd -literal -offset 3n ++gss-gex-sha1-, ++gss-group1-sha1-, ++gss-group14-sha1-, ++gss-group14-sha256-, ++gss-group16-sha512-, ++gss-nistp256-sha256-, ++gss-curve25519-sha256- ++.Ed ++.Pp ++The default is ++.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, ++gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . ++This option only applies to connections using GSSAPI. + .It Cm HostbasedAcceptedAlgorithms + 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 ab80752b..4e41a78c 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -129,6 +129,75 @@ extern const struct sshkey_impl sshkey_xmss_impl; extern const struct sshkey_impl sshkey_xmss_cert_impl; #endif @@ -4170,7 +4276,7 @@ diff --color -ruNp a/sshkey.c b/sshkey.c const struct sshkey_impl * const keyimpls[] = { &sshkey_ed25519_impl, &sshkey_ed25519_cert_impl, -@@ -169,6 +238,7 @@ const struct sshkey_impl * const keyimpl +@@ -167,6 +236,7 @@ const struct sshkey_impl * const keyimpls[] = { &sshkey_xmss_impl, &sshkey_xmss_cert_impl, #endif @@ -4178,7 +4284,7 @@ diff --color -ruNp a/sshkey.c b/sshkey.c NULL }; -@@ -324,7 +394,7 @@ sshkey_alg_list(int certs_only, int plai +@@ -336,7 +406,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; @@ -4187,10 +4293,11 @@ diff --color -ruNp a/sshkey.c b/sshkey.c continue; if (!include_sigonly && impl->sigonly) continue; -diff --color -ruNp a/sshkey.h b/sshkey.h ---- a/sshkey.h 2024-07-01 06:36:28.000000000 +0200 -+++ b/sshkey.h 2024-09-16 11:46:34.706940139 +0200 -@@ -71,6 +71,7 @@ enum sshkey_types { +diff --git a/sshkey.h b/sshkey.h +index 19bbbac7..4a318d05 100644 +--- a/sshkey.h ++++ b/sshkey.h +@@ -75,6 +75,7 @@ enum sshkey_types { KEY_ECDSA_SK_CERT, KEY_ED25519_SK, KEY_ED25519_SK_CERT, @@ -4198,3 +4305,6 @@ diff --color -ruNp a/sshkey.h b/sshkey.h KEY_UNSPEC }; +-- +2.49.0 + diff --git a/openssh-6.6p1-force_krb.patch b/0013-openssh-6.6p1-force_krb.patch similarity index 88% rename from openssh-6.6p1-force_krb.patch rename to 0013-openssh-6.6p1-force_krb.patch index 90f8322..74643b5 100644 --- a/openssh-6.6p1-force_krb.patch +++ b/0013-openssh-6.6p1-force_krb.patch @@ -1,5 +1,17 @@ +From f5e5ee321def2a3674600714ad98fd1ca9b2cff1 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 13/50] openssh-6.6p1-force_krb + +--- + gss-serv-krb5.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++- + session.c | 23 +++++++ + ssh-gss.h | 4 ++ + sshd.8 | 7 +++ + 4 files changed, 189 insertions(+), 1 deletion(-) + diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index 413b845..54dd383 100644 +index 8d2b677f..14502c5a 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c @@ -32,7 +32,9 @@ @@ -12,7 +24,7 @@ index 413b845..54dd383 100644 #include "xmalloc.h" #include "sshkey.h" -@@ -45,6 +47,7 @@ +@@ -44,6 +46,7 @@ #include "ssh-gss.h" @@ -20,7 +32,7 @@ index 413b845..54dd383 100644 extern ServerOptions options; #ifdef HEIMDAL -@@ -56,6 +59,13 @@ extern ServerOptions options; +@@ -55,6 +58,13 @@ extern ServerOptions options; # include #endif @@ -34,7 +46,7 @@ index 413b845..54dd383 100644 static krb5_context krb_context = NULL; /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ -@@ -88,6 +98,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) +@@ -87,6 +97,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) krb5_principal princ; int retval; const char *errmsg; @@ -42,7 +54,7 @@ index 413b845..54dd383 100644 if (ssh_gssapi_krb5_init() == 0) return 0; -@@ -99,10 +110,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) +@@ -98,10 +109,22 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) krb5_free_error_message(krb_context, errmsg); return 0; } @@ -66,7 +78,7 @@ index 413b845..54dd383 100644 } else retval = 0; -@@ -110,6 +133,137 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) +@@ -109,6 +132,137 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) return retval; } @@ -205,10 +217,10 @@ index 413b845..54dd383 100644 /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ diff --git a/session.c b/session.c -index 28659ec..9c94d8e 100644 +index cbfbcee8..89b3a9cf 100644 --- a/session.c +++ b/session.c -@@ -789,6 +789,29 @@ do_exec(Session *s, const char *command) +@@ -680,6 +680,29 @@ do_exec(struct ssh *ssh, Session *s, const char *command) command = auth_opts->force_command; forced = "(key-option)"; } @@ -239,7 +251,7 @@ index 28659ec..9c94d8e 100644 if (forced != NULL) { s->forced = 1; diff --git a/ssh-gss.h b/ssh-gss.h -index 0374c88..509109a 100644 +index 8ec45192..db34d77f 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -49,6 +49,10 @@ @@ -254,10 +266,10 @@ index 0374c88..509109a 100644 /* draft-ietf-secsh-gsskeyex-06 */ diff --git a/sshd.8 b/sshd.8 -index adcaaf9..824163b 100644 +index 2aa73271..049d0a94 100644 --- a/sshd.8 +++ b/sshd.8 -@@ -324,6 +324,7 @@ Finally, the server and the client enter an authentication dialog. +@@ -286,6 +286,7 @@ Finally, the server and the client enter an authentication dialog. The client tries to authenticate itself using host-based authentication, public key authentication, @@ -265,7 +277,7 @@ index adcaaf9..824163b 100644 challenge-response authentication, or password authentication. .Pp -@@ -800,6 +801,12 @@ This file is used in exactly the same way as +@@ -874,6 +875,12 @@ This file is used in exactly the same way as but allows host-based authentication without permitting login with rlogin/rsh. .Pp @@ -278,3 +290,6 @@ index adcaaf9..824163b 100644 .It Pa ~/.ssh/ This directory is the default location for all user-specific configuration and authentication information. +-- +2.49.0 + diff --git a/openssh-7.7p1-gssapi-new-unique.patch b/0014-openssh-7.7p1-gssapi-new-unique.patch similarity index 79% rename from openssh-7.7p1-gssapi-new-unique.patch rename to 0014-openssh-7.7p1-gssapi-new-unique.patch index 34b9b9d..1d21839 100644 --- a/openssh-7.7p1-gssapi-new-unique.patch +++ b/0014-openssh-7.7p1-gssapi-new-unique.patch @@ -1,26 +1,25 @@ -diff -up openssh-8.6p1/auth.h.ccache_name openssh-8.6p1/auth.h ---- openssh-8.6p1/auth.h.ccache_name 2021-04-19 14:05:10.820744325 +0200 -+++ openssh-8.6p1/auth.h 2021-04-19 14:05:10.853744569 +0200 -@@ -83,6 +83,7 @@ struct Authctxt { - krb5_principal krb5_user; - char *krb5_ticket_file; - char *krb5_ccname; -+ int krb5_set_env; - #endif - struct sshbuf *loginmsg; - -@@ -231,7 +232,7 @@ struct passwd *fakepw(void); - int sys_auth_passwd(struct ssh *, const char *); - - #if defined(KRB5) && !defined(HEIMDAL) --krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *); -+krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *); - #endif - - #endif /* AUTH_H */ -diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c ---- openssh-8.6p1/auth-krb5.c.ccache_name 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/auth-krb5.c 2021-04-19 14:40:55.142832954 +0200 +From 5fca5946aa97dce23c6824c52b070a92532752a9 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 14/50] openssh-7.7p1-gssapi-new-unique + +--- + auth-krb5.c | 262 ++++++++++++++++++++++++++++++++++++++++++------ + auth.h | 3 +- + gss-serv-krb5.c | 42 +++----- + gss-serv.c | 10 +- + servconf.c | 12 ++- + servconf.h | 2 + + session.c | 5 +- + ssh-gss.h | 4 +- + sshd-session.c | 2 +- + sshd_config.5 | 8 ++ + 10 files changed, 279 insertions(+), 71 deletions(-) + +diff --git a/auth-krb5.c b/auth-krb5.c +index c99e4e43..77714e3d 100644 +--- a/auth-krb5.c ++++ b/auth-krb5.c @@ -51,6 +51,7 @@ #include #include @@ -29,7 +28,7 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c extern ServerOptions options; -@@ -77,7 +78,7 @@ auth_krb5_password(Authctxt *authctxt, c +@@ -77,7 +78,7 @@ auth_krb5_password(Authctxt *authctxt, const char *password) #endif krb5_error_code problem; krb5_ccache ccache = NULL; @@ -38,7 +37,7 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c char *client, *platform_client; const char *errmsg; -@@ -163,8 +164,8 @@ auth_krb5_password(Authctxt *authctxt, c +@@ -163,8 +164,8 @@ auth_krb5_password(Authctxt *authctxt, const char *password) goto out; } @@ -49,7 +48,7 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c if (problem) goto out; -@@ -179,15 +180,14 @@ auth_krb5_password(Authctxt *authctxt, c +@@ -179,15 +180,14 @@ auth_krb5_password(Authctxt *authctxt, const char *password) goto out; #endif @@ -70,7 +69,7 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c do_pam_putenv("KRB5CCNAME", authctxt->krb5_ccname); #endif -@@ -223,11 +223,54 @@ auth_krb5_password(Authctxt *authctxt, c +@@ -223,11 +223,54 @@ auth_krb5_password(Authctxt *authctxt, const char *password) void krb5_cleanup_proc(Authctxt *authctxt) { @@ -131,7 +130,24 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c } -#ifndef HEIMDAL -+ +-krb5_error_code +-ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { +- int tmpfd, ret, oerrno; +- char ccname[40]; +- mode_t old_umask; + +- ret = snprintf(ccname, sizeof(ccname), +- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); +- if (ret < 0 || (size_t)ret >= sizeof(ccname)) +- return ENOMEM; +- +- old_umask = umask(0177); +- tmpfd = mkstemp(ccname + strlen("FILE:")); +- oerrno = errno; +- umask(old_umask); +- if (tmpfd == -1) { +- logit("mkstemp(): %.100s", strerror(oerrno)); +- return oerrno; +#if !defined(HEIMDAL) +int +ssh_asprintf_append(char **dsc, const char *fmt, ...) { @@ -197,8 +213,9 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c + /* unknown token, fallback to the default */ + goto cleanup; + } -+ } -+ + } + +- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { + if (ssh_asprintf_append(&r, "%s", p_o) == -1) + goto cleanup; + @@ -233,29 +250,13 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c + return ret; +} + - krb5_error_code --ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { -- int tmpfd, ret, oerrno; -- char ccname[40]; ++krb5_error_code +ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environment) { + int tmpfd, ret, oerrno, type_len; + char *ccname = NULL; - mode_t old_umask; ++ mode_t old_umask; + char *type = NULL, *colon = NULL; - -- ret = snprintf(ccname, sizeof(ccname), -- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); -- if (ret < 0 || (size_t)ret >= sizeof(ccname)) -- return ENOMEM; -- -- old_umask = umask(0177); -- tmpfd = mkstemp(ccname + strlen("FILE:")); -- oerrno = errno; -- umask(old_umask); -- if (tmpfd == -1) { -- logit("mkstemp(): %.100s", strerror(oerrno)); -- return oerrno; -- } ++ + debug3_f("called"); + if (need_environment) + *need_environment = 0; @@ -270,8 +271,7 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c + "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); + if (ret < 0) + return ENOMEM; - -- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { ++ + old_umask = umask(0177); + tmpfd = mkstemp(ccname + strlen("FILE:")); oerrno = errno; @@ -338,42 +338,32 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c } #endif /* !HEIMDAL */ #endif /* KRB5 */ -diff -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c ---- openssh-8.6p1/gss-serv.c.ccache_name 2021-04-19 14:05:10.844744503 +0200 -+++ openssh-8.6p1/gss-serv.c 2021-04-19 14:05:10.854744577 +0200 -@@ -413,13 +413,15 @@ ssh_gssapi_cleanup_creds(void) - } +diff --git a/auth.h b/auth.h +index 83d07ae8..10e88e11 100644 +--- a/auth.h ++++ b/auth.h +@@ -85,6 +85,7 @@ struct Authctxt { + krb5_principal krb5_user; + char *krb5_ticket_file; + char *krb5_ccname; ++ int krb5_set_env; + #endif + struct sshbuf *loginmsg; - /* As user */ --void -+int - ssh_gssapi_storecreds(void) - { - if (gssapi_client.mech && gssapi_client.mech->storecreds) { -- (*gssapi_client.mech->storecreds)(&gssapi_client); -+ return (*gssapi_client.mech->storecreds)(&gssapi_client); - } else - debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); -+ -+ return 0; - } +@@ -245,7 +246,7 @@ FILE *auth_openprincipals(const char *, struct passwd *, int); + int sys_auth_passwd(struct ssh *, const char *); - /* This allows GSSAPI methods to do things to the child's environment based -@@ -499,9 +501,7 @@ ssh_gssapi_rekey_creds(void) { - char *envstr; + #if defined(KRB5) && !defined(HEIMDAL) +-krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *); ++krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *); #endif -- if (gssapi_client.store.filename == NULL && -- gssapi_client.store.envval == NULL && -- gssapi_client.store.envvar == NULL) -+ if (gssapi_client.store.envval == NULL) - return; - - ok = mm_ssh_gssapi_update_creds(&gssapi_client.store); -diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c ---- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-04-19 14:05:10.852744562 +0200 -+++ openssh-8.6p1/gss-serv-krb5.c 2021-04-19 14:05:10.854744577 +0200 -@@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri + #endif /* AUTH_H */ +diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c +index 14502c5a..df55512d 100644 +--- a/gss-serv-krb5.c ++++ b/gss-serv-krb5.c +@@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ @@ -382,7 +372,7 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) { krb5_ccache ccache; -@@ -276,14 +276,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl +@@ -276,14 +276,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) OM_uint32 maj_status, min_status; const char *new_ccname, *new_cctype; const char *errmsg; @@ -400,7 +390,7 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c #ifdef HEIMDAL # ifdef HAVE_KRB5_CC_NEW_UNIQUE -@@ -297,14 +298,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl +@@ -297,14 +298,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) krb5_get_err_text(krb_context, problem)); # endif krb5_free_error_message(krb_context, errmsg); @@ -419,7 +409,7 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c } #endif /* #ifdef HEIMDAL */ -@@ -313,7 +314,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl +@@ -313,7 +314,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) errmsg = krb5_get_error_message(krb_context, problem); logit("krb5_parse_name(): %.100s", errmsg); krb5_free_error_message(krb_context, errmsg); @@ -428,7 +418,7 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c } if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { -@@ -322,7 +323,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl +@@ -322,7 +323,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) krb5_free_error_message(krb_context, errmsg); krb5_free_principal(krb_context, princ); krb5_cc_destroy(krb_context, ccache); @@ -437,7 +427,7 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c } krb5_free_principal(krb_context, princ); -@@ -331,32 +332,21 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl +@@ -331,32 +332,21 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) client->creds, ccache))) { logit("gss_krb5_copy_ccache() failed"); krb5_cc_destroy(krb_context, ccache); @@ -475,7 +465,7 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c do_pam_putenv(client->store.envvar, client->store.envval); #endif -@@ -364,7 +354,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl +@@ -364,7 +354,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) client->store.data = krb_context; @@ -484,10 +474,44 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c } int -diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c ---- openssh-8.6p1/servconf.c.ccache_name 2021-04-19 14:05:10.848744532 +0200 -+++ openssh-8.6p1/servconf.c 2021-04-19 14:05:10.854744577 +0200 -@@ -136,6 +136,7 @@ initialize_server_options(ServerOptions +diff --git a/gss-serv.c b/gss-serv.c +index a5cca797..9d5435ed 100644 +--- a/gss-serv.c ++++ b/gss-serv.c +@@ -414,13 +414,15 @@ ssh_gssapi_cleanup_creds(void) + } + + /* As user */ +-void ++int + ssh_gssapi_storecreds(void) + { + if (gssapi_client.mech && gssapi_client.mech->storecreds) { +- (*gssapi_client.mech->storecreds)(&gssapi_client); ++ return (*gssapi_client.mech->storecreds)(&gssapi_client); + } else + debug("ssh_gssapi_storecreds: Not a GSSAPI mechanism"); ++ ++ return 0; + } + + /* This allows GSSAPI methods to do things to the child's environment based +@@ -500,9 +502,7 @@ ssh_gssapi_rekey_creds(void) { + char *envstr; + #endif + +- if (gssapi_client.store.filename == NULL && +- gssapi_client.store.envval == NULL && +- gssapi_client.store.envvar == NULL) ++ if (gssapi_client.store.envval == NULL) + return; + + ok = mm_ssh_gssapi_update_creds(&gssapi_client.store); +diff --git a/servconf.c b/servconf.c +index d4f7fd66..55aa5bf0 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -138,6 +138,7 @@ initialize_server_options(ServerOptions *options) options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; @@ -495,7 +519,7 @@ diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c options->gss_authentication=-1; options->gss_keyex = -1; options->gss_cleanup_creds = -1; -@@ -359,6 +360,8 @@ fill_default_server_options(ServerOption +@@ -382,6 +383,8 @@ fill_default_server_options(ServerOptions *options) options->kerberos_ticket_cleanup = 1; if (options->kerberos_get_afs_token == -1) options->kerberos_get_afs_token = 0; @@ -504,16 +528,16 @@ 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,7 @@ typedef enum { - sPort, sHostKeyFile, sLoginGraceTime, - sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, +@@ -564,7 +567,7 @@ typedef enum { + sPort, sHostKeyFile, sLoginGraceTime, + sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, - sKerberosGetAFSToken, sPasswordAuthentication, + sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication, - sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, -@@ -593,11 +597,13 @@ static struct { + sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, +@@ -655,11 +658,13 @@ static struct { #else { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif @@ -527,7 +551,7 @@ diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, -@@ -1573,6 +1579,10 @@ process_server_config_line_depth(ServerO +@@ -1668,6 +1673,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->kerberos_get_afs_token; goto parse_flag; @@ -538,7 +562,7 @@ diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c case sGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; -@@ -2891,6 +2901,7 @@ dump_config(ServerOptions *o) +@@ -3293,6 +3302,7 @@ dump_config(ServerOptions *o) # ifdef USE_AFS dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif @@ -546,10 +570,11 @@ diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c #endif #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); -diff -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h ---- openssh-8.6p1/servconf.h.ccache_name 2021-04-19 14:05:10.848744532 +0200 -+++ openssh-8.6p1/servconf.h 2021-04-19 14:05:10.855744584 +0200 -@@ -140,6 +140,8 @@ typedef struct { +diff --git a/servconf.h b/servconf.h +index c3f50140..a4a38d6d 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -149,6 +149,8 @@ typedef struct { * file on logout. */ int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ @@ -558,10 +583,11 @@ diff -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h int gss_authentication; /* If true, permit GSSAPI authentication */ int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ -diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c ---- openssh-8.6p1/session.c.ccache_name 2021-04-19 14:05:10.852744562 +0200 -+++ openssh-8.6p1/session.c 2021-04-19 14:05:10.855744584 +0200 -@@ -1038,7 +1038,8 @@ do_setup_env(struct ssh *ssh, Session *s +diff --git a/session.c b/session.c +index 89b3a9cf..2620dd11 100644 +--- a/session.c ++++ b/session.c +@@ -1025,7 +1025,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) /* Allow any GSSAPI methods that we've used to alter * the child's environment as they see fit */ @@ -571,7 +597,7 @@ diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c #endif /* Set basic environment. */ -@@ -1114,7 +1115,7 @@ do_setup_env(struct ssh *ssh, Session *s +@@ -1101,7 +1102,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) } #endif #ifdef KRB5 @@ -580,10 +606,33 @@ diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c child_set_env(&env, &envsize, "KRB5CCNAME", s->authctxt->krb5_ccname); #endif -diff -up openssh-8.6p1/sshd-session.c.ccache_name openssh-8.6p1/sshd-session.c ---- openssh-8.6p1/sshd-session.c.ccache_name 2021-04-19 14:05:10.849744540 +0200 -+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:05:10.855744584 +0200 -@@ -2284,7 +2284,7 @@ main(int ac, char **av) +diff --git a/ssh-gss.h b/ssh-gss.h +index db34d77f..a894e23c 100644 +--- a/ssh-gss.h ++++ b/ssh-gss.h +@@ -116,7 +116,7 @@ typedef struct ssh_gssapi_mech_struct { + int (*dochild) (ssh_gssapi_client *); + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); +- void (*storecreds) (ssh_gssapi_client *); ++ int (*storecreds) (ssh_gssapi_client *); + int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + +@@ -186,7 +186,7 @@ int ssh_gssapi_userok(char *name, struct passwd *, int kex); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); +-void ssh_gssapi_storecreds(void); ++int ssh_gssapi_storecreds(void); + const char *ssh_gssapi_displayname(void); + + char *ssh_gssapi_server_mechanisms(void); +diff --git a/sshd-session.c b/sshd-session.c +index f8c8a797..478381db 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -1349,7 +1349,7 @@ main(int ac, char **av) #ifdef GSSAPI if (options.gss_authentication) { temporarily_use_uid(authctxt->pw); @@ -592,10 +641,11 @@ diff -up openssh-8.6p1/sshd-session.c.ccache_name openssh-8.6p1/sshd-session.c restore_uid(); } #endif -diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5 ---- openssh-8.6p1/sshd_config.5.ccache_name 2021-04-19 14:05:10.849744540 +0200 -+++ openssh-8.6p1/sshd_config.5 2021-04-19 14:05:10.856744592 +0200 -@@ -939,6 +939,14 @@ Specifies whether to automatically destr +diff --git a/sshd_config.5 b/sshd_config.5 +index 8bc6586e..1251d4d5 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -1033,6 +1033,14 @@ Specifies whether to automatically destroy the user's ticket cache file on logout. The default is .Cm yes . @@ -610,24 +660,6 @@ diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5 .It Cm KexAlgorithms Specifies the permitted KEX (Key Exchange) algorithms that the server will offer to clients. -diff -up openssh-8.6p1/ssh-gss.h.ccache_name openssh-8.6p1/ssh-gss.h ---- openssh-8.6p1/ssh-gss.h.ccache_name 2021-04-19 14:05:10.852744562 +0200 -+++ openssh-8.6p1/ssh-gss.h 2021-04-19 14:05:10.855744584 +0200 -@@ -114,7 +114,7 @@ typedef struct ssh_gssapi_mech_struct { - int (*dochild) (ssh_gssapi_client *); - int (*userok) (ssh_gssapi_client *, char *); - int (*localname) (ssh_gssapi_client *, char **); -- void (*storecreds) (ssh_gssapi_client *); -+ int (*storecreds) (ssh_gssapi_client *); - int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - -@@ -175,7 +175,7 @@ int ssh_gssapi_userok(char *name, struct - OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_do_child(char ***, u_int *); - void ssh_gssapi_cleanup_creds(void); --void ssh_gssapi_storecreds(void); -+int ssh_gssapi_storecreds(void); - const char *ssh_gssapi_displayname(void); - - char *ssh_gssapi_server_mechanisms(void); +-- +2.49.0 + diff --git a/openssh-7.2p2-k5login_directory.patch b/0015-openssh-7.2p2-k5login_directory.patch similarity index 74% rename from openssh-7.2p2-k5login_directory.patch rename to 0015-openssh-7.2p2-k5login_directory.patch index 80e7678..5e980c8 100644 --- a/openssh-7.2p2-k5login_directory.patch +++ b/0015-openssh-7.2p2-k5login_directory.patch @@ -1,8 +1,20 @@ +From 25540939422660b024b8832f67eab82267aa8df6 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 15/50] openssh-7.2p2-k5login_directory + +--- + auth-krb5.c | 16 ++++++++++++++++ + auth.h | 2 ++ + gss-serv-krb5.c | 21 ++++++++++++++++++++- + sshd.8 | 4 ++++ + 4 files changed, 42 insertions(+), 1 deletion(-) + diff --git a/auth-krb5.c b/auth-krb5.c -index 2b02a04..19b9364 100644 +index 77714e3d..74f56d47 100644 --- a/auth-krb5.c +++ b/auth-krb5.c -@@ -375,5 +375,21 @@ cleanup: +@@ -465,5 +465,21 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm return (krb5_cc_resolve(ctx, ccname, ccache)); } } @@ -25,10 +37,10 @@ index 2b02a04..19b9364 100644 #endif /* !HEIMDAL */ #endif /* KRB5 */ diff --git a/auth.h b/auth.h -index f9d191c..c432d2f 100644 +index 10e88e11..39163035 100644 --- a/auth.h +++ b/auth.h -@@ -222,6 +222,8 @@ int sys_auth_passwd(Authctxt *, const char *); +@@ -247,6 +247,8 @@ int sys_auth_passwd(struct ssh *, const char *); #if defined(KRB5) && !defined(HEIMDAL) krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *); @@ -38,10 +50,10 @@ index f9d191c..c432d2f 100644 #endif /* AUTH_H */ diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index a7c0c5f..df8cc9a 100644 +index df55512d..820f794c 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c -@@ -244,8 +244,27 @@ ssh_gssapi_k5login_exists() +@@ -144,8 +144,27 @@ ssh_gssapi_k5login_exists() { char file[MAXPATHLEN]; struct passwd *pw = the_authctxt->pw; @@ -71,10 +83,10 @@ index a7c0c5f..df8cc9a 100644 } diff --git a/sshd.8 b/sshd.8 -index 5c4f15b..135e290 100644 +index 049d0a94..6784286d 100644 --- a/sshd.8 +++ b/sshd.8 -@@ -806,6 +806,10 @@ rlogin/rsh. +@@ -880,6 +880,10 @@ rlogin/rsh. These files enforce GSSAPI/Kerberos authentication access control. Further details are described in .Xr ksu 1 . @@ -85,3 +97,6 @@ index 5c4f15b..135e290 100644 .Pp .It Pa ~/.ssh/ This directory is the default location for all user-specific configuration +-- +2.49.0 + diff --git a/openssh-6.6p1-kuserok.patch b/0016-openssh-6.6p1-kuserok.patch similarity index 80% rename from openssh-6.6p1-kuserok.patch rename to 0016-openssh-6.6p1-kuserok.patch index e43128b..3724b8d 100644 --- a/openssh-6.6p1-kuserok.patch +++ b/0016-openssh-6.6p1-kuserok.patch @@ -1,7 +1,22 @@ -diff -up openssh-7.4p1/auth-krb5.c.kuserok openssh-7.4p1/auth-krb5.c ---- openssh-7.4p1/auth-krb5.c.kuserok 2016-12-23 14:36:07.640465939 +0100 -+++ openssh-7.4p1/auth-krb5.c 2016-12-23 14:36:07.644465936 +0100 -@@ -56,6 +56,21 @@ +From bac7a9d1a654c8c2e0c71f979195e300b25d6232 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 16/50] openssh-6.6p1-kuserok + +--- + auth-krb5.c | 20 ++++++++- + gss-serv-krb5.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++-- + servconf.c | 13 +++++- + servconf.h | 1 + + sshd_config | 1 + + sshd_config.5 | 5 +++ + 6 files changed, 139 insertions(+), 7 deletions(-) + +diff --git a/auth-krb5.c b/auth-krb5.c +index 74f56d47..bae153c9 100644 +--- a/auth-krb5.c ++++ b/auth-krb5.c +@@ -55,6 +55,21 @@ extern ServerOptions options; @@ -23,7 +38,7 @@ diff -up openssh-7.4p1/auth-krb5.c.kuserok openssh-7.4p1/auth-krb5.c static int krb5_init(void *context) { -@@ -160,8 +175,9 @@ auth_krb5_password(Authctxt *authctxt, c +@@ -158,8 +173,9 @@ auth_krb5_password(Authctxt *authctxt, const char *password) if (problem) goto out; @@ -35,10 +50,11 @@ diff -up openssh-7.4p1/auth-krb5.c.kuserok openssh-7.4p1/auth-krb5.c problem = -1; goto out; } -diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c ---- openssh-7.4p1/gss-serv-krb5.c.kuserok 2016-12-23 14:36:07.640465939 +0100 -+++ openssh-7.4p1/gss-serv-krb5.c 2016-12-23 14:36:07.644465936 +0100 -@@ -67,6 +67,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_pr +diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c +index 820f794c..187faf92 100644 +--- a/gss-serv-krb5.c ++++ b/gss-serv-krb5.c +@@ -66,6 +66,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_principal, const char *, const char *, int); static krb5_context krb_context = NULL; @@ -46,7 +62,7 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c /* Initialise the krb5 library, for the stuff that GSSAPI won't do */ -@@ -92,6 +93,103 @@ ssh_gssapi_krb5_init(void) +@@ -91,6 +92,103 @@ ssh_gssapi_krb5_init(void) * Returns true if the user is OK to log in, otherwise returns 0 */ @@ -150,7 +166,7 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c static int ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) { -@@ -116,7 +214,8 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client +@@ -115,7 +213,8 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) /* NOTE: .k5login and .k5users must opened as root, not the user, * because if they are on a krb5-protected filesystem, user credentials * to access these files aren't available yet. */ @@ -160,7 +176,7 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c retval = 1; logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", name, (char *)client->displayname.value); -@@ -190,9 +289,8 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri +@@ -190,9 +289,8 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir); /* If both .k5login and .k5users DNE, self-login is ok. */ if (!k5login_exists && (access(file, F_OK) == -1)) { @@ -172,18 +188,19 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c } if ((fp = fopen(file, "r")) == NULL) { int saved_errno = errno; -diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c ---- openssh-7.4p1/servconf.c.kuserok 2016-12-23 14:36:07.630465944 +0100 -+++ openssh-7.4p1/servconf.c 2016-12-23 15:11:52.278133344 +0100 -@@ -116,6 +116,7 @@ initialize_server_options(ServerOptions +diff --git a/servconf.c b/servconf.c +index 55aa5bf0..5dd5ca21 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -145,6 +145,7 @@ initialize_server_options(ServerOptions *options) options->gss_strict_acceptor = -1; options->gss_store_rekey = -1; options->gss_kex_algorithms = NULL; + options->use_kuserok = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; - options->permit_empty_passwd = -1; -@@ -278,6 +279,8 @@ fill_default_server_options(ServerOption + options->permit_empty_passwd = -1; +@@ -399,6 +400,8 @@ fill_default_server_options(ServerOptions *options) if (options->gss_kex_algorithms == NULL) options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX); #endif @@ -192,16 +209,16 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -399,7 +402,7 @@ typedef enum { - sPort, sHostKeyFile, sLoginGraceTime, - sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, - sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, +@@ -567,7 +570,7 @@ typedef enum { + sPort, sHostKeyFile, sLoginGraceTime, + sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, + sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, - sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication, + sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication, - sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, - sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, -@@ -478,12 +481,14 @@ static struct { + sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, + sPrintMotd, sPrintLastLog, sIgnoreRhosts, + sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, +@@ -659,12 +662,14 @@ static struct { { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif { "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL }, @@ -216,18 +233,18 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, -@@ -1644,6 +1649,10 @@ process_server_config_line(ServerOptions - } - break; - +@@ -2441,6 +2446,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, + } + break; + + case sKerberosUseKuserok: + intptr = &options->use_kuserok; + goto parse_flag; + - case sMatch: - if (cmdline) - fatal("Match directive not supported as a command-line " -@@ -2016,6 +2025,7 @@ copy_set_server_options(ServerOptions *d + case sMatch: + if (cmdline) + fatal("Match directive not supported as a command-line " +@@ -2995,6 +3004,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(client_alive_interval); M_CP_INTOPT(ip_qos_interactive); M_CP_INTOPT(ip_qos_bulk); @@ -235,18 +252,19 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c M_CP_INTOPT(rekey_limit); M_CP_INTOPT(rekey_interval); M_CP_INTOPT(log_level); -@@ -2309,6 +2319,7 @@ dump_config(ServerOptions *o) +@@ -3303,6 +3313,7 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache); + dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); #endif #ifdef GSSAPI - dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); -diff -up openssh-7.4p1/servconf.h.kuserok openssh-7.4p1/servconf.h ---- openssh-7.4p1/servconf.h.kuserok 2016-12-23 14:36:07.630465944 +0100 -+++ openssh-7.4p1/servconf.h 2016-12-23 14:36:07.645465936 +0100 -@@ -118,6 +118,7 @@ typedef struct { + dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); +diff --git a/servconf.h b/servconf.h +index a4a38d6d..11de36a2 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -151,6 +151,7 @@ typedef struct { * authenticated with Kerberos. */ int kerberos_unique_ccache; /* If true, the acquired ticket will * be stored in per-session ccache */ @@ -254,10 +272,23 @@ diff -up openssh-7.4p1/servconf.h.kuserok openssh-7.4p1/servconf.h int gss_authentication; /* If true, permit GSSAPI authentication */ int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ -diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5 ---- openssh-7.4p1/sshd_config.5.kuserok 2016-12-23 14:36:07.637465940 +0100 -+++ openssh-7.4p1/sshd_config.5 2016-12-23 15:14:03.117162222 +0100 -@@ -850,6 +850,10 @@ Specifies whether to automatically destr +diff --git a/sshd_config b/sshd_config +index 8db9f0fb..ea5a878e 100644 +--- a/sshd_config ++++ b/sshd_config +@@ -75,6 +75,7 @@ AuthorizedKeysFile .ssh/authorized_keys + #KerberosOrLocalPasswd yes + #KerberosTicketCleanup yes + #KerberosGetAFSToken no ++#KerberosUseKuserok yes + + # GSSAPI options + #GSSAPIAuthentication no +diff --git a/sshd_config.5 b/sshd_config.5 +index 1251d4d5..0fcb409a 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -1041,6 +1041,10 @@ The default value .Cm no can lead to overwriting previous tickets by subseqent connections to the same user account. @@ -268,7 +299,7 @@ diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5 .It Cm KexAlgorithms Specifies the permitted KEX (Key Exchange) algorithms that the server will offer to clients. -@@ -1078,6 +1082,7 @@ Available keywords are +@@ -1355,6 +1359,7 @@ Available keywords are .Cm IPQoS , .Cm KbdInteractiveAuthentication , .Cm KerberosAuthentication , @@ -276,14 +307,6 @@ diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5 .Cm LogLevel , .Cm MaxAuthTries , .Cm MaxSessions , -diff -up openssh-7.4p1/sshd_config.kuserok openssh-7.4p1/sshd_config ---- openssh-7.4p1/sshd_config.kuserok 2016-12-23 14:36:07.631465943 +0100 -+++ openssh-7.4p1/sshd_config 2016-12-23 14:36:07.646465935 +0100 -@@ -73,6 +73,7 @@ ChallengeResponseAuthentication no - #KerberosOrLocalPasswd yes - #KerberosTicketCleanup yes - #KerberosGetAFSToken no -+#KerberosUseKuserok yes - - # GSSAPI options - #GSSAPIAuthentication no +-- +2.49.0 + diff --git a/0017-openssh-6.4p1-fromto-remote.patch b/0017-openssh-6.4p1-fromto-remote.patch new file mode 100644 index 0000000..5e8309d --- /dev/null +++ b/0017-openssh-6.4p1-fromto-remote.patch @@ -0,0 +1,28 @@ +From 20aabb2c445e29d211266ce7434bb0273edf88b9 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 17/50] openssh-6.4p1-fromto-remote + +--- + scp.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/scp.c b/scp.c +index 57c242ff..716ae386 100644 +--- a/scp.c ++++ b/scp.c +@@ -1162,7 +1162,10 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) + addargs(&alist, "%s", ssh_program); + addargs(&alist, "-x"); + addargs(&alist, "-oClearAllForwardings=yes"); +- addargs(&alist, "-n"); ++ if (isatty(fileno(stdin))) ++ addargs(&alist, "-t"); ++ else ++ addargs(&alist, "-n"); + for (j = 0; j < remote_remote_args.num; j++) { + addargs(&alist, "%s", + remote_remote_args.list[j]); +-- +2.49.0 + diff --git a/openssh-6.6.1p1-selinux-contexts.patch b/0018-openssh-6.6.1p1-selinux-contexts.patch similarity index 73% rename from openssh-6.6.1p1-selinux-contexts.patch rename to 0018-openssh-6.6.1p1-selinux-contexts.patch index 96161cb..49f2119 100644 --- a/openssh-6.6.1p1-selinux-contexts.patch +++ b/0018-openssh-6.6.1p1-selinux-contexts.patch @@ -1,8 +1,20 @@ +From 6481ac7fbd0027a7038560e0f51dd0af056cc229 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 18/50] openssh-6.6.1p1-selinux-contexts + +--- + openbsd-compat/port-linux-sshd.c | 69 +++++++++++++++++++++++++++++++- + openbsd-compat/port-linux.c | 2 +- + openbsd-compat/port-linux.h | 1 + + sshd-auth.c | 2 +- + 4 files changed, 71 insertions(+), 3 deletions(-) + diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c -index 8f32464..18a2ca4 100644 +index 8c5fc1fe..646f0887 100644 --- a/openbsd-compat/port-linux-sshd.c +++ b/openbsd-compat/port-linux-sshd.c -@@ -32,6 +32,7 @@ +@@ -33,6 +33,7 @@ #include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ #include "servconf.h" #include "port-linux.h" @@ -10,7 +22,7 @@ index 8f32464..18a2ca4 100644 #include "sshkey.h" #include "hostfile.h" #include "auth.h" -@@ -445,7 +446,7 @@ sshd_selinux_setup_exec_context(char *pwname) +@@ -450,7 +451,7 @@ sshd_selinux_setup_exec_context(char *pwname) void sshd_selinux_copy_context(void) { @@ -19,7 +31,7 @@ index 8f32464..18a2ca4 100644 if (!sshd_selinux_enabled()) return; -@@ -461,6 +462,72 @@ sshd_selinux_copy_context(void) +@@ -469,6 +470,72 @@ sshd_selinux_copy_context(void) } } @@ -93,22 +105,23 @@ index 8f32464..18a2ca4 100644 #endif diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c ---- a/openbsd-compat/port-linux.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/openbsd-compat/port-linux.c (date 1703108053912) -@@ -207,7 +207,7 @@ +index 7426f6f7..9a6b1d6e 100644 +--- a/openbsd-compat/port-linux.c ++++ b/openbsd-compat/port-linux.c +@@ -188,7 +188,7 @@ ssh_selinux_change_context(const char *newname) xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx, newname, cx2 == NULL ? "" : cx2); - + - debug3_f("setting context from '%s' to '%s'", oldctx, newctx); + debug_f("setting context from '%s' to '%s'", oldctx, newctx); if (setcon(newctx) < 0) do_log2_f(log_level, "setcon %s from %s failed with %s", newctx, oldctx, strerror(errno)); diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h -index cb51f99..8b7cda2 100644 +index 1b745a76..7f8ba200 100644 --- a/openbsd-compat/port-linux.h +++ b/openbsd-compat/port-linux.h -@@ -29,6 +29,7 @@ int sshd_selinux_enabled(void); +@@ -27,6 +27,7 @@ int sshd_selinux_enabled(void); void sshd_selinux_copy_context(void); void sshd_selinux_setup_exec_context(char *); int sshd_selinux_setup_env_variables(void); @@ -116,16 +129,19 @@ index cb51f99..8b7cda2 100644 #endif #ifdef LINUX_OOM_ADJUST -diff --git a/sshd-session.c b/sshd-session.c -index 2871fe9..39b9c08 100644 ---- a/sshd-session.c -+++ b/sshd-session.c -@@ -629,7 +629,7 @@ privsep_preauth_child(void) - demote_sensitive_data(); - +diff --git a/sshd-auth.c b/sshd-auth.c +index d51e4636..e4a8edfd 100644 +--- a/sshd-auth.c ++++ b/sshd-auth.c +@@ -188,7 +188,7 @@ privsep_child_demote(void) + fatal_f("ssh_sandbox_init failed"); + #endif #ifdef WITH_SELINUX - ssh_selinux_change_context("sshd_net_t"); + sshd_selinux_change_privsep_preauth_context(); #endif /* Demote the child */ +-- +2.49.0 + diff --git a/openssh-6.6.1p1-log-in-chroot.patch b/0019-openssh-6.6.1p1-log-in-chroot.patch similarity index 54% rename from openssh-6.6.1p1-log-in-chroot.patch rename to 0019-openssh-6.6.1p1-log-in-chroot.patch index 0f65279..3b30f98 100644 --- a/openssh-6.6.1p1-log-in-chroot.patch +++ b/0019-openssh-6.6.1p1-log-in-chroot.patch @@ -1,7 +1,25 @@ -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 -@@ -194,6 +194,11 @@ void +From 825018f5f2d892655f3d63167a0d1f3391cec678 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 19/50] openssh-6.6.1p1-log-in-chroot + +--- + log.c | 11 +++++++++-- + log.h | 1 + + monitor.c | 17 +++++++++++++++-- + monitor.h | 2 +- + session.c | 26 +++++++++++++++----------- + sftp-server-main.c | 2 +- + sftp-server.c | 6 +++--- + sftp.h | 2 +- + sshd-session.c | 7 ++++++- + 9 files changed, 52 insertions(+), 22 deletions(-) + +diff --git a/log.c b/log.c +index 6617f267..9782cfb0 100644 +--- a/log.c ++++ b/log.c +@@ -196,6 +196,11 @@ void log_init(const char *av0, LogLevel level, SyslogFacility facility, int on_stderr) { @@ -13,7 +31,7 @@ diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c #if defined(HAVE_OPENLOG_R) && defined(SYSLOG_DATA_INIT) struct syslog_data sdata = SYSLOG_DATA_INIT; #endif -@@ -206,8 +211,10 @@ log_init(const char *av0, LogLevel level +@@ -208,8 +213,10 @@ log_init(const char *av0, LogLevel level, SyslogFacility facility, exit(1); } @@ -26,9 +44,10 @@ diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c log_on_stderr = on_stderr; if (on_stderr) -diff -up openssh-8.6p1/log.h.log-in-chroot openssh-8.6p1/log.h ---- openssh-8.6p1/log.h.log-in-chroot 2021-04-19 14:43:08.544843434 +0200 -+++ openssh-8.6p1/log.h 2021-04-19 14:56:46.931042176 +0200 +diff --git a/log.h b/log.h +index 8e8dfc23..70048a8a 100644 +--- a/log.h ++++ b/log.h @@ -52,6 +52,7 @@ typedef enum { typedef void (log_handler_fn)(LogLevel, int, const char *, void *); @@ -37,43 +56,11 @@ diff -up openssh-8.6p1/log.h.log-in-chroot openssh-8.6p1/log.h LogLevel log_level_get(void); int log_change_level(LogLevel); int log_is_on_stderr(void); -diff -up openssh-8.6p1/monitor.c.log-in-chroot openssh-8.6p1/monitor.c ---- openssh-8.6p1/monitor.c.log-in-chroot 2021-04-19 14:43:08.526843298 +0200 -+++ openssh-8.6p1/monitor.c 2021-04-19 14:55:25.286424043 +0200 -@@ -297,6 +297,8 @@ monitor_child_preauth(struct ssh *ssh, s - close(pmonitor->m_log_sendfd); - pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1; - -+ pmonitor->m_state = "preauth"; -+ - authctxt = (Authctxt *)ssh->authctxt; - memset(authctxt, 0, sizeof(*authctxt)); - ssh->authctxt = authctxt; -@@ -408,6 +410,8 @@ monitor_child_postauth(struct ssh *ssh, - close(pmonitor->m_recvfd); - pmonitor->m_recvfd = -1; - -+ pmonitor->m_state = "postauth"; -+ - monitor_set_child_handler(pmonitor->m_pid); - ssh_signal(SIGHUP, &monitor_child_handler); - ssh_signal(SIGTERM, &monitor_child_handler); -@@ -480,7 +484,7 @@ monitor_read_log(struct monitor *pmonito - /* Log it */ - if (log_level_name(level) == NULL) - fatal_f("invalid log level %u (corrupted message?)", level); -- sshlogdirect(level, forced, "%s [preauth]", msg); -+ sshlogdirect(level, forced, "%s [%s]", msg, pmonitor->m_state); - - sshbuf_free(logmsg); - free(msg); -@@ -1868,13 +1872,28 @@ monitor_init(void) - mon = xcalloc(1, sizeof(*mon)); - monitor_openfds(mon, 1); - -+ mon->m_state = ""; -+ - return mon; +diff --git a/monitor.c b/monitor.c +index 2ef16cc8..43c10a4e 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -2001,9 +2001,22 @@ monitor_init(void) } void @@ -98,14 +85,11 @@ diff -up openssh-8.6p1/monitor.c.log-in-chroot openssh-8.6p1/monitor.c } #ifdef GSSAPI -diff -up openssh-8.6p1/monitor.h.log-in-chroot openssh-8.6p1/monitor.h ---- openssh-8.6p1/monitor.h.log-in-chroot 2021-04-19 14:43:08.527843305 +0200 -+++ openssh-8.6p1/monitor.h 2021-04-19 14:43:08.545843441 +0200 -@@ -80,10 +80,11 @@ struct monitor { - int m_log_sendfd; - struct kex **m_pkex; - pid_t m_pid; -+ char *m_state; +diff --git a/monitor.h b/monitor.h +index dbc7e003..d4d631dd 100644 +--- a/monitor.h ++++ b/monitor.h +@@ -85,7 +85,7 @@ struct monitor { }; struct monitor *monitor_init(void); @@ -114,10 +98,11 @@ diff -up openssh-8.6p1/monitor.h.log-in-chroot openssh-8.6p1/monitor.h struct Authctxt; void monitor_child_preauth(struct ssh *, struct monitor *); -diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c ---- openssh-8.6p1/session.c.log-in-chroot 2021-04-19 14:43:08.534843358 +0200 -+++ openssh-8.6p1/session.c 2021-04-19 14:43:08.545843441 +0200 -@@ -160,6 +160,7 @@ login_cap_t *lc; +diff --git a/session.c b/session.c +index 2620dd11..54da09d5 100644 +--- a/session.c ++++ b/session.c +@@ -169,6 +169,7 @@ login_cap_t *lc; static int is_child = 0; static int in_chroot = 0; @@ -125,7 +110,7 @@ diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c /* File containing userauth info, if ExposeAuthInfo set */ static char *auth_info_file = NULL; -@@ -661,6 +662,7 @@ do_exec(struct ssh *ssh, Session *s, con +@@ -670,6 +671,7 @@ do_exec(struct ssh *ssh, Session *s, const char *command) int ret; const char *forced = NULL, *tty = NULL; char session_type[1024]; @@ -133,7 +118,7 @@ diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c if (options.adm_forced_command) { original_command = command; -@@ -720,6 +722,10 @@ do_exec(struct ssh *ssh, Session *s, con +@@ -729,6 +731,10 @@ do_exec(struct ssh *ssh, Session *s, const char *command) tty += 5; } @@ -144,7 +129,7 @@ diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c verbose("Starting session: %s%s%s for %s from %.200s port %d id %d", session_type, tty == NULL ? "" : " on ", -@@ -1524,14 +1530,6 @@ child_close_fds(struct ssh *ssh) +@@ -1512,14 +1518,6 @@ child_close_fds(struct ssh *ssh) /* Stop directing logs to a high-numbered fd before we close it */ log_redirect_stderr_to(NULL); @@ -159,7 +144,7 @@ diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c } /* -@@ -1665,8 +1663,6 @@ do_child(struct ssh *ssh, Session *s, co +@@ -1652,8 +1650,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) exit(1); } @@ -168,7 +153,7 @@ diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c do_rc_files(ssh, s, shell); /* restore SIGPIPE for child */ -@@ -1691,9 +1687,17 @@ do_child(struct ssh *ssh, Session *s, co +@@ -1678,9 +1674,17 @@ do_child(struct ssh *ssh, Session *s, const char *command) argv[i] = NULL; optind = optreset = 1; __progname = argv[0]; @@ -187,29 +172,31 @@ diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c fflush(NULL); /* Get the last component of the shell name. */ -diff -up openssh-8.6p1/sftp.h.log-in-chroot openssh-8.6p1/sftp.h ---- openssh-8.6p1/sftp.h.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/sftp.h 2021-04-19 14:43:08.545843441 +0200 -@@ -97,5 +97,5 @@ +diff --git a/sftp-server-main.c b/sftp-server-main.c +index 2c70f89b..bbb79f27 100644 +--- a/sftp-server-main.c ++++ b/sftp-server-main.c +@@ -48,5 +48,5 @@ main(int argc, char **argv) + return 1; + } - struct passwd; - --int sftp_server_main(int, char **, struct passwd *); -+int sftp_server_main(int, char **, struct passwd *, int); - void sftp_server_cleanup_exit(int) __attribute__((noreturn)); -diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c ---- openssh-8.6p1/sftp-server.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/sftp-server.c 2021-04-19 14:43:08.545843441 +0200 -@@ -1644,7 +1644,7 @@ sftp_server_usage(void) +- return (sftp_server_main(argc, argv, user_pw)); ++ return (sftp_server_main(argc, argv, user_pw, 0)); + } +diff --git a/sftp-server.c b/sftp-server.c +index a4abb9f7..4985da38 100644 +--- a/sftp-server.c ++++ b/sftp-server.c +@@ -1901,7 +1901,7 @@ sftp_server_usage(void) } int -sftp_server_main(int argc, char **argv, struct passwd *user_pw) +sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handler) { - int i, r, in, out, ch, skipargs = 0, log_stderr = 0; - ssize_t len, olen; -@@ -1657,7 +1657,7 @@ sftp_server_main(int argc, char **argv, + int i, r, in, out, ch, skipargs = 0, log_stderr = 0; + ssize_t len, olen; +@@ -1913,7 +1913,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) extern char *__progname; __progname = ssh_get_progname(argv[0]); @@ -218,7 +205,7 @@ diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c pw = pwcopy(user_pw); -@@ -1730,7 +1730,7 @@ sftp_server_main(int argc, char **argv, +@@ -1986,7 +1986,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) } } @@ -227,20 +214,22 @@ diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c /* * On platforms where we can, avoid making /proc/self/{mem,maps} -diff -up openssh-8.6p1/sftp-server-main.c.log-in-chroot openssh-8.6p1/sftp-server-main.c ---- openssh-8.6p1/sftp-server-main.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/sftp-server-main.c 2021-04-19 14:43:08.545843441 +0200 -@@ -50,5 +50,5 @@ main(int argc, char **argv) - return 1; - } +diff --git a/sftp.h b/sftp.h +index 2bde8bb7..ddf1a396 100644 +--- a/sftp.h ++++ b/sftp.h +@@ -97,5 +97,5 @@ -- return (sftp_server_main(argc, argv, user_pw)); -+ return (sftp_server_main(argc, argv, user_pw, 0)); - } -diff -up openssh-8.6p1/sshd-session.c.log-in-chroot openssh-8.6p1/sshd-session.c ---- openssh-8.6p1/sshd-session.c.log-in-chroot 2021-04-19 14:43:08.543843426 +0200 -+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:43:08.545843441 +0200 -@@ -559,7 +559,7 @@ privsep_postauth(struct ssh *ssh, Authct + struct passwd; + +-int sftp_server_main(int, char **, struct passwd *); ++int sftp_server_main(int, char **, struct passwd *, int); + void sftp_server_cleanup_exit(int) __attribute__((noreturn)); +diff --git a/sshd-session.c b/sshd-session.c +index 478381db..9342e416 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -437,7 +437,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) #endif /* New socket pair */ @@ -249,7 +238,7 @@ diff -up openssh-8.6p1/sshd-session.c.log-in-chroot openssh-8.6p1/sshd-session.c pmonitor->m_pid = fork(); if (pmonitor->m_pid == -1) -@@ -578,6 +578,11 @@ privsep_postauth(struct ssh *ssh, Authct +@@ -456,6 +456,11 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) close(pmonitor->m_sendfd); pmonitor->m_sendfd = -1; @@ -261,3 +250,6 @@ diff -up openssh-8.6p1/sshd-session.c.log-in-chroot openssh-8.6p1/sshd-session.c /* Demote the private keys to public keys. */ demote_sensitive_data(); +-- +2.49.0 + diff --git a/0020-openssh-6.6.1p1-scp-non-existing-directory.patch b/0020-openssh-6.6.1p1-scp-non-existing-directory.patch new file mode 100644 index 0000000..94c43ef --- /dev/null +++ b/0020-openssh-6.6.1p1-scp-non-existing-directory.patch @@ -0,0 +1,27 @@ +From 007ee98fa9100f7241985ac2a7eed71e17d89a9f Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 20/50] openssh-6.6.1p1-scp-non-existing-directory + +--- + scp.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/scp.c b/scp.c +index 716ae386..9554b188 100644 +--- a/scp.c ++++ b/scp.c +@@ -1876,6 +1876,10 @@ sink(int argc, char **argv, const char *src) + free(vect[0]); + continue; + } ++ if (buf[0] == 'C' && ! exists && np[strlen(np)-1] == '/') { ++ errno = ENOTDIR; ++ goto bad; ++ } + omode = mode; + mode |= S_IWUSR; + if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { +-- +2.49.0 + diff --git a/openssh-6.6p1-GSSAPIEnablek5users.patch b/0021-openssh-6.6p1-GSSAPIEnablek5users.patch similarity index 61% rename from openssh-6.6p1-GSSAPIEnablek5users.patch rename to 0021-openssh-6.6p1-GSSAPIEnablek5users.patch index 7fef831..eeff02a 100644 --- a/openssh-6.6p1-GSSAPIEnablek5users.patch +++ b/0021-openssh-6.6p1-GSSAPIEnablek5users.patch @@ -1,7 +1,21 @@ -diff -up openssh-7.4p1/gss-serv-krb5.c.GSSAPIEnablek5users openssh-7.4p1/gss-serv-krb5.c ---- openssh-7.4p1/gss-serv-krb5.c.GSSAPIEnablek5users 2016-12-23 15:18:40.615216100 +0100 -+++ openssh-7.4p1/gss-serv-krb5.c 2016-12-23 15:18:40.628216102 +0100 -@@ -279,7 +279,6 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri +From 9c75c175e3555377328fc5fc9b06e94f129b7cd7 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 21/50] openssh-6.6p1-GSSAPIEnablek5users + +--- + gss-serv-krb5.c | 3 +-- + servconf.c | 13 ++++++++++++- + servconf.h | 1 + + sshd_config | 1 + + sshd_config.5 | 6 ++++++ + 5 files changed, 21 insertions(+), 3 deletions(-) + +diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c +index 187faf92..03188d9b 100644 +--- a/gss-serv-krb5.c ++++ b/gss-serv-krb5.c +@@ -278,7 +278,6 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, FILE *fp; char file[MAXPATHLEN]; char *line = NULL; @@ -9,7 +23,7 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.GSSAPIEnablek5users openssh-7.4p1/gss-ser struct stat st; struct passwd *pw = the_authctxt->pw; int found_principal = 0; -@@ -288,7 +287,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri +@@ -288,7 +287,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, snprintf(file, sizeof(file), "%s/.k5users", pw->pw_dir); /* If both .k5login and .k5users DNE, self-login is ok. */ @@ -18,18 +32,19 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.GSSAPIEnablek5users openssh-7.4p1/gss-ser return ssh_krb5_kuserok(krb_context, principal, luser, k5login_exists); } -diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c ---- openssh-7.4p1/servconf.c.GSSAPIEnablek5users 2016-12-23 15:18:40.615216100 +0100 -+++ openssh-7.4p1/servconf.c 2016-12-23 15:35:36.354401156 +0100 -@@ -168,6 +168,7 @@ initialize_server_options(ServerOptions +diff --git a/servconf.c b/servconf.c +index 5dd5ca21..c0de7110 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -146,6 +146,7 @@ initialize_server_options(ServerOptions *options) options->gss_store_rekey = -1; options->gss_kex_algorithms = NULL; options->use_kuserok = -1; + options->enable_k5users = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; - options->permit_empty_passwd = -1; -@@ -345,6 +346,8 @@ fill_default_server_options(ServerOption + options->permit_empty_passwd = -1; +@@ -402,6 +403,8 @@ fill_default_server_options(ServerOptions *options) #endif if (options->use_kuserok == -1) options->use_kuserok = 1; @@ -38,7 +53,7 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -578,7 +578,7 @@ typedef enum { +@@ -585,7 +588,7 @@ typedef enum { sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, @@ -47,7 +62,7 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, -@@ -600,14 +600,16 @@ static struct { +@@ -681,6 +684,7 @@ static struct { { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, @@ -55,8 +70,7 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, - { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, - { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, +@@ -689,6 +693,7 @@ static struct { { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL }, @@ -64,7 +78,7 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c #endif { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, -@@ -1653,6 +1658,10 @@ process_server_config_line(ServerOptions +@@ -2450,6 +2455,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->use_kuserok; goto parse_flag; @@ -72,10 +86,10 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c + intptr = &options->enable_k5users; + goto parse_flag; + - case sMatch: - if (cmdline) - fatal("Match directive not supported as a command-line " -@@ -2026,6 +2035,7 @@ copy_set_server_options(ServerOptions *d + case sMatch: + if (cmdline) + fatal("Match directive not supported as a command-line " +@@ -3005,6 +3014,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(ip_qos_interactive); M_CP_INTOPT(ip_qos_bulk); M_CP_INTOPT(use_kuserok); @@ -83,7 +97,7 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c M_CP_INTOPT(rekey_limit); M_CP_INTOPT(rekey_interval); M_CP_INTOPT(log_level); -@@ -2320,6 +2330,7 @@ dump_config(ServerOptions *o) +@@ -3314,6 +3324,7 @@ dump_config(ServerOptions *o) # endif dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache); dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); @@ -91,21 +105,35 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c #endif #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); -diff -up openssh-7.4p1/servconf.h.GSSAPIEnablek5users openssh-7.4p1/servconf.h ---- openssh-7.4p1/servconf.h.GSSAPIEnablek5users 2016-12-23 15:18:40.616216100 +0100 -+++ openssh-7.4p1/servconf.h 2016-12-23 15:18:40.629216102 +0100 -@@ -174,6 +174,7 @@ typedef struct { - int kerberos_unique_ccache; /* If true, the acquired ticket will - * be stored in per-session ccache */ +diff --git a/servconf.h b/servconf.h +index 11de36a2..c08cf6a7 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -152,6 +152,7 @@ typedef struct { + int kerberos_unique_ccache; /* If true, the acquired ticket will + * be stored in per-session ccache */ int use_kuserok; + int enable_k5users; int gss_authentication; /* If true, permit GSSAPI authentication */ int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ -diff -up openssh-7.4p1/sshd_config.5.GSSAPIEnablek5users openssh-7.4p1/sshd_config.5 ---- openssh-7.4p1/sshd_config.5.GSSAPIEnablek5users 2016-12-23 15:18:40.630216103 +0100 -+++ openssh-7.4p1/sshd_config.5 2016-12-23 15:36:21.607408435 +0100 -@@ -628,6 +628,12 @@ Specifies whether to automatically destr +diff --git a/sshd_config b/sshd_config +index ea5a878e..33713c88 100644 +--- a/sshd_config ++++ b/sshd_config +@@ -82,6 +82,7 @@ AuthorizedKeysFile .ssh/authorized_keys + #GSSAPICleanupCredentials yes + #GSSAPIStrictAcceptorCheck yes + #GSSAPIKeyExchange no ++#GSSAPIEnablek5users no + + # 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 0fcb409a..fe246fc2 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -739,6 +739,12 @@ Specifies whether to automatically destroy the user's credentials cache on logout. The default is .Cm yes . @@ -118,17 +146,6 @@ diff -up openssh-7.4p1/sshd_config.5.GSSAPIEnablek5users openssh-7.4p1/sshd_conf .It Cm GSSAPIKeyExchange Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange doesn't rely on ssh keys to verify host identity. -diff -up openssh-7.4p1/sshd_config.GSSAPIEnablek5users openssh-7.4p1/sshd_config ---- openssh-7.4p1/sshd_config.GSSAPIEnablek5users 2016-12-23 15:18:40.616216100 +0100 -+++ openssh-7.4p1/sshd_config 2016-12-23 15:18:40.631216103 +0100 -@@ -80,6 +80,7 @@ GSSAPIAuthentication yes - #GSSAPICleanupCredentials yes - #GSSAPIStrictAcceptorCheck yes - #GSSAPIKeyExchange no -+#GSSAPIEnablek5users no - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -diff -up openssh-9.8p1/servconf.c.xxx openssh-9.8p1/servconf.c ---- openssh-9.8p1/servconf.c.xxx 2024-07-11 13:51:19.969960781 +0200 -+++ openssh-9.8p1/servconf.c 2024-07-11 13:51:30.938231250 +0200 +-- +2.49.0 + diff --git a/0022-openssh-6.8p1-sshdT-output.patch b/0022-openssh-6.8p1-sshdT-output.patch new file mode 100644 index 0000000..4e4766e --- /dev/null +++ b/0022-openssh-6.8p1-sshdT-output.patch @@ -0,0 +1,25 @@ +From 05b09904f431333e19cd24528ef66d1fd15e9efe Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 22/50] openssh-6.8p1-sshdT-output + +--- + servconf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/servconf.c b/servconf.c +index c0de7110..105e301d 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -3366,7 +3366,7 @@ dump_config(ServerOptions *o) + dump_cfg_string(sXAuthLocation, o->xauth_location); + dump_cfg_string(sCiphers, o->ciphers); + dump_cfg_string(sMacs, o->macs); +- dump_cfg_string(sBanner, o->banner); ++ dump_cfg_string(sBanner, o->banner != NULL ? o->banner : "none"); + dump_cfg_string(sForceCommand, o->adm_forced_command); + dump_cfg_string(sChrootDirectory, o->chroot_directory); + dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); +-- +2.49.0 + diff --git a/openssh-6.7p1-sftp-force-permission.patch b/0023-openssh-6.7p1-sftp-force-permission.patch similarity index 72% rename from openssh-6.7p1-sftp-force-permission.patch rename to 0023-openssh-6.7p1-sftp-force-permission.patch index 1cfa309..1cdc0df 100644 --- a/openssh-6.7p1-sftp-force-permission.patch +++ b/0023-openssh-6.7p1-sftp-force-permission.patch @@ -1,6 +1,17 @@ -diff -up openssh-7.2p2/sftp-server.8.sftp-force-mode openssh-7.2p2/sftp-server.8 ---- openssh-7.2p2/sftp-server.8.sftp-force-mode 2016-03-09 19:04:48.000000000 +0100 -+++ openssh-7.2p2/sftp-server.8 2016-06-23 16:18:20.463854117 +0200 +From 34b196198018059bed294fa7a08e70606b4cbc36 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 23/50] openssh-6.7p1-sftp-force-permission + +--- + sftp-server.8 | 7 +++++++ + sftp-server.c | 24 ++++++++++++++++++++++-- + 2 files changed, 29 insertions(+), 2 deletions(-) + +diff --git a/sftp-server.8 b/sftp-server.8 +index 5311bf92..5e6e3aa4 100644 +--- a/sftp-server.8 ++++ b/sftp-server.8 @@ -38,6 +38,7 @@ .Op Fl P Ar denied_requests .Op Fl p Ar allowed_requests @@ -22,10 +33,11 @@ diff -up openssh-7.2p2/sftp-server.8.sftp-force-mode openssh-7.2p2/sftp-server.8 .El .Pp On some systems, -diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c ---- openssh-7.2p2/sftp-server.c.sftp-force-mode 2016-06-23 16:18:20.446854128 +0200 -+++ openssh-7.2p2/sftp-server.c 2016-06-23 16:20:37.950766082 +0200 -@@ -69,6 +69,10 @@ struct sshbuf *oqueue; +diff --git a/sftp-server.c b/sftp-server.c +index 4985da38..6ed1c27f 100644 +--- a/sftp-server.c ++++ b/sftp-server.c +@@ -76,6 +76,10 @@ struct sshbuf *oqueue; /* Version of client */ static u_int version; @@ -36,7 +48,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c /* SSH2_FXP_INIT received */ static int init_done; -@@ -683,6 +687,7 @@ process_open(u_int32_t id) +@@ -745,6 +749,7 @@ process_open(u_int32_t id) Attrib a; char *name; int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; @@ -44,7 +56,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ -@@ -692,6 +697,10 @@ process_open(u_int32_t id) +@@ -754,6 +759,10 @@ process_open(u_int32_t id) debug3("request %u: open flags %d", id, pflags); flags = flags_from_portable(pflags); mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; @@ -55,7 +67,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); if (readonly && -@@ -713,6 +722,8 @@ process_open(u_int32_t id) +@@ -775,6 +784,8 @@ process_open(u_int32_t id) } } } @@ -64,7 +76,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c if (status != SSH2_FX_OK) send_status(id, status); free(name); -@@ -1494,7 +1505,7 @@ sftp_server_usage(void) +@@ -1894,7 +1905,7 @@ sftp_server_usage(void) fprintf(stderr, "usage: %s [-ehR] [-d start_directory] [-f log_facility] " "[-l log_level]\n\t[-P denied_requests] " @@ -73,7 +85,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c " %s -Q protocol_feature\n", __progname, __progname); exit(1); -@@ -1520,7 +1531,7 @@ sftp_server_main(int argc, char **argv, +@@ -1918,7 +1929,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle pw = pwcopy(user_pw); while (!skipargs && (ch = getopt(argc, argv, @@ -82,7 +94,7 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c switch (ch) { case 'Q': if (strcasecmp(optarg, "requests") != 0) { -@@ -1580,6 +1591,15 @@ sftp_server_main(int argc, char **argv, +@@ -1980,6 +1991,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle fatal("Invalid umask \"%s\"", optarg); (void)umask((mode_t)mask); break; @@ -98,3 +110,6 @@ diff -up openssh-7.2p2/sftp-server.c.sftp-force-mode openssh-7.2p2/sftp-server.c case 'h': default: sftp_server_usage(); +-- +2.49.0 + diff --git a/openssh-7.2p2-s390-closefrom.patch b/0024-openssh-7.2p2-s390-closefrom.patch similarity index 66% rename from openssh-7.2p2-s390-closefrom.patch rename to 0024-openssh-7.2p2-s390-closefrom.patch index 363538c..0214781 100644 --- a/openssh-7.2p2-s390-closefrom.patch +++ b/0024-openssh-7.2p2-s390-closefrom.patch @@ -1,21 +1,17 @@ -Zseries only: Leave the hardware filedescriptors open. - -All filedescriptors above 2 are getting closed when a new -sshd process to handle a new client connection is -spawned. As the process also chroot into an empty filesystem -without any device nodes, there is no chance to reopen the -files. This patch filters out the reqired fds in the -closefrom function so these are skipped in the close loop. - -Author: Harald Freudenberger +From 9bb31b63142adaaf949e20c2d86c97f9b787217b Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 24/50] openssh-7.2p2-s390-closefrom --- - openbsd-compat/bsd-closefrom.c | 26 ++++++++++++++++++++++++++ + openbsd-compat/bsd-closefrom.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) +diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c +index 49a4f35f..f6112458 100644 --- a/openbsd-compat/bsd-closefrom.c +++ b/openbsd-compat/bsd-closefrom.c -@@ -82,7 +82,33 @@ closefrom(int lowfd) +@@ -140,7 +140,33 @@ closefrom(int lowfd) fd = strtol(dent->d_name, &endp, 10); if (dent->d_name != endp && *endp == '\0' && fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) @@ -49,4 +45,6 @@ Author: Harald Freudenberger } (void) closedir(dirp); return; +-- +2.49.0 diff --git a/openssh-7.3p1-x11-max-displays.patch b/0025-openssh-7.3p1-x11-max-displays.patch similarity index 53% rename from openssh-7.3p1-x11-max-displays.patch rename to 0025-openssh-7.3p1-x11-max-displays.patch index e28c62e..68d679c 100644 --- a/openssh-7.3p1-x11-max-displays.patch +++ b/0025-openssh-7.3p1-x11-max-displays.patch @@ -1,18 +1,22 @@ -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 NUM_SOCKS 10 - - /* -- X11 forwarding */ --/* Maximum number of fake X11 displays to try. */ --#define MAX_DISPLAYS 1000 -+/* Minimum port number for X11 forwarding */ -+#define X11_PORT_MIN 6000 - - /* Per-channel callback for pre/post IO actions */ - typedef void chan_fn(struct ssh *, Channel *c); -@@ -4228,7 +4228,7 @@ channel_send_window_changes(void) +From 36e3430d1f81397d5f40600e075272a81f7effce Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 25/50] openssh-7.3p1-x11-max-displays + +--- + channels.c | 9 ++++++--- + channels.h | 2 +- + servconf.c | 12 +++++++++++- + servconf.h | 2 ++ + session.c | 5 +++-- + sshd_config.5 | 7 +++++++ + 6 files changed, 30 insertions(+), 7 deletions(-) + +diff --git a/channels.c b/channels.c +index d46531ce..7438c1a5 100644 +--- a/channels.c ++++ b/channels.c +@@ -4996,7 +4996,7 @@ rdynamic_connect_finish(struct ssh *ssh, Channel *c) */ int x11_create_display_inet(struct ssh *ssh, int x11_display_offset, @@ -21,8 +25,8 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c u_int *display_numberp, int **chanids) { Channel *nc = NULL; -@@ -4240,10 +4241,15 @@ x11_create_display_inet(int x11_display_ - if (chanids == NULL) +@@ -5009,8 +5009,11 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, + x11_display_offset > UINT16_MAX - X11_BASE_PORT - MAX_DISPLAYS) return -1; + /* Try to bind ports starting at 6000+X11DisplayOffset */ @@ -32,55 +36,22 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c - display_number < MAX_DISPLAYS; + display_number < x11_max_displays; display_number++) { -- port = 6000 + display_number; -+ port = X11_PORT_MIN + display_number; -+ if (port < X11_PORT_MIN) /* overflow */ -+ break; + port = X11_BASE_PORT + display_number; memset(&hints, 0, sizeof(hints)); - hints.ai_family = ssh->chanctxt->IPv4or6; - hints.ai_flags = x11_use_localhost ? 0: AI_PASSIVE; -@@ -4295,7 +4301,7 @@ x11_create_display_inet(int x11_display_ +@@ -5065,7 +5068,7 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, if (num_socks > 0) break; } - if (display_number >= MAX_DISPLAYS) { -+ if (display_number >= x11_max_displays || port < X11_PORT_MIN ) { ++ if (display_number >= x11_max_displays || port < X11_BASE_PORT ) { error("Failed to allocate internet-domain X11 display socket."); return -1; } -@@ -4441,7 +4447,7 @@ x11_connect_display(void) - memset(&hints, 0, sizeof(hints)); - hints.ai_family = ssh->chanctxt->IPv4or6; - hints.ai_socktype = SOCK_STREAM; -- snprintf(strport, sizeof strport, "%u", 6000 + display_number); -+ snprintf(strport, sizeof strport, "%u", X11_PORT_MIN + display_number); - if ((gaierr = getaddrinfo(buf, strport, &hints, &aitop)) != 0) { - error("%.100s: unknown host. (%s)", buf, - ssh_gai_strerror(gaierr)); -@@ -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, -- 6000 + display_number, strerror(errno)); -+ X11_PORT_MIN + display_number, strerror(errno)); - close(sock); - continue; - } -@@ -4466,8 +4472,8 @@ x11_connect_display(void) - } - freeaddrinfo(aitop); - if (!ai) { -- 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 -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 *); +diff --git a/channels.h b/channels.h +index 134528d5..8a09a820 100644 +--- a/channels.h ++++ b/channels.h +@@ -379,7 +379,7 @@ int permitopen_port(const char *); void channel_set_x11_refuse_time(struct ssh *, time_t); int x11_connect_display(struct ssh *); @@ -88,11 +59,12 @@ diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h +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 -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 + int x11_channel_used_recently(struct ssh *ssh); +diff --git a/servconf.c b/servconf.c +index 105e301d..15c99b30 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -117,6 +117,7 @@ initialize_server_options(ServerOptions *options) options->print_lastlog = -1; options->x11_forwarding = -1; options->x11_display_offset = -1; @@ -100,7 +72,7 @@ diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c options->x11_use_localhost = -1; options->permit_tty = -1; options->permit_user_rc = -1; -@@ -243,6 +244,8 @@ fill_default_server_options(ServerOption +@@ -353,6 +354,8 @@ fill_default_server_options(ServerOptions *options) options->x11_forwarding = 0; if (options->x11_display_offset == -1) options->x11_display_offset = 10; @@ -109,16 +81,16 @@ diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c if (options->x11_use_localhost == -1) options->x11_use_localhost = 1; if (options->xauth_location == NULL) -@@ -419,7 +422,7 @@ typedef enum { - sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication, - sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, - sPrintMotd, sPrintLastLog, sIgnoreRhosts, +@@ -576,7 +579,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, -@@ -540,6 +543,7 @@ static struct { +@@ -714,6 +717,7 @@ static struct { { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, @@ -126,7 +98,7 @@ diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, -@@ -1316,6 +1320,10 @@ process_server_config_line(ServerOptions +@@ -1750,6 +1754,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, *intptr = value; break; @@ -137,7 +109,7 @@ diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c case sX11UseLocalhost: intptr = &options->x11_use_localhost; goto parse_flag; -@@ -2063,6 +2071,7 @@ copy_set_server_options(ServerOptions *d +@@ -3004,6 +3012,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); M_CP_INTOPT(x11_display_offset); M_CP_INTOPT(x11_forwarding); @@ -145,7 +117,7 @@ diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c M_CP_INTOPT(x11_use_localhost); M_CP_INTOPT(permit_tty); M_CP_INTOPT(permit_user_rc); -@@ -2315,6 +2324,7 @@ dump_config(ServerOptions *o) +@@ -3299,6 +3308,7 @@ dump_config(ServerOptions *o) #endif dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); @@ -153,10 +125,11 @@ diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c dump_cfg_int(sMaxAuthTries, o->max_authtries); dump_cfg_int(sMaxSessions, o->max_sessions); dump_cfg_int(sClientAliveInterval, o->client_alive_interval); -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 @@ +diff --git a/servconf.h b/servconf.h +index c08cf6a7..7c7e5d43 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -38,6 +38,7 @@ #define DEFAULT_AUTH_FAIL_MAX 6 /* Default for MaxAuthTries */ #define DEFAULT_SESSIONS_MAX 10 /* Default for MaxSessions */ @@ -164,7 +137,7 @@ diff -up openssh-7.4p1/servconf.h.x11max openssh-7.4p1/servconf.h /* Magic name for internal sftp-server */ #define INTERNAL_SFTP_NAME "internal-sftp" -@@ -85,6 +86,7 @@ typedef struct { +@@ -114,6 +115,7 @@ typedef struct { int x11_forwarding; /* If true, permit inet (spoofing) X11 fwd. */ int x11_display_offset; /* What DISPLAY number to start * searching at */ @@ -172,13 +145,14 @@ diff -up openssh-7.4p1/servconf.h.x11max openssh-7.4p1/servconf.h 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 -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) +diff --git a/session.c b/session.c +index 54da09d5..28bbb8a7 100644 +--- a/session.c ++++ b/session.c +@@ -2611,8 +2611,9 @@ session_setup_x11fwd(struct ssh *ssh, 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, @@ -187,10 +161,11 @@ diff -up openssh-7.4p1/session.c.x11max openssh-7.4p1/session.c debug("x11_create_display_inet failed."); return 0; } -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 +diff --git a/sshd_config.5 b/sshd_config.5 +index fe246fc2..26fcdc84 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -1391,6 +1391,7 @@ Available keywords are .Cm TrustedUserCAKeys , .Cm UnusedConnectionTimeout , .Cm X11DisplayOffset , @@ -198,7 +173,7 @@ diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5 .Cm X11Forwarding and .Cm X11UseLocalhost . -@@ -1566,6 +1567,12 @@ Specifies the first display number avail +@@ -2111,6 +2112,12 @@ Specifies the first display number available for X11 forwarding. This prevents sshd from interfering with real X11 servers. The default is 10. @@ -211,3 +186,6 @@ diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5 .It Cm X11Forwarding Specifies whether X11 forwarding is permitted. The argument must be +-- +2.49.0 + diff --git a/openssh-7.6p1-cleanup-selinux.patch b/0026-openssh-7.6p1-cleanup-selinux.patch similarity index 65% rename from openssh-7.6p1-cleanup-selinux.patch rename to 0026-openssh-7.6p1-cleanup-selinux.patch index cfe11ad..c4f2d15 100644 --- a/openssh-7.6p1-cleanup-selinux.patch +++ b/0026-openssh-7.6p1-cleanup-selinux.patch @@ -1,7 +1,25 @@ -diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c ---- openssh/auth2-pubkey.c.refactor 2019-04-04 13:19:12.188821236 +0200 -+++ openssh/auth2-pubkey.c 2019-04-04 13:19:12.276822078 +0200 -@@ -72,6 +72,8 @@ +From 43320351b6f150167190aacc84f2f87030fef3d2 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 26/50] openssh-7.6p1-cleanup-selinux + +--- + auth2-pubkey.c | 8 ++++-- + misc.c | 5 ++-- + misc.h | 2 +- + openbsd-compat/port-linux-sshd.c | 42 +++++++++++++++++--------------- + openbsd-compat/port-linux.h | 4 +-- + platform.c | 6 ++++- + sshconnect.c | 2 +- + sshd-auth.c | 2 +- + sshd-session.c | 6 +++-- + 9 files changed, 45 insertions(+), 32 deletions(-) + +diff --git a/auth2-pubkey.c b/auth2-pubkey.c +index 267a27d2..0d5ae0df 100644 +--- a/auth2-pubkey.c ++++ b/auth2-pubkey.c +@@ -77,6 +77,8 @@ /* import */ extern ServerOptions options; @@ -10,7 +28,7 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c extern struct authmethod_cfg methodcfg_pubkey; static char * -@@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh +@@ -485,7 +487,8 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key, if ((pid = subprocess("AuthorizedPrincipalsCommand", command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, @@ -20,20 +38,21 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c goto out; uid_swapped = 1; -@@ -981,7 +985,8 @@ user_key_command_allowed2(struct ssh *ss +@@ -755,7 +758,8 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key, if ((pid = subprocess("AuthorizedKeysCommand", command, ac, av, &f, - SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, - runas_pw, temporarily_use_uid, restore_uid)) == 0) + runas_pw, temporarily_use_uid, restore_uid, + inetd_flag, the_authctxt)) == 0) goto out; uid_swapped = 1; -diff -up openssh/misc.c.refactor openssh/misc.c ---- openssh/misc.c.refactor 2019-04-04 13:19:12.235821686 +0200 -+++ openssh/misc.c 2019-04-04 13:19:12.276822078 +0200 -@@ -756,7 +756,8 @@ auth_get_canonical_hostname(struct ssh * +diff --git a/misc.c b/misc.c +index 1e31acc9..09722962 100644 +--- a/misc.c ++++ b/misc.c +@@ -2764,7 +2764,8 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) pid_t subprocess(const char *tag, const char *command, int ac, char **av, FILE **child, u_int flags, @@ -43,7 +62,7 @@ diff -up openssh/misc.c.refactor openssh/misc.c { FILE *f = NULL; struct stat st; -@@ -872,7 +873,7 @@ subprocess(const char *tag, struct passw +@@ -2898,7 +2899,7 @@ subprocess(const char *tag, const char *command, _exit(1); } #ifdef WITH_SELINUX @@ -52,10 +71,11 @@ diff -up openssh/misc.c.refactor openssh/misc.c error ("failed to copy environment: %s", strerror(errno)); _exit(127); -diff -up openssh/misc.h.refactor openssh/misc.h ---- openssh/misc.h.refactor 2019-04-04 13:19:12.251821839 +0200 -+++ openssh/misc.h 2019-04-04 13:19:12.276822078 +0200 -@@ -235,7 +235,7 @@ struct passwd *fakepw(void); +diff --git a/misc.h b/misc.h +index efecdf1a..9efa9cf4 100644 +--- a/misc.h ++++ b/misc.h +@@ -122,7 +122,7 @@ typedef void privrestore_fn(void); #define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */ #define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */ pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int, @@ -64,23 +84,10 @@ diff -up openssh/misc.h.refactor openssh/misc.h typedef struct arglist arglist; struct arglist { -diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/port-linux.h ---- openssh/openbsd-compat/port-linux.h.refactor 2019-04-04 13:19:12.256821887 +0200 -+++ openssh/openbsd-compat/port-linux.h 2019-04-04 13:19:12.276822078 +0200 -@@ -26,8 +26,8 @@ void ssh_selinux_setfscreatecon(const ch - - int sshd_selinux_enabled(void); - void sshd_selinux_copy_context(void); --void sshd_selinux_setup_exec_context(char *); --int sshd_selinux_setup_env_variables(void); -+void sshd_selinux_setup_exec_context(char *, int, int(char *, const char *), void *, int); -+int sshd_selinux_setup_env_variables(int inetd, void *); - void sshd_selinux_change_privsep_preauth_context(void); - #endif - -diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c ---- openssh/openbsd-compat/port-linux-sshd.c.refactor 2019-04-04 13:19:12.256821887 +0200 -+++ openssh/openbsd-compat/port-linux-sshd.c 2019-04-04 13:19:12.276822078 +0200 +diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c +index 646f0887..291b569a 100644 +--- a/openbsd-compat/port-linux-sshd.c ++++ b/openbsd-compat/port-linux-sshd.c @@ -49,10 +49,6 @@ #include #endif @@ -92,7 +99,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa /* Wrapper around is_selinux_enabled() to log its return value once only */ int sshd_selinux_enabled(void) -@@ -223,7 +218,8 @@ get_user_context(const char *sename, con +@@ -222,7 +218,8 @@ get_user_context(const char *sename, const char *role, const char *lvl, } static void @@ -102,7 +109,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa { *role = NULL; *level = NULL; -@@ -241,8 +237,8 @@ ssh_selinux_get_role_level(char **role, +@@ -240,8 +237,8 @@ ssh_selinux_get_role_level(char **role, const char **level) /* Return the default security context for the given username */ static int @@ -113,7 +120,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa { char *sename, *lvl; char *role; -@@ -250,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -249,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname, int r = 0; context_t con = NULL; @@ -122,7 +129,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa #ifdef HAVE_GETSEUSERBYNAME if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { -@@ -272,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -271,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname, if (r == 0) { /* If launched from xinetd, we must use current level */ @@ -131,7 +138,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa security_context_t sshdsc=NULL; if (getcon_raw(&sshdsc) < 0) -@@ -333,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -332,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname, /* Setup environment variables for pam_selinux */ static int @@ -141,7 +148,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa { const char *reqlvl; char *role; -@@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it +@@ -341,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) debug3_f("setting execution context"); @@ -155,7 +162,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa use_current = "1"; } else { use_current = ""; -@@ -362,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it +@@ -361,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) } static int @@ -168,7 +175,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa } static int -@@ -374,25 +372,28 @@ do_setenv(char *name, const char *value) +@@ -373,25 +372,28 @@ do_setenv(char *name, const char *value) } int @@ -202,7 +209,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa switch (security_getenforce()) { case -1: fatal_f("security_getenforce() failed"); -@@ -410,7 +411,7 @@ sshd_selinux_setup_exec_context(char *pw +@@ -407,7 +409,7 @@ sshd_selinux_setup_exec_context(char *pwname) debug3_f("setting execution context"); @@ -211,10 +218,26 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa if (r >= 0) { r = setexeccon(user_ctx); if (r < 0) { -diff -up openssh/platform.c.refactor openssh/platform.c ---- openssh/platform.c.refactor 2019-04-04 13:19:12.204821389 +0200 -+++ openssh/platform.c 2019-04-04 13:19:12.277822088 +0200 -@@ -32,6 +32,8 @@ +diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h +index 7f8ba200..3cd7da6a 100644 +--- a/openbsd-compat/port-linux.h ++++ b/openbsd-compat/port-linux.h +@@ -25,8 +25,8 @@ void ssh_selinux_setfscreatecon(const char *); + + int sshd_selinux_enabled(void); + void sshd_selinux_copy_context(void); +-void sshd_selinux_setup_exec_context(char *); +-int sshd_selinux_setup_env_variables(void); ++void sshd_selinux_setup_exec_context(char *, int, int(char *, const char *), void *, int); ++int sshd_selinux_setup_env_variables(int inetd, void *); + void sshd_selinux_change_privsep_preauth_context(void); + #endif + +diff --git a/platform.c b/platform.c +index 0d12f311..f0800b1f 100644 +--- a/platform.c ++++ b/platform.c +@@ -33,6 +33,8 @@ #include "openbsd-compat/openbsd-compat.h" extern ServerOptions options; @@ -223,7 +246,7 @@ diff -up openssh/platform.c.refactor openssh/platform.c /* return 1 if we are running with privilege to swap UIDs, 0 otherwise */ int -@@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru +@@ -140,7 +142,9 @@ platform_setusercontext_post_groups(struct passwd *pw) } #endif /* HAVE_SETPCRED */ #ifdef WITH_SELINUX @@ -234,10 +257,37 @@ diff -up openssh/platform.c.refactor openssh/platform.c #endif } -diff -up openssh/sshd-session.c.refactor openssh/sshd-session.c ---- openssh/sshd-session.c.refactor 2019-04-04 13:19:12.275822068 +0200 -+++ openssh/sshd-session.c 2019-04-04 13:19:51.270195262 +0200 -@@ -158,7 +158,7 @@ int debug_flag = 0; +diff --git a/sshconnect.c b/sshconnect.c +index c86182d1..04084810 100644 +--- a/sshconnect.c ++++ b/sshconnect.c +@@ -925,7 +925,7 @@ load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template, + + if ((pid = subprocess(tag, command, ac, av, &f, + SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| +- SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0) ++ SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL, 0, NULL)) == 0) + goto out; + + load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); +diff --git a/sshd-auth.c b/sshd-auth.c +index e4a8edfd..897db9b4 100644 +--- a/sshd-auth.c ++++ b/sshd-auth.c +@@ -122,7 +122,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; + int debug_flag = 0; + + /* Flag indicating that the daemon is being started from inetd. */ +-static int inetd_flag = 0; ++int inetd_flag = 0; + + /* Saved arguments to main(). */ + static char **saved_argv; +diff --git a/sshd-session.c b/sshd-session.c +index 9342e416..81d30152 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -136,7 +136,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; int debug_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ @@ -246,7 +296,7 @@ diff -up openssh/sshd-session.c.refactor openssh/sshd-session.c /* debug goes to stderr unless inetd_flag is set */ static int log_stderr = 0; -@@ -2192,7 +2192,9 @@ main(int ac, char **av) +@@ -1359,7 +1359,9 @@ main(int ac, char **av) } #endif #ifdef WITH_SELINUX @@ -257,15 +307,6 @@ diff -up openssh/sshd-session.c.refactor openssh/sshd-session.c #endif #ifdef USE_PAM if (options.use_pam) { -diff -up openssh/sshconnect.c.refactor openssh/sshconnect.c ---- openssh/sshconnect.c.refactor 2021-02-24 00:12:03.065325046 +0100 -+++ openssh/sshconnect.c 2021-02-24 00:12:12.126449544 +0100 -@@ -892,7 +892,7 @@ load_hostkeys_command(struct hostkeys *h - - if ((pid = subprocess(tag, command, ac, av, &f, - SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| -- SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL)) == 0) -+ SSH_SUBPROCESS_PRESERVE_ENV, NULL, NULL, NULL, 0, NULL)) == 0) - goto out; - - load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); +-- +2.49.0 + diff --git a/0027-openssh-7.5p1-sandbox.patch b/0027-openssh-7.5p1-sandbox.patch new file mode 100644 index 0000000..435d029 --- /dev/null +++ b/0027-openssh-7.5p1-sandbox.patch @@ -0,0 +1,58 @@ +From 35205319dd71d8e61c1596b8f9479df91aff7756 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 27/50] openssh-7.5p1-sandbox + +--- + sandbox-seccomp-filter.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c +index b31062c2..1fabf99d 100644 +--- a/sandbox-seccomp-filter.c ++++ b/sandbox-seccomp-filter.c +@@ -277,6 +277,9 @@ static const struct sock_filter preauth_insns[] = { + #ifdef __NR_exit_group + SC_ALLOW(__NR_exit_group), + #endif ++#if defined(__NR_flock) && defined(__s390__) ++ SC_ALLOW(__NR_flock), ++#endif + #ifdef __NR_futex + SC_FUTEX(__NR_futex), + #endif +@@ -295,6 +298,21 @@ static const struct sock_filter preauth_insns[] = { + #ifdef __NR_getpid + SC_ALLOW(__NR_getpid), + #endif ++#ifdef __NR_getuid ++ SC_ALLOW(__NR_getuid), ++#endif ++#ifdef __NR_getuid32 ++ SC_ALLOW(__NR_getuid32), ++#endif ++#ifdef __NR_geteuid ++ SC_ALLOW(__NR_geteuid), ++#endif ++#ifdef __NR_geteuid32 ++ SC_ALLOW(__NR_geteuid32), ++#endif ++#ifdef __NR_gettid ++ SC_ALLOW(__NR_gettid), ++#endif + #ifdef __NR_getrandom + SC_ALLOW(__NR_getrandom), + #endif +@@ -304,6 +322,9 @@ static const struct sock_filter preauth_insns[] = { + #ifdef __NR_gettimeofday + SC_ALLOW(__NR_gettimeofday), + #endif ++#if defined(__NR_ipc) && defined(__s390__) ++ SC_ALLOW(__NR_ipc), ++#endif + #ifdef __NR_getuid + SC_ALLOW(__NR_getuid), + #endif +-- +2.49.0 + diff --git a/openssh-8.0p1-pkcs11-uri.patch b/0028-openssh-8.0p1-pkcs11-uri.patch similarity index 90% rename from openssh-8.0p1-pkcs11-uri.patch rename to 0028-openssh-8.0p1-pkcs11-uri.patch index bdc4722..73e890b 100644 --- a/openssh-8.0p1-pkcs11-uri.patch +++ b/0028-openssh-8.0p1-pkcs11-uri.patch @@ -1,7 +1,102 @@ -diff -up openssh-9.6p1/configure.ac.pkcs11-uri openssh-9.6p1/configure.ac ---- openssh-9.6p1/configure.ac.pkcs11-uri 2024-01-12 14:25:25.228942213 +0100 -+++ openssh-9.6p1/configure.ac 2024-01-12 14:25:25.233942336 +0100 -@@ -2066,12 +2066,14 @@ AC_LINK_IFELSE( +From 5d6ec35c1a0e06452a2c087decb0baf6e8063e21 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 28/50] openssh-8.0p1-pkcs11-uri + +--- + Makefile.in | 20 +- + configure.ac | 37 ++ + regress/Makefile | 8 +- + regress/pkcs11.sh | 349 +++++++++++++++ + regress/unittests/Makefile | 2 +- + regress/unittests/pkcs11/tests.c | 346 ++++++++++++++ + ssh-add.c | 48 +- + ssh-agent.c | 103 ++++- + ssh-keygen.c | 7 +- + ssh-pkcs11-client.c | 3 + + ssh-pkcs11-uri.c | 437 ++++++++++++++++++ + ssh-pkcs11-uri.h | 43 ++ + ssh-pkcs11.c | 745 +++++++++++++++++++++++-------- + ssh-pkcs11.h | 4 + + ssh.c | 104 ++++- + ssh_config.5 | 15 + + 16 files changed, 2024 insertions(+), 247 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 78f65948..6c417ef7 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -110,7 +110,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 \ +@@ -339,6 +339,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/ssh-verify-attestation/ssh-verify-attestation$(EXEEXT) +@@ -377,6 +379,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 +@@ -558,6 +562,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 + $(MKDIR_P) `pwd`/regress/misc/ssh-verify-attestation + [ -f `pwd`/regress/Makefile ] || \ +@@ -731,6 +736,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 \ +@@ -776,7 +791,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 extra-tests unit + echo all tests passed +diff --git a/configure.ac b/configure.ac +index 13c70a98..d9bd2f51 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2172,12 +2172,14 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) @@ -16,7 +111,7 @@ diff -up openssh-9.6p1/configure.ac.pkcs11-uri openssh-9.6p1/configure.ac fi ] ) -@@ -2095,6 +2097,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) +@@ -2207,6 +2209,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_FUNCS([dlopen]) AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) @@ -57,7 +152,7 @@ diff -up openssh-9.6p1/configure.ac.pkcs11-uri openssh-9.6p1/configure.ac # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5708,6 +5744,7 @@ echo " BSD Auth support +@@ -5820,6 +5856,7 @@ echo " BSD Auth support: $BSD_AUTH_MSG" echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" @@ -65,75 +160,11 @@ diff -up openssh-9.6p1/configure.ac.pkcs11-uri openssh-9.6p1/configure.ac echo " U2F/FIDO support: $enable_sk" echo "" -diff -up openssh-9.6p1/Makefile.in.pkcs11-uri openssh-9.6p1/Makefile.in ---- openssh-9.6p1/Makefile.in.pkcs11-uri 2024-01-12 14:25:25.204941622 +0100 -+++ openssh-9.6p1/Makefile.in 2024-01-12 14:25:25.233942336 +0100 -@@ -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 ed25519.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 -@@ -685,6 +690,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 \ -@@ -720,7 +735,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 extra-tests unit - echo all tests passed -diff -up openssh-9.6p1/regress/Makefile.pkcs11-uri openssh-9.6p1/regress/Makefile ---- openssh-9.6p1/regress/Makefile.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 -+++ openssh-9.6p1/regress/Makefile 2024-01-12 14:25:25.233942336 +0100 -@@ -134,7 +134,8 @@ CLEANFILES= *.core actual agent-key.* au +diff --git a/regress/Makefile b/regress/Makefile +index 7e7f95b5..f36de51e 100644 +--- a/regress/Makefile ++++ b/regress/Makefile +@@ -137,7 +137,8 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ modpipe netcat no_identity_config \ pidfile putty.rsa2 ready regress.log remote_pid \ @@ -143,7 +174,7 @@ diff -up openssh-9.6p1/regress/Makefile.pkcs11-uri openssh-9.6p1/regress/Makefil 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 \ -@@ -273,8 +274,9 @@ unit: +@@ -297,8 +298,9 @@ unit: V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ @@ -155,9 +186,11 @@ diff -up openssh-9.6p1/regress/Makefile.pkcs11-uri openssh-9.6p1/regress/Makefil -d ${.CURDIR}/unittests/sshkey/testdata ; \ $$V ${.OBJDIR}/unittests/sshsig/test_sshsig \ -d ${.CURDIR}/unittests/sshsig/testdata ; \ -diff -up openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri openssh-9.6p1/regress/pkcs11.sh ---- openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri 2024-01-12 14:25:25.233942336 +0100 -+++ openssh-9.6p1/regress/pkcs11.sh 2024-01-12 14:25:25.233942336 +0100 +diff --git a/regress/pkcs11.sh b/regress/pkcs11.sh +new file mode 100644 +index 00000000..a91aee94 +--- /dev/null ++++ b/regress/pkcs11.sh @@ -0,0 +1,349 @@ +# +# Copyright (c) 2017 Red Hat @@ -508,9 +541,10 @@ diff -up openssh-9.6p1/regress/pkcs11.sh.pkcs11-uri openssh-9.6p1/regress/pkcs11 + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi -diff -up openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri openssh-9.6p1/regress/unittests/Makefile ---- openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 -+++ openssh-9.6p1/regress/unittests/Makefile 2024-01-12 14:25:25.233942336 +0100 +diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile +index e370900e..d6c89c12 100644 +--- a/regress/unittests/Makefile ++++ b/regress/unittests/Makefile @@ -1,6 +1,6 @@ # $OpenBSD: Makefile,v 1.13 2023/09/24 08:14:13 claudio Exp $ @@ -519,9 +553,11 @@ diff -up openssh-9.6p1/regress/unittests/Makefile.pkcs11-uri openssh-9.6p1/regre +SUBDIR+=authopt misc sshsig pkcs11 .include -diff -up openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-9.6p1/regress/unittests/pkcs11/tests.c ---- openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri 2024-01-12 14:25:25.233942336 +0100 -+++ openssh-9.6p1/regress/unittests/pkcs11/tests.c 2024-01-12 14:25:25.233942336 +0100 +diff --git a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c +new file mode 100644 +index 00000000..7d4fa499 +--- /dev/null ++++ b/regress/unittests/pkcs11/tests.c @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2017 Red Hat @@ -869,9 +905,10 @@ diff -up openssh-9.6p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-9.6p1 + test_parse_invalid(); + test_generate_valid(); +} -diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c ---- openssh-9.6p1/ssh-add.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 -+++ openssh-9.6p1/ssh-add.c 2024-01-12 14:25:25.233942336 +0100 +diff --git a/ssh-add.c b/ssh-add.c +index 0035cb84..b0f47f4d 100644 +--- a/ssh-add.c ++++ b/ssh-add.c @@ -69,6 +69,7 @@ #include "ssh-sk.h" #include "sk-api.h" @@ -880,7 +917,7 @@ diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c /* argv0 */ extern char *__progname; -@@ -240,6 +241,38 @@ delete_all(int agent_fd, int qflag) +@@ -242,6 +243,38 @@ delete_all(int agent_fd, int qflag) return ret; } @@ -919,7 +956,7 @@ diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c static int add_file(int agent_fd, const char *filename, int key_only, int cert_only, int qflag, const char *skprovider, -@@ -460,15 +489,14 @@ static int +@@ -462,15 +495,14 @@ static int update_card(int agent_fd, int add, const char *id, int qflag, int key_only, int cert_only, struct dest_constraint **dest_constraints, size_t ndest_constraints, @@ -937,7 +974,7 @@ diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; -@@ -656,6 +684,14 @@ do_file(int agent_fd, int deleting, int +@@ -658,6 +690,14 @@ do_file(int agent_fd, int deleting, int key_only, int cert_only, char *file, int qflag, const char *skprovider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { @@ -952,7 +989,7 @@ diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c if (deleting) { if (delete_file(agent_fd, file, key_only, cert_only, qflag) == -1) -@@ -999,7 +1035,7 @@ main(int argc, char **argv) +@@ -1001,7 +1041,7 @@ main(int argc, char **argv) if (update_card(agent_fd, !deleting, pkcs11provider, qflag, key_only, cert_only, dest_constraints, ndest_constraints, @@ -961,10 +998,11 @@ diff -up openssh-9.6p1/ssh-add.c.pkcs11-uri openssh-9.6p1/ssh-add.c ret = 1; goto done; } -diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c ---- openssh-9.6p1/ssh-agent.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 -+++ openssh-9.6p1/ssh-agent.c 2024-01-12 14:25:25.234942360 +0100 -@@ -1549,10 +1549,74 @@ add_p11_identity(struct sshkey *key, cha +diff --git a/ssh-agent.c b/ssh-agent.c +index c27c5a95..798bf9b6 100644 +--- a/ssh-agent.c ++++ b/ssh-agent.c +@@ -1569,10 +1569,74 @@ add_p11_identity(struct sshkey *key, char *comment, const char *provider, idtab->nentries++; } @@ -1040,21 +1078,21 @@ diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds = 0; -@@ -1581,25 +1643,18 @@ process_add_smartcard_key(SocketEntry *e +@@ -1601,25 +1665,18 @@ process_add_smartcard_key(SocketEntry *e) "providers is disabled", provider); goto send; } - if (realpath(provider, canonical_provider) == NULL) { - verbose("failed PKCS#11 add of \"%.100s\": realpath: %s", - provider, strerror(errno)); -+ sane_uri = sanitize_pkcs11_provider(provider); -+ if (sane_uri == NULL) - goto send; +- goto send; - } - if (match_pattern_list(canonical_provider, allowed_providers, 0) != 1) { - verbose("refusing PKCS#11 add of \"%.100s\": " - "provider not allowed", canonical_provider); -- goto send; ++ sane_uri = sanitize_pkcs11_provider(provider); ++ if (sane_uri == NULL) + goto send; - } - debug_f("add %.100s", canonical_provider); if (lifetime && !death) @@ -1071,7 +1109,7 @@ diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c } for (j = 0; j < ncerts; j++) { if (!sshkey_is_cert(certs[j])) -@@ -1609,13 +1664,13 @@ process_add_smartcard_key(SocketEntry *e +@@ -1629,13 +1686,13 @@ process_add_smartcard_key(SocketEntry *e) if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) continue; add_p11_identity(k, xstrdup(comments[i]), @@ -1087,7 +1125,7 @@ diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c dest_constraints, ndest_constraints); keys[i] = NULL; /* transferred */ comments[i] = NULL; /* transferred */ -@@ -1628,6 +1683,7 @@ process_add_smartcard_key(SocketEntry *e +@@ -1648,6 +1705,7 @@ process_add_smartcard_key(SocketEntry *e) send: free(pin); free(provider); @@ -1095,7 +1133,7 @@ diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c free(keys); free(comments); free_dest_constraints(dest_constraints, ndest_constraints); -@@ -1640,7 +1696,7 @@ send: +@@ -1660,7 +1718,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { @@ -1104,7 +1142,7 @@ diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c int r, success = 0; Identity *id, *nxt; -@@ -1652,30 +1708,29 @@ process_remove_smartcard_key(SocketEntry +@@ -1672,30 +1730,29 @@ process_remove_smartcard_key(SocketEntry *e) } free(pin); @@ -1141,185 +1179,11 @@ diff -up openssh-9.6p1/ssh-agent.c.pkcs11-uri openssh-9.6p1/ssh-agent.c send_status(e, success); } #endif /* ENABLE_PKCS11 */ -diff -up openssh-9.6p1/ssh_config.5.pkcs11-uri openssh-9.6p1/ssh_config.5 ---- openssh-9.6p1/ssh_config.5.pkcs11-uri 2024-01-12 14:25:25.208941721 +0100 -+++ openssh-9.6p1/ssh_config.5 2024-01-12 14:25:25.234942360 +0100 -@@ -1216,6 +1216,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-9.6p1/ssh.c.pkcs11-uri openssh-9.6p1/ssh.c ---- openssh-9.6p1/ssh.c.pkcs11-uri 2024-01-12 14:25:25.208941721 +0100 -+++ openssh-9.6p1/ssh.c 2024-01-12 14:25:25.234942360 +0100 -@@ -882,6 +882,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; -+ } -+#endif - p = tilde_expand_filename(optarg, getuid()); - if (stat(p, &st) == -1) - fprintf(stderr, "Warning: Identity file %s " -@@ -1784,6 +1792,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); -@@ -2307,6 +2316,45 @@ ssh_session2(struct ssh *ssh, const stru - 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; -+ -+ debug("identity file '%s' from pkcs#11", pkcs11_uri); -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PKCS#11 URI"); -+ -+ if (pkcs11_uri_parse(pkcs11_uri, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri); -+ -+ /* we need to merge URI and provider together */ -+ if (options.pkcs11_provider != NULL && uri->module_path == NULL) -+ uri->module_path = strdup(options.pkcs11_provider); -+ -+ 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); -+ } -+ -+ pkcs11_uri_cleanup(uri); -+} -+#endif /* ENABLE_PKCS11 */ -+ - /* Loads all IdentityFile and CertificateFile keys */ - static void - load_public_identity_files(const struct ssh_conn_info *cinfo) -@@ -2321,11 +2369,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)); -@@ -2338,33 +2381,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); -+ -+ if (options.pkcs11_provider != NULL) { -+ struct pkcs11_uri *uri; -+ -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PKCS#11 URI"); -+ -+ /* Construct simple PKCS#11 URI to simplify access */ -+ uri->module_path = strdup(options.pkcs11_provider); -+ -+ /* Add it as any other IdentityFile */ -+ cp = pkcs11_uri_get(uri); -+ add_identity_file(&options, NULL, cp, 1); -+ free(cp); -+ -+ 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 -up openssh-9.6p1/ssh-keygen.c.pkcs11-uri openssh-9.6p1/ssh-keygen.c ---- openssh-9.6p1/ssh-keygen.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 -+++ openssh-9.6p1/ssh-keygen.c 2024-01-12 14:25:25.234942360 +0100 -@@ -862,8 +862,11 @@ do_download(struct passwd *pw) +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 89c3ed28..16cff947 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -906,8 +906,11 @@ do_download(struct passwd *pw) free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ @@ -1333,10 +1197,11 @@ diff -up openssh-9.6p1/ssh-keygen.c.pkcs11-uri openssh-9.6p1/ssh-keygen.c } free(comments[i]); sshkey_free(keys[i]); -diff -up openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-client.c ---- openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 -+++ openssh-9.6p1/ssh-pkcs11-client.c 2024-01-12 14:25:25.234942360 +0100 -@@ -592,6 +592,8 @@ pkcs11_add_provider(char *name, char *pi +diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c +index b8d1700f..64df695e 100644 +--- a/ssh-pkcs11-client.c ++++ b/ssh-pkcs11-client.c +@@ -635,6 +635,8 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, struct sshbuf *msg; struct helper *helper; @@ -1345,7 +1210,7 @@ diff -up openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-c if ((helper = helper_by_provider(name)) == NULL && (helper = pkcs11_start_helper(name)) == NULL) return -1; -@@ -612,6 +614,7 @@ pkcs11_add_provider(char *name, char *pi +@@ -655,6 +657,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); if (labelsp) *labelsp = xcalloc(nkeys, sizeof(char *)); @@ -1353,1296 +1218,11 @@ diff -up openssh-9.6p1/ssh-pkcs11-client.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-c 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-9.9p1/ssh-pkcs11.c.xxx openssh-9.9p1/ssh-pkcs11.c ---- openssh-9.9p1/ssh-pkcs11.c.xxx 2024-10-09 11:56:35.890126144 +0200 -+++ openssh-9.9p1/ssh-pkcs11.c 2024-10-09 11:56:48.528459585 +0200 -@@ -38,6 +38,7 @@ - #include - #include - #include -+#include - - #define CRYPTOKI_COMPAT - #include "pkcs11.h" -@@ -55,8 +55,8 @@ struct pkcs11_slotinfo { - int logged_in; - }; - --struct pkcs11_provider { -- char *name; -+struct pkcs11_module { -+ char *module_path; - void *handle; - CK_FUNCTION_LIST *function_list; - CK_INFO info; -@@ -65,6 +65,13 @@ struct pkcs11_provider { - struct pkcs11_slotinfo *slotinfo; - int valid; - int refcount; -+}; -+ -+struct pkcs11_provider { -+ char *name; -+ struct pkcs11_module *module; /* can be shared between various providers */ -+ int refcount; -+ int valid; - TAILQ_ENTRY(pkcs11_provider) next; - }; - -@@ -75,6 +82,7 @@ struct pkcs11_key { - CK_ULONG slotidx; - char *keyid; - int keyid_len; -+ char *label; - }; - - int pkcs11_interactive = 0; -@@ -106,26 +114,61 @@ pkcs11_init(int interactive) - * this is called when a provider gets unregistered. - */ - static void --pkcs11_provider_finalize(struct pkcs11_provider *p) -+pkcs11_module_finalize(struct pkcs11_module *m) - { - CK_RV rv; - CK_ULONG i; - -- debug_f("provider \"%s\" refcount %d valid %d", -- p->name, p->refcount, p->valid); -- if (!p->valid) -+ debug_f("%p refcount %d valid %d", m, m->refcount, m->valid); -+ if (!m->valid) - return; -- for (i = 0; i < p->nslots; i++) { -- if (p->slotinfo[i].session && -- (rv = p->function_list->C_CloseSession( -- p->slotinfo[i].session)) != CKR_OK) -+ for (i = 0; i < m->nslots; i++) { -+ if (m->slotinfo[i].session && -+ (rv = m->function_list->C_CloseSession( -+ m->slotinfo[i].session)) != CKR_OK) - error("C_CloseSession failed: %lu", rv); - } -- if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK) -+ if ((rv = m->function_list->C_Finalize(NULL)) != CKR_OK) - error("C_Finalize failed: %lu", rv); -+ m->valid = 0; -+ m->function_list = NULL; -+ dlclose(m->handle); -+} -+ -+/* -+ * remove a reference to the pkcs11 module. -+ * called when a provider is unregistered. -+ */ -+static void -+pkcs11_module_unref(struct pkcs11_module *m) -+{ -+ debug_f("%p refcount %d", m, m->refcount); -+ if (--m->refcount <= 0) { -+ pkcs11_module_finalize(m); -+ if (m->valid) -+ error_f("%p still valid", m); -+ free(m->slotlist); -+ free(m->slotinfo); -+ free(m->module_path); -+ free(m); -+ } -+} -+ -+/* -+ * finalize a provider shared library, it's no longer usable. -+ * however, there might still be keys referencing this provider, -+ * so the actual freeing of memory is handled by pkcs11_provider_unref(). -+ * this is called when a provider gets unregistered. -+ */ -+static void -+pkcs11_provider_finalize(struct pkcs11_provider *p) -+{ -+ debug_f("%p refcount %d valid %d", p, p->refcount, p->valid); -+ if (!p->valid) -+ return; -+ pkcs11_module_unref(p->module); -+ p->module = NULL; - p->valid = 0; -- p->function_list = NULL; -- dlclose(p->handle); - } - - /* -@@ -137,11 +180,9 @@ pkcs11_provider_unref(struct pkcs11_prov - { - debug_f("provider \"%s\" refcount %d", p->name, p->refcount); - if (--p->refcount <= 0) { -- if (p->valid) -- error_f("provider \"%s\" still valid", p->name); - free(p->name); -- free(p->slotlist); -- free(p->slotinfo); -+ if (p->module) -+ pkcs11_module_unref(p->module); - free(p); - } - } -@@ -159,6 +200,20 @@ pkcs11_terminate(void) - } - } - -+/* lookup provider by module path */ -+static struct pkcs11_module * -+pkcs11_provider_lookup_module(char *module_path) -+{ -+ struct pkcs11_provider *p; -+ -+ TAILQ_FOREACH(p, &pkcs11_providers, next) { -+ debug("check %p %s (%s)", p, p->name, p->module->module_path); -+ if (!strcmp(module_path, p->module->module_path)) -+ return (p->module); -+ } -+ return (NULL); -+} -+ - /* lookup provider by name */ - static struct pkcs11_provider * - pkcs11_provider_lookup(char *provider_id) -@@ -173,19 +228,55 @@ pkcs11_provider_lookup(char *provider_id - return (NULL); - } - -+int pkcs11_del_provider_by_uri(struct pkcs11_uri *); -+ - /* unregister provider by name */ - int - pkcs11_del_provider(char *provider_id) - { -+ int rv; -+ struct pkcs11_uri *uri; -+ -+ debug_f("called, provider_id = %s", provider_id); -+ -+ if (provider_id == NULL) -+ return 0; -+ -+ 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); -+ } -+ -+ rv = pkcs11_del_provider_by_uri(uri); -+ pkcs11_uri_cleanup(uri); -+ return rv; -+} -+ -+/* 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); -+ -+ debug3_f("called with provider %s", provider_uri); - -- if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { -+ if ((p = pkcs11_provider_lookup(provider_uri)) != NULL) { - TAILQ_REMOVE(&pkcs11_providers, p, next); - pkcs11_provider_finalize(p); - pkcs11_provider_unref(p); -- return (0); -+ rv = 0; - } -- return (-1); -+ free(provider_uri); -+ return rv; - } - - static RSA_METHOD *rsa_method; -@@ -195,6 +286,60 @@ static EC_KEY_METHOD *ec_key_method; - static int ec_key_idx = 0; - #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - -+/* -+ * This can't be in the ssh-pkcs11-uri, becase we can not depend on -+ * PKCS#11 structures in ssh-agent (using client-helper communication) -+ */ -+int -+pkcs11_uri_write(const struct sshkey *key, FILE *f) -+{ -+ char *p = NULL; -+ struct pkcs11_uri uri; -+ struct pkcs11_key *k11; -+ -+ /* sanity - is it a RSA key with associated app_data? */ -+ switch (key->type) { -+ case KEY_RSA: { -+ const RSA *rsa = EVP_PKEY_get0_RSA(key->pkey); -+ k11 = RSA_get_ex_data(rsa, rsa_idx); -+ break; -+ } -+#ifdef HAVE_EC_KEY_METHOD_NEW -+ case KEY_ECDSA: { -+ const EC_KEY * ecdsa = EVP_PKEY_get0_EC_KEY(key->pkey); -+ k11 = EC_KEY_get_ex_data(ecdsa, ec_key_idx); -+ break; -+ } -+#endif -+ default: -+ error("Unknown key type %d", key->type); -+ return -1; -+ } -+ if (k11 == NULL) { -+ error("Failed to get ex_data for key type %d", key->type); -+ return (-1); -+ } -+ -+ /* omit type -- we are looking for private-public or private-certificate pairs */ -+ uri.id = k11->keyid; -+ uri.id_len = k11->keyid_len; -+ uri.token = k11->provider->module->slotinfo[k11->slotidx].token.label; -+ uri.object = k11->label; -+ uri.module_path = k11->provider->module->module_path; -+ uri.lib_manuf = k11->provider->module->info.manufacturerID; -+ uri.manuf = k11->provider->module->slotinfo[k11->slotidx].token.manufacturerID; -+ uri.serial = k11->provider->module->slotinfo[k11->slotidx].token.serialNumber; -+ -+ p = pkcs11_uri_get(&uri); -+ /* do not cleanup -- we do not allocate here, only reference */ -+ if (p == NULL) -+ return -1; -+ -+ fprintf(f, " %s", p); -+ free(p); -+ return 0; -+} -+ - /* release a wrapped object */ - static void - pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, -@@ -208,6 +349,7 @@ pkcs11_k11_free(void *parent, void *ptr, - if (k11->provider) - pkcs11_provider_unref(k11->provider); - free(k11->keyid); -+ free(k11->label); - free(k11); - } - -@@ -222,8 +364,8 @@ pkcs11_find(struct pkcs11_provider *p, C - CK_RV rv; - int ret = -1; - -- f = p->function_list; -- session = p->slotinfo[slotidx].session; -+ f = p->module->function_list; -+ session = p->module->slotinfo[slotidx].session; - if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { - error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); - return (-1); -@@ -260,14 +402,14 @@ pkcs11_login_slot(struct pkcs11_provider - if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) - verbose("Deferring PIN entry to reader keypad."); - else { -- snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", -+ snprintf(prompt, sizeof(prompt), "Enter PIN for '%.32s': ", - si->token.label); -- if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) { -+ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF|RP_ALLOW_STDIN)) == NULL) { - debug_f("no pin specified"); - return (-1); /* bail out */ - } - } -- rv = provider->function_list->C_Login(si->session, type, (u_char *)pin, -+ rv = provider->module->function_list->C_Login(si->session, type, (u_char *)pin, - (pin != NULL) ? strlen(pin) : 0); - if (pin != NULL) - freezero(pin, strlen(pin)); -@@ -297,13 +439,14 @@ pkcs11_login_slot(struct pkcs11_provider - static int - pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) - { -- if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) { -+ if (k11 == NULL || k11->provider == NULL || !k11->provider->valid || -+ k11->provider->module == NULL || !k11->provider->module->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - - return pkcs11_login_slot(k11->provider, -- &k11->provider->slotinfo[k11->slotidx], type); -+ &k11->provider->module->slotinfo[k11->slotidx], type); - } - - -@@ -319,13 +462,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs - - *val = 0; - -- if (!k11->provider || !k11->provider->valid) { -+ if (!k11->provider || !k11->provider->valid || -+ !k11->provider->module || !k11->provider->module->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - attr.type = type; - attr.pValue = &flag; -@@ -356,13 +500,14 @@ pkcs11_get_key(struct pkcs11_key *k11, C - int always_auth = 0; - int did_login = 0; - -- if (!k11->provider || !k11->provider->valid) { -+ if (!k11->provider || !k11->provider->valid || -+ !k11->provider->module || !k11->provider->module->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { - if (pkcs11_login(k11, CKU_USER) < 0) { -@@ -439,8 +584,8 @@ pkcs11_rsa_private_encrypt(int flen, con - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - tlen = RSA_size(rsa); - - /* XXX handle CKR_BUFFER_TOO_SMALL */ -@@ -484,7 +629,7 @@ pkcs11_rsa_start_wrapper(void) - /* redirect private key operations for rsa key to pkcs11 token */ - static int - pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, -- CK_ATTRIBUTE *keyid_attrib, RSA *rsa) -+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, RSA *rsa) - { - struct pkcs11_key *k11; - -@@ -502,6 +647,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider * - 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); -+ k11->label[label_attrib->ulValueLen] = 0; -+ } -+ - if (RSA_set_method(rsa, rsa_method) != 1) - fatal_f("RSA_set_method failed"); - if (RSA_set_ex_data(rsa, rsa_idx, k11) != 1) -@@ -532,8 +683,8 @@ ecdsa_do_sign(const unsigned char *dgst, - return (NULL); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - siglen = ECDSA_size(ec); - sig = xmalloc(siglen); -@@ -598,7 +749,7 @@ pkcs11_ecdsa_start_wrapper(void) - - static int - pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, -- CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) -+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ec) - { - struct pkcs11_key *k11; - -@@ -615,6 +766,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); -+ k11->label[label_attrib->ulValueLen] = 0; -+ } -+ - if (EC_KEY_set_method(ec, ec_key_method) != 1) - fatal_f("EC_KEY_set_method failed"); - if (EC_KEY_set_ex_data(ec, ec_key_idx, k11) != 1) -@@ -622,7 +779,8 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider - } - #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - --/* remove trailing spaces */ -+/* remove trailing spaces. Note, that this does NOT guarantee the buffer -+ * will be null terminated if there are no trailing spaces! */ - static char * - rmspace(u_char *buf, size_t len) - { -@@ -654,8 +812,8 @@ pkcs11_open_session(struct pkcs11_provid - CK_SESSION_HANDLE session; - int login_required, ret; - -- f = p->function_list; -- si = &p->slotinfo[slotidx]; -+ f = p->module->function_list; -+ si = &p->module->slotinfo[slotidx]; - - login_required = si->token.flags & CKF_LOGIN_REQUIRED; - -@@ -665,9 +823,9 @@ pkcs11_open_session(struct pkcs11_provid - error("pin required"); - return (-SSH_PKCS11_ERR_PIN_REQUIRED); - } -- if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| -+ if ((rv = f->C_OpenSession(p->module->slotlist[slotidx], CKF_RW_SESSION| - CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { -- error("C_OpenSession failed: %lu", rv); -+ error("C_OpenSession failed for slot %lu: %lu", slotidx, rv); - return (-1); - } - if (login_required && pin != NULL && strlen(pin) != 0) { -@@ -703,7 +861,8 @@ static struct sshkey * - pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj) - { -- CK_ATTRIBUTE key_attr[3]; -+ CK_ATTRIBUTE key_attr[4]; -+ int nattr = 4; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -717,14 +876,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ - - memset(&key_attr, 0, sizeof(key_attr)); - key_attr[0].type = CKA_ID; -- key_attr[1].type = CKA_EC_POINT; -- key_attr[2].type = CKA_EC_PARAMS; -+ key_attr[1].type = CKA_LABEL; -+ key_attr[2].type = CKA_EC_POINT; -+ key_attr[3].type = CKA_EC_PARAMS; - -- session = p->slotinfo[slotidx].session; -- f = p->function_list; -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - - /* figure out size of the attributes */ -- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return (NULL); -@@ -735,19 +895,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ - * ensure that none of the others are zero length. - * XXX assumes CKA_ID is always first. - */ -- if (key_attr[1].ulValueLen == 0 || -- key_attr[2].ulValueLen == 0) { -+ if (key_attr[2].ulValueLen == 0 || -+ key_attr[3].ulValueLen == 0) { - error("invalid attribute length"); - return (NULL); - } - - /* allocate buffers for attributes */ -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - if (key_attr[i].ulValueLen > 0) - key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); - - /* retrieve ID, public point and curve parameters of EC key */ -- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto fail; -@@ -759,8 +919,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ - goto fail; - } - -- attrp = key_attr[2].pValue; -- group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); -+ attrp = key_attr[3].pValue; -+ group = d2i_ECPKParameters(NULL, &attrp, key_attr[3].ulValueLen); - if (group == NULL) { - ossl_error("d2i_ECPKParameters failed"); - goto fail; -@@ -771,13 +931,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ - goto fail; - } - -- if (key_attr[1].ulValueLen <= 2) { -+ if (key_attr[2].ulValueLen <= 2) { - error("CKA_EC_POINT too small"); - goto fail; - } - -- attrp = key_attr[1].pValue; -- octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen); -+ attrp = key_attr[2].pValue; -+ octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[2].ulValueLen); - if (octet == NULL) { - ossl_error("d2i_ASN1_OCTET_STRING failed"); - goto fail; -@@ -794,7 +954,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ - goto fail; - } - -- if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) -+ if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], ec)) - goto fail; - - key = sshkey_new(KEY_UNSPEC); -@@ -810,7 +970,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_ - key->flags |= SSHKEY_FLAG_EXT; - - fail: -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - free(key_attr[i].pValue); - if (ec) - EC_KEY_free(ec); -@@ -827,7 +987,8 @@ static struct sshkey * - pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj) - { -- CK_ATTRIBUTE key_attr[3]; -+ CK_ATTRIBUTE key_attr[4]; -+ int nattr = 4; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -838,14 +999,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr - - memset(&key_attr, 0, sizeof(key_attr)); - key_attr[0].type = CKA_ID; -- key_attr[1].type = CKA_MODULUS; -- key_attr[2].type = CKA_PUBLIC_EXPONENT; -+ key_attr[1].type = CKA_LABEL; -+ key_attr[2].type = CKA_MODULUS; -+ key_attr[3].type = CKA_PUBLIC_EXPONENT; - -- session = p->slotinfo[slotidx].session; -- f = p->function_list; -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - - /* figure out size of the attributes */ -- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return (NULL); -@@ -856,19 +1018,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr - * ensure that none of the others are zero length. - * XXX assumes CKA_ID is always first. - */ -- if (key_attr[1].ulValueLen == 0 || -- key_attr[2].ulValueLen == 0) { -+ if (key_attr[2].ulValueLen == 0 || -+ key_attr[3].ulValueLen == 0) { - error("invalid attribute length"); - return (NULL); - } - - /* allocate buffers for attributes */ -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - if (key_attr[i].ulValueLen > 0) - key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); - - /* retrieve ID, modulus and public exponent of RSA key */ -- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto fail; -@@ -880,8 +1042,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr - goto fail; - } - -- rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); -- rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); -+ rsa_n = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); -+ rsa_e = BN_bin2bn(key_attr[3].pValue, key_attr[3].ulValueLen, NULL); - if (rsa_n == NULL || rsa_e == NULL) { - error("BN_bin2bn failed"); - goto fail; -@@ -890,7 +1052,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr - fatal_f("set key"); - rsa_n = rsa_e = NULL; /* transferred */ - -- if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) -+ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], rsa)) - goto fail; - - key = sshkey_new(KEY_UNSPEC); -@@ -905,7 +1067,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_pr - key->flags |= SSHKEY_FLAG_EXT; - - fail: -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - free(key_attr[i].pValue); - RSA_free(rsa); - -@@ -916,7 +1078,8 @@ static int - pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) - { -- CK_ATTRIBUTE cert_attr[3]; -+ CK_ATTRIBUTE cert_attr[4]; -+ int nattr = 4; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -940,14 +1103,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p - - memset(&cert_attr, 0, sizeof(cert_attr)); - cert_attr[0].type = CKA_ID; -- cert_attr[1].type = CKA_SUBJECT; -- cert_attr[2].type = CKA_VALUE; -+ cert_attr[1].type = CKA_LABEL; -+ cert_attr[2].type = CKA_SUBJECT; -+ cert_attr[3].type = CKA_VALUE; - -- session = p->slotinfo[slotidx].session; -- f = p->function_list; -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - - /* figure out size of the attributes */ -- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - return -1; -@@ -959,18 +1123,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p - * XXX assumes CKA_ID is always first. - */ - if (cert_attr[1].ulValueLen == 0 || -- cert_attr[2].ulValueLen == 0) { -+ cert_attr[2].ulValueLen == 0 || -+ cert_attr[3].ulValueLen == 0) { - error("invalid attribute length"); - return -1; - } - - /* allocate buffers for attributes */ -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - if (cert_attr[i].ulValueLen > 0) - cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); - - /* retrieve ID, subject and value of certificate */ -- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); -+ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); - if (rv != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - goto out; -@@ -984,8 +1149,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p - subject = xstrdup("invalid subject"); - X509_NAME_free(x509_name); - -- cp = cert_attr[2].pValue; -- if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) { -+ cp = cert_attr[3].pValue; -+ if ((x509 = d2i_X509(NULL, &cp, cert_attr[3].ulValueLen)) == NULL) { - error("d2i_x509 failed"); - goto out; - } -@@ -1005,7 +1170,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p - goto out; - } - -- if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) -+ if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], rsa)) - goto out; - - key = sshkey_new(KEY_UNSPEC); -@@ -1035,7 +1200,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p - goto out; - } - -- if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) -+ if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], ec)) - goto out; - - key = sshkey_new(KEY_UNSPEC); -@@ -1055,7 +1220,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_p - goto out; - } - out: -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - free(cert_attr[i].pValue); - X509_free(x509); - RSA_free(rsa); -@@ -1106,11 +1271,12 @@ note_key(struct pkcs11_provider *p, CK_U - */ - static int - pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, -- struct sshkey ***keysp, char ***labelsp, int *nkeys) -+ struct sshkey ***keysp, char ***labelsp, int *nkeys, struct pkcs11_uri *uri) - { - struct sshkey *key = NULL; - CK_OBJECT_CLASS key_class; -- CK_ATTRIBUTE key_attr[1]; -+ CK_ATTRIBUTE key_attr[3]; -+ int nattr = 1; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -1127,10 +1293,23 @@ pkcs11_fetch_certs(struct pkcs11_provide - key_attr[0].pValue = &key_class; - key_attr[0].ulValueLen = sizeof(key_class); - -- session = p->slotinfo[slotidx].session; -- f = p->function_list; -+ if (uri->id != NULL) { -+ key_attr[nattr].type = CKA_ID; -+ key_attr[nattr].pValue = uri->id; -+ key_attr[nattr].ulValueLen = uri->id_len; -+ nattr++; -+ } -+ if (uri->object != NULL) { -+ key_attr[nattr].type = CKA_LABEL; -+ key_attr[nattr].pValue = uri->object; -+ 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, nattr); - if (rv != CKR_OK) { - error("C_FindObjectsInit failed: %lu", rv); - goto fail; -@@ -1211,11 +1390,12 @@ fail: - */ - static int - pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, -- struct sshkey ***keysp, char ***labelsp, int *nkeys) -+ struct sshkey ***keysp, char ***labelsp, int *nkeys, struct pkcs11_uri *uri) - { - struct sshkey *key = NULL; - CK_OBJECT_CLASS key_class; -- CK_ATTRIBUTE key_attr[2]; -+ CK_ATTRIBUTE key_attr[3]; -+ int nattr = 1; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f = NULL; - CK_RV rv; -@@ -1231,10 +1411,23 @@ pkcs11_fetch_keys(struct pkcs11_provider - key_attr[0].pValue = &key_class; - key_attr[0].ulValueLen = sizeof(key_class); - -- session = p->slotinfo[slotidx].session; -- f = p->function_list; -+ if (uri->id != NULL) { -+ key_attr[nattr].type = CKA_ID; -+ key_attr[nattr].pValue = uri->id; -+ key_attr[nattr].ulValueLen = uri->id_len; -+ nattr++; -+ } -+ if (uri->object != NULL) { -+ key_attr[nattr].type = CKA_LABEL; -+ key_attr[nattr].pValue = uri->object; -+ key_attr[nattr].ulValueLen = strlen(uri->object); -+ nattr++; -+ } -+ -+ 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; -@@ -1503,16 +1696,10 @@ pkcs11_ecdsa_generate_private_key(struct - } - #endif /* WITH_PKCS11_KEYGEN */ - --/* -- * register a new provider, fails if provider already exists. if -- * keyp is provided, fetch keys. -- */ - static int --pkcs11_register_provider(char *provider_id, char *pin, -- struct sshkey ***keyp, char ***labelsp, -- struct pkcs11_provider **providerp, CK_ULONG user) -+pkcs11_initialize_provider(struct pkcs11_uri *uri, struct pkcs11_provider **providerp) - { -- int nkeys, need_finalize = 0; -+ int need_finalize = 0; - int ret = -1; - struct pkcs11_provider *p = NULL; - void *handle = NULL; -@@ -1521,162 +1708,309 @@ pkcs11_register_provider(char *provider_ - CK_FUNCTION_LIST *f = NULL; - CK_TOKEN_INFO *token; - CK_ULONG i; -+ char *provider_module = NULL; -+ struct pkcs11_module *m = NULL; - -- if (providerp == NULL) -- goto fail; -- *providerp = NULL; -- -- if (keyp != NULL) -- *keyp = NULL; -- if (labelsp != NULL) -- *labelsp = NULL; -+ /* if no provider specified, fallback to p11-kit */ -+ if (uri->module_path == NULL) { -+#ifdef PKCS11_DEFAULT_PROVIDER -+ provider_module = strdup(PKCS11_DEFAULT_PROVIDER); -+#else -+ error_f("No module path provided"); -+ goto fail; -+#endif -+ } else { -+ provider_module = strdup(uri->module_path); -+ } -+ 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); -+ if (lib_contains_symbol(provider_module, "C_GetFunctionList") != 0) { -+ error("provider %s is not a PKCS11 library", provider_module); - goto fail; - } -- if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) { -- error("provider %s is not a PKCS11 library", provider_id); -- goto fail; -+ if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL -+ && m->valid) { -+ debug_f("provider module already initialized: %s", provider_module); -+ free(provider_module); -+ /* Skip the initialization of PKCS#11 module */ -+ m->refcount++; -+ p->module = m; -+ p->valid = 1; -+ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -+ p->refcount++; /* add to provider list */ -+ *providerp = p; -+ return 0; -+ } else { -+ m = xcalloc(1, sizeof(*m)); -+ p->module = m; -+ m->refcount++; - } -+ - /* open shared pkcs11-library */ -- if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { -- error("dlopen %s failed: %s", provider_id, dlerror()); -+ if ((handle = dlopen(provider_module, RTLD_NOW)) == NULL) { -+ error("dlopen %s failed: %s", provider_module, dlerror()); - goto fail; - } - if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) - fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); -- p = xcalloc(1, sizeof(*p)); -- p->name = xstrdup(provider_id); -- p->handle = handle; -+ p->module->handle = handle; - /* setup the pkcs11 callbacks */ - if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { - error("C_GetFunctionList for provider %s failed: %lu", -- provider_id, rv); -+ provider_module, rv); - goto fail; - } -- p->function_list = f; -+ m->function_list = f; - if ((rv = f->C_Initialize(NULL)) != CKR_OK) { - error("C_Initialize for provider %s failed: %lu", -- provider_id, rv); -+ provider_module, rv); - goto fail; - } - need_finalize = 1; -- if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) { -+ if ((rv = f->C_GetInfo(&m->info)) != CKR_OK) { - error("C_GetInfo for provider %s failed: %lu", -- provider_id, rv); -+ provider_module, rv); - goto fail; - } -- debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" -- " libraryDescription <%.*s> libraryVersion %d.%d", -- provider_id, -- RMSPACE(p->info.manufacturerID), -- p->info.cryptokiVersion.major, -- p->info.cryptokiVersion.minor, -- RMSPACE(p->info.libraryDescription), -- p->info.libraryVersion.major, -- p->info.libraryVersion.minor); -- if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { -+ rmspace(m->info.manufacturerID, sizeof(m->info.manufacturerID)); -+ if (uri->lib_manuf != NULL && -+ strncmp(uri->lib_manuf, m->info.manufacturerID, 32)) { -+ debug_f("Skipping provider %s not matching library_manufacturer", -+ m->info.manufacturerID); -+ goto fail; -+ } -+ rmspace(m->info.libraryDescription, sizeof(m->info.libraryDescription)); -+ debug("provider %s: manufacturerID <%.32s> cryptokiVersion %d.%d" -+ " libraryDescription <%.32s> libraryVersion %d.%d", -+ provider_module, -+ m->info.manufacturerID, -+ m->info.cryptokiVersion.major, -+ m->info.cryptokiVersion.minor, -+ m->info.libraryDescription, -+ m->info.libraryVersion.major, -+ m->info.libraryVersion.minor); -+ -+ if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &m->nslots)) != CKR_OK) { - error("C_GetSlotList failed: %lu", rv); - goto fail; - } -- if (p->nslots == 0) { -- debug_f("provider %s returned no slots", provider_id); -+ if (m->nslots == 0) { -+ debug_f("provider %s returned no slots", provider_module); - ret = -SSH_PKCS11_ERR_NO_SLOTS; - goto fail; - } -- p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); -- if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots)) -+ m->slotlist = xcalloc(m->nslots, sizeof(CK_SLOT_ID)); -+ if ((rv = f->C_GetSlotList(CK_TRUE, m->slotlist, &m->nslots)) - != CKR_OK) { - error("C_GetSlotList for provider %s failed: %lu", -- provider_id, rv); -+ provider_module, rv); - goto fail; - } -- p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); -+ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); - p->valid = 1; -- nkeys = 0; -- for (i = 0; i < p->nslots; i++) { -- token = &p->slotinfo[i].token; -- if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) -+ m->valid = 1; -+ for (i = 0; i < m->nslots; i++) { -+ token = &m->slotinfo[i].token; -+ if ((rv = f->C_GetTokenInfo(m->slotlist[i], token)) - != CKR_OK) { - error("C_GetTokenInfo for provider %s slot %lu " -- "failed: %lu", provider_id, (u_long)i, rv); -- continue; -- } -- if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { -- debug2_f("ignoring uninitialised token in " -- "provider %s slot %lu", provider_id, (u_long)i); -+ "failed: %lu", provider_module, (u_long)i, rv); -+ token->flags = 0; - continue; - } - debug("provider %s slot %lu: label <%.*s> " - "manufacturerID <%.*s> model <%.*s> serial <%.*s> " - "flags 0x%lx", -- provider_id, (unsigned long)i, -+ provider_module, (unsigned long)i, - RMSPACE(token->label), RMSPACE(token->manufacturerID), - RMSPACE(token->model), RMSPACE(token->serialNumber), - token->flags); -+ } -+ m->module_path = provider_module; -+ provider_module = NULL; -+ -+ /* now owned by caller */ -+ *providerp = p; -+ -+ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -+ p->refcount++; /* add to provider list */ -+ -+ return 0; -+fail: -+ if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) -+ error("C_Finalize for provider %s failed: %lu", -+ provider_module, rv); -+ free(provider_module); -+ if (m) { -+ free(m->slotlist); -+ free(m); -+ } -+ if (p) { -+ free(p->name); -+ free(p); -+ } -+ if (handle) -+ dlclose(handle); -+ return (ret); -+} -+ -+/* -+ * register a new provider, fails if provider already exists. if -+ * keyp is provided, fetch keys. -+ */ -+static int -+pkcs11_register_provider_by_uri(struct pkcs11_uri *uri, char *pin, -+ struct sshkey ***keyp, char ***labelsp, struct pkcs11_provider **providerp, -+ CK_ULONG user) -+{ -+ int nkeys; -+ int ret = -1; -+ struct pkcs11_provider *p = NULL; -+ CK_ULONG i; -+ CK_TOKEN_INFO *token; -+ char *provider_uri = NULL; -+ -+ if (providerp == NULL) -+ goto fail; -+ *providerp = NULL; -+ -+ if (keyp != NULL) -+ *keyp = NULL; -+ -+ if ((ret = pkcs11_initialize_provider(uri, &p)) != 0) { -+ goto fail; -+ } -+ -+ provider_uri = pkcs11_uri_get(uri); -+ if (pin == NULL && uri->pin != NULL) { -+ pin = uri->pin; -+ } -+ nkeys = 0; -+ for (i = 0; i < p->module->nslots; i++) { -+ token = &p->module->slotinfo[i].token; -+ if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { -+ debug2_f("ignoring uninitialised token in " -+ "provider %s slot %lu", provider_uri, (u_long)i); -+ continue; -+ } -+ if (uri->token != NULL && -+ strncmp(token->label, uri->token, 32) != 0) { -+ debug2_f("ignoring token not matching label (%.32s) " -+ "specified by PKCS#11 URI in slot %lu", -+ token->label, (unsigned long)i); -+ continue; -+ } -+ if (uri->manuf != NULL && -+ strncmp(token->manufacturerID, uri->manuf, 32) != 0) { -+ debug2_f("ignoring token not matching requrested " -+ "manufacturerID (%.32s) specified by PKCS#11 URI in " -+ "slot %lu", token->manufacturerID, (unsigned long)i); -+ continue; -+ } -+ if (uri->serial != NULL && -+ strncmp(token->serialNumber, uri->serial, 16) != 0) { -+ debug2_f("ignoring token not matching requrested " -+ "serialNumber (%s) specified by PKCS#11 URI in " -+ "slot %lu", token->serialNumber, (unsigned long)i); -+ continue; -+ } -+ debug("provider %s slot %lu: label <%.32s> manufacturerID <%.32s> " -+ "model <%.16s> serial <%.16s> flags 0x%lx", -+ provider_uri, (unsigned long)i, -+ token->label, token->manufacturerID, token->model, -+ token->serialNumber, token->flags); - /* -- * open session, login with pin and retrieve public -- * keys (if keyp is provided) -+ * open session if not yet opened, login with pin and -+ * retrieve public keys (if keyp is provided) - */ -- if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || -+ if ((p->module->slotinfo[i].session != 0 || -+ (ret = pkcs11_open_session(p, i, pin, user)) != 0) && /* ??? */ - keyp == NULL) - continue; -- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); -- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); -- if (nkeys == 0 && !p->slotinfo[i].logged_in && -+ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); -+ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); -+ if (nkeys == 0 && !p->module->slotinfo[i].logged_in && - pkcs11_interactive) { - /* - * Some tokens require login before they will - * expose keys. - */ -- if (pkcs11_login_slot(p, &p->slotinfo[i], -+ debug3_f("Trying to login as there were no keys found"); -+ if (pkcs11_login_slot(p, &p->module->slotinfo[i], - CKU_USER) < 0) { - error("login failed"); - continue; - } -- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); -- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); -+ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); -+ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); -+ } -+ if (nkeys == 0 && uri->object != NULL) { -+ debug3_f("No keys found. Retrying without label (%.32s) ", -+ uri->object); -+ /* Try once more without the label filter */ -+ char *label = uri->object; -+ uri->object = NULL; /* XXX clone uri? */ -+ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); -+ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); -+ uri->object = label; - } - } -+ pin = NULL; /* Will be cleaned up with URI */ - - /* now owned by caller */ - *providerp = p; - -- TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -- p->refcount++; /* add to provider list */ -- -+ free(provider_uri); - return (nkeys); - fail: -- if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) -- error("C_Finalize for provider %s failed: %lu", -- provider_id, rv); - if (p) { -- free(p->name); -- free(p->slotlist); -- free(p->slotinfo); -- free(p); -+ TAILQ_REMOVE(&pkcs11_providers, p, next); -+ pkcs11_provider_unref(p); - } -- if (handle) -- dlclose(handle); - if (ret > 0) - ret = -1; - return (ret); - } - --/* -- * register a new provider and get number of keys hold by the token, -- * fails if provider already exists -- */ -+static int -+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; -+ -+ 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) { -@@ -1685,7 +2019,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-9.6p1/ssh-pkcs11.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11.h ---- openssh-9.6p1/ssh-pkcs11.h.pkcs11-uri 2023-12-18 15:59:50.000000000 +0100 -+++ openssh-9.6p1/ssh-pkcs11.h 2024-01-12 14:25:25.235942385 +0100 -@@ -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-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri.c ---- openssh-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri 2024-01-12 14:25:25.235942385 +0100 -+++ openssh-9.6p1/ssh-pkcs11-uri.c 2024-01-12 14:25:25.235942385 +0100 +diff --git a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c +new file mode 100644 +index 00000000..8bd97e9e +--- /dev/null ++++ b/ssh-pkcs11-uri.c @@ -0,0 +1,437 @@ +/* + * Copyright (c) 2017 Red Hat @@ -3081,9 +1661,11 @@ diff -up openssh-9.6p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri. +} + +#endif /* ENABLE_PKCS11 */ -diff -up openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri.h ---- openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri 2024-01-12 14:25:25.235942385 +0100 -+++ openssh-9.6p1/ssh-pkcs11-uri.h 2024-01-12 14:25:25.235942385 +0100 +diff --git a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h +new file mode 100644 +index 00000000..29e9f732 +--- /dev/null ++++ b/ssh-pkcs11-uri.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017 Red Hat @@ -3128,3 +1710,1473 @@ diff -up openssh-9.6p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-9.6p1/ssh-pkcs11-uri. +struct pkcs11_uri *pkcs11_uri_init(); +char *pkcs11_uri_get(struct pkcs11_uri *uri); + +diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c +index 31b9360f..b96f5b89 100644 +--- a/ssh-pkcs11.c ++++ b/ssh-pkcs11.c +@@ -38,6 +38,7 @@ + #include + #include + #include ++#include + + #define CRYPTOKI_COMPAT + #include "pkcs11.h" +@@ -55,8 +56,8 @@ struct pkcs11_slotinfo { + int logged_in; + }; + +-struct pkcs11_provider { +- char *name; ++struct pkcs11_module { ++ char *module_path; + void *handle; + CK_FUNCTION_LIST *function_list; + CK_INFO info; +@@ -65,6 +66,13 @@ struct pkcs11_provider { + struct pkcs11_slotinfo *slotinfo; + int valid; + int refcount; ++}; ++ ++struct pkcs11_provider { ++ char *name; ++ struct pkcs11_module *module; /* can be shared between various providers */ ++ int refcount; ++ int valid; + TAILQ_ENTRY(pkcs11_provider) next; + }; + +@@ -75,6 +83,7 @@ struct pkcs11_key { + CK_ULONG slotidx; + char *keyid; + int keyid_len; ++ char *label; + }; + + int pkcs11_interactive = 0; +@@ -106,26 +115,61 @@ pkcs11_init(int interactive) + * this is called when a provider gets unregistered. + */ + static void +-pkcs11_provider_finalize(struct pkcs11_provider *p) ++pkcs11_module_finalize(struct pkcs11_module *m) + { + CK_RV rv; + CK_ULONG i; + +- debug_f("provider \"%s\" refcount %d valid %d", +- p->name, p->refcount, p->valid); +- if (!p->valid) ++ debug_f("%p refcount %d valid %d", m, m->refcount, m->valid); ++ if (!m->valid) + return; +- for (i = 0; i < p->nslots; i++) { +- if (p->slotinfo[i].session && +- (rv = p->function_list->C_CloseSession( +- p->slotinfo[i].session)) != CKR_OK) ++ for (i = 0; i < m->nslots; i++) { ++ if (m->slotinfo[i].session && ++ (rv = m->function_list->C_CloseSession( ++ m->slotinfo[i].session)) != CKR_OK) + error("C_CloseSession failed: %lu", rv); + } +- if ((rv = p->function_list->C_Finalize(NULL)) != CKR_OK) ++ if ((rv = m->function_list->C_Finalize(NULL)) != CKR_OK) + error("C_Finalize failed: %lu", rv); ++ m->valid = 0; ++ m->function_list = NULL; ++ dlclose(m->handle); ++} ++ ++/* ++ * remove a reference to the pkcs11 module. ++ * called when a provider is unregistered. ++ */ ++static void ++pkcs11_module_unref(struct pkcs11_module *m) ++{ ++ debug_f("%p refcount %d", m, m->refcount); ++ if (--m->refcount <= 0) { ++ pkcs11_module_finalize(m); ++ if (m->valid) ++ error_f("%p still valid", m); ++ free(m->slotlist); ++ free(m->slotinfo); ++ free(m->module_path); ++ free(m); ++ } ++} ++ ++/* ++ * finalize a provider shared library, it's no longer usable. ++ * however, there might still be keys referencing this provider, ++ * so the actual freeing of memory is handled by pkcs11_provider_unref(). ++ * this is called when a provider gets unregistered. ++ */ ++static void ++pkcs11_provider_finalize(struct pkcs11_provider *p) ++{ ++ debug_f("%p refcount %d valid %d", p, p->refcount, p->valid); ++ if (!p->valid) ++ return; ++ pkcs11_module_unref(p->module); ++ p->module = NULL; + p->valid = 0; +- p->function_list = NULL; +- dlclose(p->handle); + } + + /* +@@ -137,11 +181,9 @@ pkcs11_provider_unref(struct pkcs11_provider *p) + { + debug_f("provider \"%s\" refcount %d", p->name, p->refcount); + if (--p->refcount <= 0) { +- if (p->valid) +- error_f("provider \"%s\" still valid", p->name); + free(p->name); +- free(p->slotlist); +- free(p->slotinfo); ++ if (p->module) ++ pkcs11_module_unref(p->module); + free(p); + } + } +@@ -159,6 +201,20 @@ pkcs11_terminate(void) + } + } + ++/* lookup provider by module path */ ++static struct pkcs11_module * ++pkcs11_provider_lookup_module(char *module_path) ++{ ++ struct pkcs11_provider *p; ++ ++ TAILQ_FOREACH(p, &pkcs11_providers, next) { ++ debug("check %p %s (%s)", p, p->name, p->module->module_path); ++ if (!strcmp(module_path, p->module->module_path)) ++ return (p->module); ++ } ++ return (NULL); ++} ++ + /* lookup provider by name */ + static struct pkcs11_provider * + pkcs11_provider_lookup(char *provider_id) +@@ -173,19 +229,55 @@ pkcs11_provider_lookup(char *provider_id) + return (NULL); + } + ++int pkcs11_del_provider_by_uri(struct pkcs11_uri *); ++ + /* unregister provider by name */ + int + pkcs11_del_provider(char *provider_id) ++{ ++ int rv; ++ struct pkcs11_uri *uri; ++ ++ debug_f("called, provider_id = %s", provider_id); ++ ++ if (provider_id == NULL) ++ return 0; ++ ++ 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); ++ } ++ ++ rv = pkcs11_del_provider_by_uri(uri); ++ pkcs11_uri_cleanup(uri); ++ return rv; ++} ++ ++/* 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); + +- if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { ++ debug3_f("called with provider %s", provider_uri); ++ ++ if ((p = pkcs11_provider_lookup(provider_uri)) != NULL) { + TAILQ_REMOVE(&pkcs11_providers, p, next); + pkcs11_provider_finalize(p); + pkcs11_provider_unref(p); +- return (0); ++ rv = 0; + } +- return (-1); ++ free(provider_uri); ++ return rv; + } + + static RSA_METHOD *rsa_method; +@@ -195,6 +287,60 @@ static EC_KEY_METHOD *ec_key_method; + static int ec_key_idx = 0; + #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + ++/* ++ * This can't be in the ssh-pkcs11-uri, becase we can not depend on ++ * PKCS#11 structures in ssh-agent (using client-helper communication) ++ */ ++int ++pkcs11_uri_write(const struct sshkey *key, FILE *f) ++{ ++ char *p = NULL; ++ struct pkcs11_uri uri; ++ struct pkcs11_key *k11; ++ ++ /* sanity - is it a RSA key with associated app_data? */ ++ switch (key->type) { ++ case KEY_RSA: { ++ const RSA *rsa = EVP_PKEY_get0_RSA(key->pkey); ++ k11 = RSA_get_ex_data(rsa, rsa_idx); ++ break; ++ } ++#ifdef HAVE_EC_KEY_METHOD_NEW ++ case KEY_ECDSA: { ++ const EC_KEY * ecdsa = EVP_PKEY_get0_EC_KEY(key->pkey); ++ k11 = EC_KEY_get_ex_data(ecdsa, ec_key_idx); ++ break; ++ } ++#endif ++ default: ++ error("Unknown key type %d", key->type); ++ return -1; ++ } ++ if (k11 == NULL) { ++ error("Failed to get ex_data for key type %d", key->type); ++ return (-1); ++ } ++ ++ /* omit type -- we are looking for private-public or private-certificate pairs */ ++ uri.id = k11->keyid; ++ uri.id_len = k11->keyid_len; ++ uri.token = k11->provider->module->slotinfo[k11->slotidx].token.label; ++ uri.object = k11->label; ++ uri.module_path = k11->provider->module->module_path; ++ uri.lib_manuf = k11->provider->module->info.manufacturerID; ++ uri.manuf = k11->provider->module->slotinfo[k11->slotidx].token.manufacturerID; ++ uri.serial = k11->provider->module->slotinfo[k11->slotidx].token.serialNumber; ++ ++ p = pkcs11_uri_get(&uri); ++ /* do not cleanup -- we do not allocate here, only reference */ ++ if (p == NULL) ++ return -1; ++ ++ fprintf(f, " %s", p); ++ free(p); ++ return 0; ++} ++ + /* release a wrapped object */ + static void + pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, +@@ -208,6 +354,7 @@ pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, + if (k11->provider) + pkcs11_provider_unref(k11->provider); + free(k11->keyid); ++ free(k11->label); + free(k11); + } + +@@ -222,8 +369,8 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, + CK_RV rv; + int ret = -1; + +- f = p->function_list; +- session = p->slotinfo[slotidx].session; ++ f = p->module->function_list; ++ session = p->module->slotinfo[slotidx].session; + if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { + error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); + return (-1); +@@ -260,14 +407,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, + if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + verbose("Deferring PIN entry to reader keypad."); + else { +- snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", ++ snprintf(prompt, sizeof(prompt), "Enter PIN for '%.32s': ", + si->token.label); +- if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) { ++ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF|RP_ALLOW_STDIN)) == NULL) { + debug_f("no pin specified"); + return (-1); /* bail out */ + } + } +- rv = provider->function_list->C_Login(si->session, type, (u_char *)pin, ++ rv = provider->module->function_list->C_Login(si->session, type, (u_char *)pin, + (pin != NULL) ? strlen(pin) : 0); + if (pin != NULL) + freezero(pin, strlen(pin)); +@@ -297,13 +444,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, + static int + pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) + { +- if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) { ++ if (k11 == NULL || k11->provider == NULL || !k11->provider->valid || ++ k11->provider->module == NULL || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + + return pkcs11_login_slot(k11->provider, +- &k11->provider->slotinfo[k11->slotidx], type); ++ &k11->provider->module->slotinfo[k11->slotidx], type); + } + + +@@ -319,13 +467,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, + + *val = 0; + +- if (!k11->provider || !k11->provider->valid) { ++ if (!k11->provider || !k11->provider->valid || ++ !k11->provider->module || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + attr.type = type; + attr.pValue = &flag; +@@ -356,13 +505,14 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) + int always_auth = 0; + int did_login = 0; + +- if (!k11->provider || !k11->provider->valid) { ++ if (!k11->provider || !k11->provider->valid || ++ !k11->provider->module || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { + if (pkcs11_login(k11, CKU_USER) < 0) { +@@ -439,8 +589,8 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + tlen = RSA_size(rsa); + + /* XXX handle CKR_BUFFER_TOO_SMALL */ +@@ -484,7 +634,7 @@ pkcs11_rsa_start_wrapper(void) + /* redirect private key operations for rsa key to pkcs11 token */ + static int + pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, +- CK_ATTRIBUTE *keyid_attrib, RSA *rsa) ++ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, RSA *rsa) + { + struct pkcs11_key *k11; + +@@ -502,6 +652,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, + 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); ++ k11->label[label_attrib->ulValueLen] = 0; ++ } ++ + if (RSA_set_method(rsa, rsa_method) != 1) + fatal_f("RSA_set_method failed"); + if (RSA_set_ex_data(rsa, rsa_idx, k11) != 1) +@@ -534,8 +690,8 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, + return (NULL); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + siglen = ECDSA_size(ec); + sig = xmalloc(siglen); +@@ -600,7 +756,7 @@ pkcs11_ecdsa_start_wrapper(void) + + static int + pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, +- CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) ++ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ec) + { + struct pkcs11_key *k11; + +@@ -617,6 +773,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, + 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); ++ k11->label[label_attrib->ulValueLen] = 0; ++ } ++ + if (EC_KEY_set_method(ec, ec_key_method) != 1) + fatal_f("EC_KEY_set_method failed"); + if (EC_KEY_set_ex_data(ec, ec_key_idx, k11) != 1) +@@ -626,7 +788,8 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, + } + #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + +-/* remove trailing spaces */ ++/* remove trailing spaces. Note, that this does NOT guarantee the buffer ++ * will be null terminated if there are no trailing spaces! */ + static char * + rmspace(u_char *buf, size_t len) + { +@@ -658,8 +821,8 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, + CK_SESSION_HANDLE session; + int login_required, ret; + +- f = p->function_list; +- si = &p->slotinfo[slotidx]; ++ f = p->module->function_list; ++ si = &p->module->slotinfo[slotidx]; + + login_required = si->token.flags & CKF_LOGIN_REQUIRED; + +@@ -669,9 +832,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, + error("pin required"); + return (-SSH_PKCS11_ERR_PIN_REQUIRED); + } +- if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| ++ if ((rv = f->C_OpenSession(p->module->slotlist[slotidx], CKF_RW_SESSION| + CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { +- error("C_OpenSession failed: %lu", rv); ++ error("C_OpenSession failed for slot %lu: %lu", slotidx, rv); + return (-1); + } + if (login_required && pin != NULL && strlen(pin) != 0) { +@@ -707,7 +870,8 @@ static struct sshkey * + pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) + { +- CK_ATTRIBUTE key_attr[3]; ++ CK_ATTRIBUTE key_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -721,14 +885,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; +- key_attr[1].type = CKA_EC_POINT; +- key_attr[2].type = CKA_EC_PARAMS; ++ key_attr[1].type = CKA_LABEL; ++ key_attr[2].type = CKA_EC_POINT; ++ key_attr[3].type = CKA_EC_PARAMS; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); +@@ -739,19 +904,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * ensure that none of the others are zero length. + * XXX assumes CKA_ID is always first. + */ +- if (key_attr[1].ulValueLen == 0 || +- key_attr[2].ulValueLen == 0) { ++ if (key_attr[2].ulValueLen == 0 || ++ key_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (key_attr[i].ulValueLen > 0) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + + /* retrieve ID, public point and curve parameters of EC key */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; +@@ -763,8 +928,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto fail; + } + +- attrp = key_attr[2].pValue; +- group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); ++ attrp = key_attr[3].pValue; ++ group = d2i_ECPKParameters(NULL, &attrp, key_attr[3].ulValueLen); + if (group == NULL) { + ossl_error("d2i_ECPKParameters failed"); + goto fail; +@@ -775,13 +940,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto fail; + } + +- if (key_attr[1].ulValueLen <= 2) { ++ if (key_attr[2].ulValueLen <= 2) { + error("CKA_EC_POINT too small"); + goto fail; + } + +- attrp = key_attr[1].pValue; +- octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen); ++ attrp = key_attr[2].pValue; ++ octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[2].ulValueLen); + if (octet == NULL) { + ossl_error("d2i_ASN1_OCTET_STRING failed"); + goto fail; +@@ -798,7 +963,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto fail; + } + +- if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) ++ if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], ec)) + goto fail; + + key = sshkey_new(KEY_UNSPEC); +@@ -817,7 +982,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + key->flags |= SSHKEY_FLAG_EXT; + + fail: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(key_attr[i].pValue); + if (ec) + EC_KEY_free(ec); +@@ -834,7 +999,8 @@ static struct sshkey * + pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) + { +- CK_ATTRIBUTE key_attr[3]; ++ CK_ATTRIBUTE key_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -845,14 +1011,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; +- key_attr[1].type = CKA_MODULUS; +- key_attr[2].type = CKA_PUBLIC_EXPONENT; ++ key_attr[1].type = CKA_LABEL; ++ key_attr[2].type = CKA_MODULUS; ++ key_attr[3].type = CKA_PUBLIC_EXPONENT; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); +@@ -863,19 +1030,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * ensure that none of the others are zero length. + * XXX assumes CKA_ID is always first. + */ +- if (key_attr[1].ulValueLen == 0 || +- key_attr[2].ulValueLen == 0) { ++ if (key_attr[2].ulValueLen == 0 || ++ key_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (key_attr[i].ulValueLen > 0) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + + /* retrieve ID, modulus and public exponent of RSA key */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; +@@ -887,8 +1054,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto fail; + } + +- rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); +- rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); ++ rsa_n = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); ++ rsa_e = BN_bin2bn(key_attr[3].pValue, key_attr[3].ulValueLen, NULL); + if (rsa_n == NULL || rsa_e == NULL) { + error("BN_bin2bn failed"); + goto fail; +@@ -897,7 +1064,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + fatal_f("set key"); + rsa_n = rsa_e = NULL; /* transferred */ + +- if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) ++ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], rsa)) + goto fail; + + key = sshkey_new(KEY_UNSPEC); +@@ -915,7 +1082,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + key->flags |= SSHKEY_FLAG_EXT; + + fail: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(key_attr[i].pValue); + RSA_free(rsa); + +@@ -926,7 +1093,8 @@ static int + pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) + { +- CK_ATTRIBUTE cert_attr[3]; ++ CK_ATTRIBUTE cert_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -950,14 +1118,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + + memset(&cert_attr, 0, sizeof(cert_attr)); + cert_attr[0].type = CKA_ID; +- cert_attr[1].type = CKA_SUBJECT; +- cert_attr[2].type = CKA_VALUE; ++ cert_attr[1].type = CKA_LABEL; ++ cert_attr[2].type = CKA_SUBJECT; ++ cert_attr[3].type = CKA_VALUE; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return -1; +@@ -969,18 +1138,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * XXX assumes CKA_ID is always first. + */ + if (cert_attr[1].ulValueLen == 0 || +- cert_attr[2].ulValueLen == 0) { ++ cert_attr[2].ulValueLen == 0 || ++ cert_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return -1; + } + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (cert_attr[i].ulValueLen > 0) + cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); + + /* retrieve ID, subject and value of certificate */ +- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto out; +@@ -994,8 +1164,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + subject = xstrdup("invalid subject"); + X509_NAME_free(x509_name); + +- cp = cert_attr[2].pValue; +- if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) { ++ cp = cert_attr[3].pValue; ++ if ((x509 = d2i_X509(NULL, &cp, cert_attr[3].ulValueLen)) == NULL) { + error("d2i_x509 failed"); + goto out; + } +@@ -1015,7 +1185,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto out; + } + +- if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) ++ if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], rsa)) + goto out; + + key = sshkey_new(KEY_UNSPEC); +@@ -1048,7 +1218,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto out; + } + +- if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) ++ if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], ec)) + goto out; + + key = sshkey_new(KEY_UNSPEC); +@@ -1071,7 +1241,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto out; + } + out: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(cert_attr[i].pValue); + X509_free(x509); + RSA_free(rsa); +@@ -1122,11 +1292,12 @@ note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, + */ + static int + pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, +- struct sshkey ***keysp, char ***labelsp, int *nkeys) ++ struct sshkey ***keysp, char ***labelsp, int *nkeys, struct pkcs11_uri *uri) + { + struct sshkey *key = NULL; + CK_OBJECT_CLASS key_class; +- CK_ATTRIBUTE key_attr[1]; ++ CK_ATTRIBUTE key_attr[3]; ++ int nattr = 1; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -1143,10 +1314,23 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, + key_attr[0].pValue = &key_class; + key_attr[0].ulValueLen = sizeof(key_class); + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ if (uri->id != NULL) { ++ key_attr[nattr].type = CKA_ID; ++ key_attr[nattr].pValue = uri->id; ++ key_attr[nattr].ulValueLen = uri->id_len; ++ nattr++; ++ } ++ if (uri->object != NULL) { ++ key_attr[nattr].type = CKA_LABEL; ++ key_attr[nattr].pValue = uri->object; ++ key_attr[nattr].ulValueLen = strlen(uri->object); ++ nattr++; ++ } ++ ++ 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; +@@ -1227,11 +1411,12 @@ fail: + */ + static int + pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, +- struct sshkey ***keysp, char ***labelsp, int *nkeys) ++ struct sshkey ***keysp, char ***labelsp, int *nkeys, struct pkcs11_uri *uri) + { + struct sshkey *key = NULL; + CK_OBJECT_CLASS key_class; +- CK_ATTRIBUTE key_attr[2]; ++ CK_ATTRIBUTE key_attr[3]; ++ int nattr = 1; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -1247,10 +1432,23 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, + key_attr[0].pValue = &key_class; + key_attr[0].ulValueLen = sizeof(key_class); + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ if (uri->id != NULL) { ++ key_attr[nattr].type = CKA_ID; ++ key_attr[nattr].pValue = uri->id; ++ key_attr[nattr].ulValueLen = uri->id_len; ++ nattr++; ++ } ++ if (uri->object != NULL) { ++ key_attr[nattr].type = CKA_LABEL; ++ key_attr[nattr].pValue = uri->object; ++ key_attr[nattr].ulValueLen = strlen(uri->object); ++ nattr++; ++ } ++ ++ 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; +@@ -1532,16 +1730,10 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, + } + #endif /* WITH_PKCS11_KEYGEN */ + +-/* +- * register a new provider, fails if provider already exists. if +- * keyp is provided, fetch keys. +- */ + static int +-pkcs11_register_provider(char *provider_id, char *pin, +- struct sshkey ***keyp, char ***labelsp, +- struct pkcs11_provider **providerp, CK_ULONG user) ++pkcs11_initialize_provider(struct pkcs11_uri *uri, struct pkcs11_provider **providerp) + { +- int nkeys, need_finalize = 0; ++ int need_finalize = 0; + int ret = -1; + struct pkcs11_provider *p = NULL; + void *handle = NULL; +@@ -1550,162 +1742,309 @@ pkcs11_register_provider(char *provider_id, char *pin, + CK_FUNCTION_LIST *f = NULL; + CK_TOKEN_INFO *token; + CK_ULONG i; ++ char *provider_module = NULL; ++ struct pkcs11_module *m = NULL; ++ ++ /* if no provider specified, fallback to p11-kit */ ++ if (uri->module_path == NULL) { ++#ifdef PKCS11_DEFAULT_PROVIDER ++ provider_module = strdup(PKCS11_DEFAULT_PROVIDER); ++#else ++ error_f("No module path provided"); ++ goto fail; ++#endif ++ } else { ++ provider_module = strdup(uri->module_path); ++ } ++ p = xcalloc(1, sizeof(*p)); ++ p->name = pkcs11_uri_get(uri); + +- if (providerp == NULL) +- goto fail; +- *providerp = NULL; +- +- if (keyp != NULL) +- *keyp = NULL; +- if (labelsp != NULL) +- *labelsp = NULL; +- +- if (pkcs11_provider_lookup(provider_id) != NULL) { +- debug_f("provider already registered: %s", provider_id); ++ if (lib_contains_symbol(provider_module, "C_GetFunctionList") != 0) { ++ error("provider %s is not a PKCS11 library", provider_module); + goto fail; + } +- if (lib_contains_symbol(provider_id, "C_GetFunctionList") != 0) { +- error("provider %s is not a PKCS11 library", provider_id); +- goto fail; ++ if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL ++ && m->valid) { ++ debug_f("provider module already initialized: %s", provider_module); ++ free(provider_module); ++ /* Skip the initialization of PKCS#11 module */ ++ m->refcount++; ++ p->module = m; ++ p->valid = 1; ++ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); ++ p->refcount++; /* add to provider list */ ++ *providerp = p; ++ return 0; ++ } else { ++ m = xcalloc(1, sizeof(*m)); ++ p->module = m; ++ m->refcount++; + } ++ + /* open shared pkcs11-library */ +- if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { +- error("dlopen %s failed: %s", provider_id, dlerror()); ++ if ((handle = dlopen(provider_module, RTLD_NOW)) == NULL) { ++ error("dlopen %s failed: %s", provider_module, dlerror()); + goto fail; + } + if ((getfunctionlist = dlsym(handle, "C_GetFunctionList")) == NULL) + fatal("dlsym(C_GetFunctionList) failed: %s", dlerror()); +- p = xcalloc(1, sizeof(*p)); +- p->name = xstrdup(provider_id); +- p->handle = handle; ++ p->module->handle = handle; + /* setup the pkcs11 callbacks */ + if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { + error("C_GetFunctionList for provider %s failed: %lu", +- provider_id, rv); ++ provider_module, rv); + goto fail; + } +- p->function_list = f; ++ m->function_list = f; + if ((rv = f->C_Initialize(NULL)) != CKR_OK) { + error("C_Initialize for provider %s failed: %lu", +- provider_id, rv); ++ provider_module, rv); + goto fail; + } + need_finalize = 1; +- if ((rv = f->C_GetInfo(&p->info)) != CKR_OK) { ++ if ((rv = f->C_GetInfo(&m->info)) != CKR_OK) { + error("C_GetInfo for provider %s failed: %lu", +- provider_id, rv); ++ provider_module, rv); ++ goto fail; ++ } ++ rmspace(m->info.manufacturerID, sizeof(m->info.manufacturerID)); ++ if (uri->lib_manuf != NULL && ++ strncmp(uri->lib_manuf, m->info.manufacturerID, 32)) { ++ debug_f("Skipping provider %s not matching library_manufacturer", ++ m->info.manufacturerID); + goto fail; + } +- debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" +- " libraryDescription <%.*s> libraryVersion %d.%d", +- provider_id, +- RMSPACE(p->info.manufacturerID), +- p->info.cryptokiVersion.major, +- p->info.cryptokiVersion.minor, +- RMSPACE(p->info.libraryDescription), +- p->info.libraryVersion.major, +- p->info.libraryVersion.minor); +- if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { ++ rmspace(m->info.libraryDescription, sizeof(m->info.libraryDescription)); ++ debug("provider %s: manufacturerID <%.32s> cryptokiVersion %d.%d" ++ " libraryDescription <%.32s> libraryVersion %d.%d", ++ provider_module, ++ m->info.manufacturerID, ++ m->info.cryptokiVersion.major, ++ m->info.cryptokiVersion.minor, ++ m->info.libraryDescription, ++ m->info.libraryVersion.major, ++ m->info.libraryVersion.minor); ++ ++ if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &m->nslots)) != CKR_OK) { + error("C_GetSlotList failed: %lu", rv); + goto fail; + } +- if (p->nslots == 0) { +- debug_f("provider %s returned no slots", provider_id); ++ if (m->nslots == 0) { ++ debug_f("provider %s returned no slots", provider_module); + ret = -SSH_PKCS11_ERR_NO_SLOTS; + goto fail; + } +- p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); +- if ((rv = f->C_GetSlotList(CK_TRUE, p->slotlist, &p->nslots)) ++ m->slotlist = xcalloc(m->nslots, sizeof(CK_SLOT_ID)); ++ if ((rv = f->C_GetSlotList(CK_TRUE, m->slotlist, &m->nslots)) + != CKR_OK) { + error("C_GetSlotList for provider %s failed: %lu", +- provider_id, rv); ++ provider_module, rv); + goto fail; + } +- p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); ++ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); + p->valid = 1; +- nkeys = 0; +- for (i = 0; i < p->nslots; i++) { +- token = &p->slotinfo[i].token; +- if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) ++ m->valid = 1; ++ for (i = 0; i < m->nslots; i++) { ++ token = &m->slotinfo[i].token; ++ if ((rv = f->C_GetTokenInfo(m->slotlist[i], token)) + != CKR_OK) { + error("C_GetTokenInfo for provider %s slot %lu " +- "failed: %lu", provider_id, (u_long)i, rv); +- continue; +- } +- if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { +- debug2_f("ignoring uninitialised token in " +- "provider %s slot %lu", provider_id, (u_long)i); ++ "failed: %lu", provider_module, (u_long)i, rv); ++ token->flags = 0; + continue; + } + debug("provider %s slot %lu: label <%.*s> " + "manufacturerID <%.*s> model <%.*s> serial <%.*s> " + "flags 0x%lx", +- provider_id, (unsigned long)i, ++ provider_module, (unsigned long)i, + RMSPACE(token->label), RMSPACE(token->manufacturerID), + RMSPACE(token->model), RMSPACE(token->serialNumber), + token->flags); ++ } ++ m->module_path = provider_module; ++ provider_module = NULL; ++ ++ /* now owned by caller */ ++ *providerp = p; ++ ++ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); ++ p->refcount++; /* add to provider list */ ++ ++ return 0; ++fail: ++ if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) ++ error("C_Finalize for provider %s failed: %lu", ++ provider_module, rv); ++ free(provider_module); ++ if (m) { ++ free(m->slotlist); ++ free(m); ++ } ++ if (p) { ++ free(p->name); ++ free(p); ++ } ++ if (handle) ++ dlclose(handle); ++ return (ret); ++} ++ ++/* ++ * register a new provider, fails if provider already exists. if ++ * keyp is provided, fetch keys. ++ */ ++static int ++pkcs11_register_provider_by_uri(struct pkcs11_uri *uri, char *pin, ++ struct sshkey ***keyp, char ***labelsp, struct pkcs11_provider **providerp, ++ CK_ULONG user) ++{ ++ int nkeys; ++ int ret = -1; ++ struct pkcs11_provider *p = NULL; ++ CK_ULONG i; ++ CK_TOKEN_INFO *token; ++ char *provider_uri = NULL; ++ ++ if (providerp == NULL) ++ goto fail; ++ *providerp = NULL; ++ ++ if (keyp != NULL) ++ *keyp = NULL; ++ ++ if ((ret = pkcs11_initialize_provider(uri, &p)) != 0) { ++ goto fail; ++ } ++ ++ provider_uri = pkcs11_uri_get(uri); ++ if (pin == NULL && uri->pin != NULL) { ++ pin = uri->pin; ++ } ++ nkeys = 0; ++ for (i = 0; i < p->module->nslots; i++) { ++ token = &p->module->slotinfo[i].token; ++ if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { ++ debug2_f("ignoring uninitialised token in " ++ "provider %s slot %lu", provider_uri, (u_long)i); ++ continue; ++ } ++ if (uri->token != NULL && ++ strncmp(token->label, uri->token, 32) != 0) { ++ debug2_f("ignoring token not matching label (%.32s) " ++ "specified by PKCS#11 URI in slot %lu", ++ token->label, (unsigned long)i); ++ continue; ++ } ++ if (uri->manuf != NULL && ++ strncmp(token->manufacturerID, uri->manuf, 32) != 0) { ++ debug2_f("ignoring token not matching requrested " ++ "manufacturerID (%.32s) specified by PKCS#11 URI in " ++ "slot %lu", token->manufacturerID, (unsigned long)i); ++ continue; ++ } ++ if (uri->serial != NULL && ++ strncmp(token->serialNumber, uri->serial, 16) != 0) { ++ debug2_f("ignoring token not matching requrested " ++ "serialNumber (%s) specified by PKCS#11 URI in " ++ "slot %lu", token->serialNumber, (unsigned long)i); ++ continue; ++ } ++ debug("provider %s slot %lu: label <%.32s> manufacturerID <%.32s> " ++ "model <%.16s> serial <%.16s> flags 0x%lx", ++ provider_uri, (unsigned long)i, ++ token->label, token->manufacturerID, token->model, ++ token->serialNumber, token->flags); + /* +- * open session, login with pin and retrieve public +- * keys (if keyp is provided) ++ * open session if not yet opened, login with pin and ++ * retrieve public keys (if keyp is provided) + */ +- if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || ++ if ((p->module->slotinfo[i].session != 0 || ++ (ret = pkcs11_open_session(p, i, pin, user)) != 0) && /* ??? */ + keyp == NULL) + continue; +- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); +- if (nkeys == 0 && !p->slotinfo[i].logged_in && ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ if (nkeys == 0 && !p->module->slotinfo[i].logged_in && + pkcs11_interactive) { + /* + * Some tokens require login before they will + * expose keys. + */ +- if (pkcs11_login_slot(p, &p->slotinfo[i], ++ debug3_f("Trying to login as there were no keys found"); ++ if (pkcs11_login_slot(p, &p->module->slotinfo[i], + CKU_USER) < 0) { + error("login failed"); + continue; + } +- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ } ++ if (nkeys == 0 && uri->object != NULL) { ++ debug3_f("No keys found. Retrying without label (%.32s) ", ++ uri->object); ++ /* Try once more without the label filter */ ++ char *label = uri->object; ++ uri->object = NULL; /* XXX clone uri? */ ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ uri->object = label; + } + } ++ pin = NULL; /* Will be cleaned up with URI */ + + /* now owned by caller */ + *providerp = p; + +- TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); +- p->refcount++; /* add to provider list */ +- ++ free(provider_uri); + return (nkeys); + fail: +- if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) +- error("C_Finalize for provider %s failed: %lu", +- provider_id, rv); + if (p) { +- free(p->name); +- free(p->slotlist); +- free(p->slotinfo); +- free(p); ++ TAILQ_REMOVE(&pkcs11_providers, p, next); ++ pkcs11_provider_unref(p); + } +- if (handle) +- dlclose(handle); + if (ret > 0) + ret = -1; + return (ret); + } + +-/* +- * register a new provider and get number of keys hold by the token, +- * fails if provider already exists +- */ ++static int ++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; ++ ++ 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) { +@@ -1714,7 +2053,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); ++ ++ 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 --git a/ssh-pkcs11.h b/ssh-pkcs11.h +index 52602231..9ce20c1f 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" ++ + 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 c23d3b9e..98b103c9 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -890,6 +890,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; ++ } ++#endif + p = tilde_expand_filename(optarg, getuid()); + if (stat(p, &st) == -1) + fprintf(stderr, "Warning: Identity file %s " +@@ -1847,6 +1855,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); +@@ -2370,6 +2379,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; ++ ++ debug("identity file '%s' from pkcs#11", pkcs11_uri); ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); ++ ++ if (pkcs11_uri_parse(pkcs11_uri, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri); ++ ++ /* we need to merge URI and provider together */ ++ if (options.pkcs11_provider != NULL && uri->module_path == NULL) ++ uri->module_path = strdup(options.pkcs11_provider); ++ ++ 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); ++ } ++ ++ pkcs11_uri_cleanup(uri); ++} ++#endif /* ENABLE_PKCS11 */ ++ + /* Loads all IdentityFile and CertificateFile keys */ + static void + load_public_identity_files(const struct ssh_conn_info *cinfo) +@@ -2384,11 +2432,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)); +@@ -2401,33 +2444,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); ++ ++ if (options.pkcs11_provider != NULL) { ++ struct pkcs11_uri *uri; ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); ++ ++ /* Construct simple PKCS#11 URI to simplify access */ ++ uri->module_path = strdup(options.pkcs11_provider); ++ ++ /* Add it as any other IdentityFile */ ++ cp = pkcs11_uri_get(uri); ++ add_identity_file(&options, NULL, cp, 1); ++ free(cp); ++ ++ 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 3a8e246c..8d5d0722 100644 +--- a/ssh_config.5 ++++ b/ssh_config.5 +@@ -1263,6 +1263,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.49.0 + diff --git a/openssh-7.8p1-scp-ipv6.patch b/0029-openssh-7.8p1-scp-ipv6.patch similarity index 51% rename from openssh-7.8p1-scp-ipv6.patch rename to 0029-openssh-7.8p1-scp-ipv6.patch index 8ae0948..dbd69aa 100644 --- a/openssh-7.8p1-scp-ipv6.patch +++ b/0029-openssh-7.8p1-scp-ipv6.patch @@ -1,8 +1,17 @@ +From 507e6f245557ae7261806f7ecbd40697cb0dd389 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 29/50] openssh-7.8p1-scp-ipv6 + +--- + scp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + diff --git a/scp.c b/scp.c -index 60682c68..9344806e 100644 +index 9554b188..7f9795a5 100644 --- a/scp.c +++ b/scp.c -@@ -714,7 +714,9 @@ toremote(int argc, char **argv) +@@ -1183,7 +1183,9 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) addargs(&alist, "%s", host); addargs(&alist, "%s", cmd); addargs(&alist, "%s", src); @@ -13,4 +22,6 @@ index 60682c68..9344806e 100644 tuser ? tuser : "", tuser ? "@" : "", thost, targ); if (do_local_cmd(&alist) != 0) +-- +2.49.0 diff --git a/openssh-8.0p1-crypto-policies.patch b/0030-openssh-8.0p1-crypto-policies.patch similarity index 90% rename from openssh-8.0p1-crypto-policies.patch rename to 0030-openssh-8.0p1-crypto-policies.patch index a666c5c..498e3f5 100644 --- a/openssh-8.0p1-crypto-policies.patch +++ b/0030-openssh-8.0p1-crypto-policies.patch @@ -1,7 +1,18 @@ -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 @@ +From b436140fe3abd9f97f01f9af9f5da5cf6c5d7725 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 30/50] openssh-8.0p1-crypto-policies + +--- + ssh_config.5 | 164 ++++++++++++++++++++------------------------- + sshd_config.5 | 179 +++++++++++++++++++------------------------------- + 2 files changed, 140 insertions(+), 203 deletions(-) + +diff --git a/ssh_config.5 b/ssh_config.5 +index 8d5d0722..a43b2a27 100644 +--- a/ssh_config.5 ++++ b/ssh_config.5 +@@ -438,17 +438,13 @@ A single argument of causes no CNAMEs to be considered for canonicalization. This is the default behaviour. .It Cm CASignatureAlgorithms @@ -24,7 +35,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set -@@ -450,20 +446,25 @@ +@@ -587,20 +583,25 @@ If the option is set to (the default), the check will not be executed. .It Cm Ciphers @@ -54,21 +65,21 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Pp The supported ciphers are: .Bd -literal -offset indent -@@ -479,13 +480,6 @@ +@@ -616,13 +617,6 @@ aes256-gcm@openssh.com chacha20-poly1305@openssh.com .Ed .Pp -The default is: -.Bd -literal -offset indent -chacha20-poly1305@openssh.com, --aes128-ctr,aes192-ctr,aes256-ctr, --aes128-gcm@openssh.com,aes256-gcm@openssh.com +-aes128-gcm@openssh.com,aes256-gcm@openssh.com, +-aes128-ctr,aes192-ctr,aes256-ctr -.Ed -.Pp The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClearAllForwardings -@@ -885,6 +879,11 @@ +@@ -1022,6 +1016,11 @@ command line will be passed untouched to the GSSAPI library. The default is .Dq no . .It Cm GSSAPIKexAlgorithms @@ -80,7 +91,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x The list of key exchange algorithms that are offered for GSSAPI key exchange. Possible values are .Bd -literal -offset 3n -@@ -897,10 +896,8 @@ +@@ -1034,10 +1033,8 @@ gss-nistp256-sha256-, gss-curve25519-sha256- .Ed .Pp @@ -92,7 +103,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .It Cm HashKnownHosts Indicates that .Xr ssh 1 -@@ -919,36 +916,25 @@ +@@ -1056,36 +1053,25 @@ will not be converted automatically, but may be manually hashed using .Xr ssh-keygen 1 . .It Cm HostbasedAcceptedAlgorithms @@ -137,7 +148,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Pp The .Fl Q -@@ -1001,6 +987,17 @@ +@@ -1138,6 +1124,17 @@ to prefer their algorithms. .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . @@ -155,7 +166,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key -@@ -1330,6 +1330,11 @@ it may be zero or more of: +@@ -1376,6 +1373,11 @@ it may be zero or more of: and .Cm pam . .It Cm KexAlgorithms @@ -167,7 +178,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x Specifies the permitted KEX (Key Exchange) algorithms that will be used and their preference order. The selected algorithm will be the first algorithm in this list that -@@ -1338,29 +1343,17 @@ Multiple algorithms must be comma-separa +@@ -1384,29 +1386,17 @@ Multiple algorithms must be comma-separated. .Pp If the specified list begins with a .Sq + @@ -187,8 +198,8 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x -.Pp -The default is: -.Bd -literal -offset indent --sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, -mlkem768x25519-sha256, +-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, -curve25519-sha256,curve25519-sha256@libssh.org, -ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, -diffie-hellman-group-exchange-sha256, @@ -201,7 +212,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x The list of supported key exchange algorithms may also be obtained using .Qq ssh -Q kex . .It Cm KnownHostsCommand -@@ -1365,37 +1357,33 @@ +@@ -1522,37 +1512,33 @@ function, and all code in the file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs @@ -248,7 +259,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm NoHostAuthenticationForLocalhost -@@ -1567,39 +1555,31 @@ +@@ -1741,39 +1727,31 @@ instead of continuing to execute and pass data. The default is .Cm no . .It Cm PubkeyAcceptedAlgorithms @@ -300,7 +311,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .It Cm PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be -@@ -2265,7 +2245,9 @@ +@@ -2497,7 +2475,9 @@ for those users who do not have a configuration file. This file must be world-readable. .El .Sh SEE ALSO @@ -311,10 +322,11 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Sh AUTHORS .An -nosplit OpenSSH is a derivative of the original and free -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 @@ +diff --git a/sshd_config.5 b/sshd_config.5 +index 26fcdc84..583a01cd 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -379,17 +379,13 @@ If the argument is then no banner is displayed. By default, no banner is displayed. .It Cm CASignatureAlgorithms @@ -337,7 +349,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set -@@ -525,20 +521,25 @@ +@@ -533,20 +529,25 @@ The default is indicating not to .Xr chroot 2 . .It Cm Ciphers @@ -367,21 +379,21 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Pp The supported ciphers are: .Pp -@@ -565,13 +566,6 @@ +@@ -573,13 +574,6 @@ aes256-gcm@openssh.com chacha20-poly1305@openssh.com .El .Pp -The default is: -.Bd -literal -offset indent -chacha20-poly1305@openssh.com, --aes128-ctr,aes192-ctr,aes256-ctr, --aes128-gcm@openssh.com,aes256-gcm@openssh.com +-aes128-gcm@openssh.com,aes256-gcm@openssh.com, +-aes128-ctr,aes192-ctr,aes256-ctr -.Ed -.Pp The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClientAliveCountMax -@@ -766,53 +760,43 @@ +@@ -774,53 +768,43 @@ For this to work .Cm GSSAPIKeyExchange needs to be enabled in the server and also used by the client. .It Cm GSSAPIKexAlgorithms @@ -454,7 +466,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q HostbasedAcceptedAlgorithms . -@@ -879,25 +863,14 @@ +@@ -887,25 +871,14 @@ is specified, the location of the socket will be read from the .Ev SSH_AUTH_SOCK environment variable. .It Cm HostKeyAlgorithms @@ -485,7 +497,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts -@@ -1025,6 +1025,11 @@ Specifies whether to look at .k5login fi +@@ -1052,6 +1025,11 @@ Specifies whether to look at .k5login file for user's aliases. The default is .Cm yes . .It Cm KexAlgorithms @@ -497,7 +509,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x Specifies the permitted KEX (Key Exchange) algorithms that the server will offer to clients. The ordering of this list is not important, as the client specifies the -@@ -1033,16 +1038,16 @@ Multiple algorithms must be comma-separa +@@ -1060,16 +1038,16 @@ Multiple algorithms must be comma-separated. .Pp If the specified list begins with a .Sq + @@ -518,25 +530,22 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Pp The supported algorithms are: .Pp -@@ -1075,17 +1080,6 @@ ecdh-sha2-nistp521 +@@ -1106,14 +1084,6 @@ sntrup761x25519-sha512 sntrup761x25519-sha512@openssh.com .El .Pp -The default is: -.Bd -literal -offset indent --sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, -mlkem768x25519-sha256, +-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com, -curve25519-sha256,curve25519-sha256@libssh.org, --ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, --diffie-hellman-group-exchange-sha256, --diffie-hellman-group16-sha512,diffie-hellman-group18-sha512, --diffie-hellman-group14-sha256 +-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521 -.Ed -.Pp The list of supported key exchange algorithms may also be obtained using .Qq ssh -Q KexAlgorithms . .It Cm ListenAddress -@@ -1184,21 +1152,26 @@ +@@ -1200,21 +1170,26 @@ function, and all code in the file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs @@ -567,7 +576,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Pp The algorithms that contain .Qq -etm -@@ -1241,15 +1214,6 @@ +@@ -1257,15 +1232,6 @@ umac-64-etm@openssh.com umac-128-etm@openssh.com .El .Pp @@ -583,7 +592,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm Match -@@ -1633,36 +1597,25 @@ +@@ -1753,36 +1719,25 @@ or equivalent.) The default is .Cm yes . .It Cm PubkeyAcceptedAlgorithms @@ -629,7 +638,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . -@@ -2131,7 +2084,9 @@ +@@ -2289,7 +2244,9 @@ This file should be writable by root only, but it is recommended .El .Sh SEE ALSO .Xr sftp-server 8 , @@ -640,3 +649,6 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x .Sh AUTHORS .An -nosplit OpenSSH is a derivative of the original and free +-- +2.49.0 + diff --git a/openssh-8.0p1-openssl-kdf.patch b/0031-openssh-8.0p1-openssl-kdf.patch similarity index 84% rename from openssh-8.0p1-openssl-kdf.patch rename to 0031-openssh-8.0p1-openssl-kdf.patch index c22b210..529940f 100644 --- a/openssh-8.0p1-openssl-kdf.patch +++ b/0031-openssh-8.0p1-openssl-kdf.patch @@ -1,14 +1,18 @@ -commit 2c3ef499bfffce3cfd315edeebf202850ba4e00a -Author: Jakub Jelen -Date: Tue Apr 16 15:35:18 2019 +0200 +From 430bd33963725beb8ec01a1e581529ae6bf6bec0 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 31/50] openssh-8.0p1-openssl-kdf - Use the new OpenSSL KDF +--- + configure.ac | 1 + + kex.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 108 insertions(+) diff --git a/configure.ac b/configure.ac -index 2a455e4e..e01c3d43 100644 +index d9bd2f51..d92a8580 100644 --- a/configure.ac +++ b/configure.ac -@@ -2712,6 +2712,7 @@ if test "x$openssl" = "xyes" ; then +@@ -3137,6 +3137,7 @@ if test "x$openssl" = "xyes" ; then HMAC_CTX_init \ RSA_generate_key_ex \ RSA_get_default_method \ @@ -17,10 +21,10 @@ index 2a455e4e..e01c3d43 100644 # OpenSSL_add_all_algorithms may be a macro. diff --git a/kex.c b/kex.c -index b6f041f4..1fbce2bb 100644 +index 19a56e8e..8b200ff4 100644 --- a/kex.c +++ b/kex.c -@@ -38,6 +38,11 @@ +@@ -40,6 +40,11 @@ #ifdef WITH_OPENSSL #include #include @@ -32,7 +36,7 @@ index b6f041f4..1fbce2bb 100644 #endif #include "ssh.h" -@@ -942,6 +945,107 @@ kex_choose_conf(struct ssh *ssh) +@@ -1078,6 +1083,107 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) return r; } @@ -140,7 +144,7 @@ index b6f041f4..1fbce2bb 100644 static int derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, const struct sshbuf *shared_secret, u_char **keyp) -@@ -1004,6 +1096,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, +@@ -1141,6 +1247,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, ssh_digest_free(hashctx); return r; } @@ -148,4 +152,6 @@ index b6f041f4..1fbce2bb 100644 #define NKEYS 6 int +-- +2.49.0 diff --git a/openssh-8.2p1-visibility.patch b/0032-openssh-8.2p1-visibility.patch similarity index 62% rename from openssh-8.2p1-visibility.patch rename to 0032-openssh-8.2p1-visibility.patch index 89c35ef..c67373c 100644 --- a/openssh-8.2p1-visibility.patch +++ b/0032-openssh-8.2p1-visibility.patch @@ -1,8 +1,17 @@ +From 6aa231d9acfeca870ee87e3bf9c4a1239518706d Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 32/50] openssh-8.2p1-visibility + +--- + regress/misc/sk-dummy/sk-dummy.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c -index dca158de..afdcb1d2 100644 +index 347b2122..344f8a8a 100644 --- a/regress/misc/sk-dummy/sk-dummy.c +++ b/regress/misc/sk-dummy/sk-dummy.c -@@ -71,7 +71,7 @@ skdebug(const char *func, const char *fmt, ...) +@@ -81,7 +81,7 @@ skdebug(const char *func, const char *fmt, ...) #endif } @@ -11,7 +20,7 @@ index dca158de..afdcb1d2 100644 sk_api_version(void) { return SSH_SK_VERSION_MAJOR; -@@ -220,7 +220,7 @@ check_options(struct sk_option **options) +@@ -230,7 +230,7 @@ check_options(struct sk_option **options) return 0; } @@ -20,7 +29,7 @@ index dca158de..afdcb1d2 100644 sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, const char *application, uint8_t flags, const char *pin, struct sk_option **options, struct sk_enroll_response **enroll_response) -@@ -467,7 +467,7 @@ sig_ed25519(const uint8_t *message, size_t message_len, +@@ -478,7 +478,7 @@ sig_ed25519(const uint8_t *message, size_t message_len, return ret; } @@ -29,7 +38,7 @@ index dca158de..afdcb1d2 100644 sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, const char *application, const uint8_t *key_handle, size_t key_handle_len, uint8_t flags, const char *pin, struct sk_option **options, -@@ -518,7 +518,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len, +@@ -535,7 +535,7 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, return ret; } @@ -38,3 +47,6 @@ index dca158de..afdcb1d2 100644 sk_load_resident_keys(const char *pin, struct sk_option **options, struct sk_resident_key ***rks, size_t *nrks) { +-- +2.49.0 + diff --git a/openssh-8.2p1-x11-without-ipv6.patch b/0033-openssh-8.2p1-x11-without-ipv6.patch similarity index 55% rename from openssh-8.2p1-x11-without-ipv6.patch rename to 0033-openssh-8.2p1-x11-without-ipv6.patch index 8b83bc3..32a9056 100644 --- a/openssh-8.2p1-x11-without-ipv6.patch +++ b/0033-openssh-8.2p1-x11-without-ipv6.patch @@ -1,12 +1,17 @@ +From cfe5a99d335eb57b8c08b4eb6b4535dd042d96e3 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:28 +0200 +Subject: [PATCH 33/50] openssh-8.2p1-x11-without-ipv6 + +--- + channels.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + diff --git a/channels.c b/channels.c +index 7438c1a5..95836d50 100644 --- a/channels.c +++ b/channels.c -@@ -3933,16 +3933,26 @@ x11_create_display_inet(int x11_display_ - if (ai->ai_family == AF_INET6) - sock_set_v6only(sock); - if (x11_use_localhost) - set_reuseaddr(sock); - if (bind(sock, ai->ai_addr, ai->ai_addrlen) == -1) { +@@ -5055,6 +5055,16 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, debug2_f("bind port %d: %.100s", port, strerror(errno)); close(sock); @@ -23,8 +28,6 @@ diff --git a/channels.c b/channels.c for (n = 0; n < num_socks; n++) close(socks[n]); num_socks = 0; - break; - } - socks[num_socks++] = sock; - if (num_socks == NUM_SOCKS) - break; +-- +2.49.0 + diff --git a/openssh-8.0p1-preserve-pam-errors.patch b/0034-openssh-8.0p1-preserve-pam-errors.patch similarity index 67% rename from openssh-8.0p1-preserve-pam-errors.patch rename to 0034-openssh-8.0p1-preserve-pam-errors.patch index b7ab965..15e59c2 100644 --- a/openssh-8.0p1-preserve-pam-errors.patch +++ b/0034-openssh-8.0p1-preserve-pam-errors.patch @@ -1,7 +1,17 @@ -diff -up openssh-8.0p1/auth-pam.c.preserve-pam-errors openssh-8.0p1/auth-pam.c ---- openssh-8.0p1/auth-pam.c.preserve-pam-errors 2021-03-31 17:03:15.618592347 +0200 -+++ openssh-8.0p1/auth-pam.c 2021-03-31 17:06:58.115220014 +0200 -@@ -511,7 +511,11 @@ sshpam_thread(void *ctxtp) +From 8de0391e3b3eb75e23ee9f173f04a9c78f2b96c9 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 34/50] openssh-8.0p1-preserve-pam-errors + +--- + auth-pam.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/auth-pam.c b/auth-pam.c +index b4100ea1..a042c3c8 100644 +--- a/auth-pam.c ++++ b/auth-pam.c +@@ -523,7 +523,11 @@ sshpam_thread(void *ctxtp) goto auth_fail; if (!do_pam_account()) { @@ -14,7 +24,7 @@ diff -up openssh-8.0p1/auth-pam.c.preserve-pam-errors openssh-8.0p1/auth-pam.c goto auth_fail; } if (sshpam_authctxt->force_pwchange) { -@@ -568,8 +572,10 @@ sshpam_thread(void *ctxtp) +@@ -580,8 +584,10 @@ sshpam_thread(void *ctxtp) pam_strerror(sshpam_handle, sshpam_err))) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* XXX - can't do much about an error here */ @@ -27,17 +37,20 @@ diff -up openssh-8.0p1/auth-pam.c.preserve-pam-errors openssh-8.0p1/auth-pam.c else if (sshpam_maxtries_reached) ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer); else -@@ -856,9 +862,11 @@ sshpam_query(void *ctx, char **name, cha +@@ -890,9 +896,11 @@ sshpam_query(void *ctx, char **name, char **info, free(msg); break; case PAM_ACCT_EXPIRED: + sshpam_account_status = 0; + /* FALLTHROUGH */ case PAM_MAXTRIES: -+ case PAM_USER_UNKNOWN: -+ case PAM_PERM_DENIED: - if (type == PAM_ACCT_EXPIRED) - sshpam_account_status = 0; ++ case PAM_USER_UNKNOWN: ++ case PAM_PERM_DENIED: if (type == PAM_MAXTRIES) sshpam_set_maxtries_reached(1); /* FALLTHROUGH */ +-- +2.49.0 + diff --git a/openssh-8.7p1-scp-kill-switch.patch b/0035-openssh-8.7p1-scp-kill-switch.patch similarity index 57% rename from openssh-8.7p1-scp-kill-switch.patch rename to 0035-openssh-8.7p1-scp-kill-switch.patch index 161ab2d..58a5036 100644 --- a/openssh-8.7p1-scp-kill-switch.patch +++ b/0035-openssh-8.7p1-scp-kill-switch.patch @@ -1,6 +1,18 @@ -diff -up openssh-8.7p1/pathnames.h.kill-scp openssh-8.7p1/pathnames.h ---- openssh-8.7p1/pathnames.h.kill-scp 2021-09-16 11:37:57.240171687 +0200 -+++ openssh-8.7p1/pathnames.h 2021-09-16 11:42:29.183427917 +0200 +From a68f3741fdc01bf6823a69d2442caba7de9835f9 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 35/50] openssh-8.7p1-scp-kill-switch + +--- + pathnames.h | 1 + + scp.1 | 7 +++++++ + scp.c | 8 ++++++++ + 3 files changed, 16 insertions(+) + +diff --git a/pathnames.h b/pathnames.h +index 1158bec9..43f0c570 100644 +--- a/pathnames.h ++++ b/pathnames.h @@ -42,6 +42,7 @@ #define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key" #define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" @@ -9,10 +21,11 @@ diff -up openssh-8.7p1/pathnames.h.kill-scp openssh-8.7p1/pathnames.h #ifndef _PATH_SSH_PROGRAM #define _PATH_SSH_PROGRAM "/usr/bin/ssh" -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 +diff --git a/scp.1 b/scp.1 +index aa2e2d8b..373d7237 100644 +--- a/scp.1 ++++ b/scp.1 +@@ -331,6 +331,13 @@ during download or upload. By default a 32KB buffer is used. .El .El @@ -26,10 +39,11 @@ diff -up openssh-8.7p1/scp.1.kill-scp openssh-8.7p1/scp.1 .Sh EXIT STATUS .Ex -std scp .Sh SEE ALSO -diff -up openssh-8.7p1/scp.c.kill-scp openssh-8.7p1/scp.c ---- openssh-8.7p1/scp.c.kill-scp 2021-09-16 11:42:56.013650519 +0200 -+++ openssh-8.7p1/scp.c 2021-09-16 11:53:03.249713836 +0200 -@@ -596,6 +596,14 @@ main(int argc, char **argv) +diff --git a/scp.c b/scp.c +index 7f9795a5..7ed1a54c 100644 +--- a/scp.c ++++ b/scp.c +@@ -649,6 +649,14 @@ main(int argc, char **argv) if (iamremote) mode = MODE_SCP; @@ -44,3 +58,6 @@ diff -up openssh-8.7p1/scp.c.kill-scp openssh-8.7p1/scp.c if ((pwd = getpwuid(userid = getuid())) == NULL) fatal("unknown user %u", (u_int) userid); +-- +2.49.0 + diff --git a/openssh-8.7p1-recursive-scp.patch b/0036-openssh-8.7p1-recursive-scp.patch similarity index 73% rename from openssh-8.7p1-recursive-scp.patch rename to 0036-openssh-8.7p1-recursive-scp.patch index 17c340e..929b408 100644 --- a/openssh-8.7p1-recursive-scp.patch +++ b/0036-openssh-8.7p1-recursive-scp.patch @@ -1,8 +1,21 @@ -diff --git a/scp.c b/scp.c ---- a/scp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/scp.c (date 1703111453316) -@@ -1372,7 +1372,7 @@ +From 99e1e3af524376788e591ca73387f1ca37e6f5ef Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 36/50] openssh-8.7p1-recursive-scp +--- + scp.c | 2 +- + sftp-client.c | 60 +++++++++++++++++++++++++++++++++++++++------------ + sftp-client.h | 4 ++-- + sftp.c | 6 +++--- + 4 files changed, 52 insertions(+), 20 deletions(-) + +diff --git a/scp.c b/scp.c +index 7ed1a54c..0c87dd0e 100644 +--- a/scp.c ++++ b/scp.c +@@ -1388,7 +1388,7 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) + if (src_is_dir && iamrecursive) { if (sftp_upload_dir(conn, src, abs_dst, pflag, - SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { @@ -11,10 +24,11 @@ diff --git a/scp.c b/scp.c errs = 1; } diff --git a/sftp-client.c b/sftp-client.c ---- a/sftp-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/sftp-client.c (date 1703169614263) -@@ -1003,7 +1003,7 @@ - +index 9f8ab4af..873dec04 100644 +--- a/sftp-client.c ++++ b/sftp-client.c +@@ -1003,7 +1003,7 @@ sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, + /* Implements both the realpath and expand-path operations */ static char * -sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) @@ -22,7 +36,7 @@ diff --git a/sftp-client.c b/sftp-client.c { struct sshbuf *msg; u_int expected_id, count, id; -@@ -1049,11 +1049,43 @@ +@@ -1049,11 +1049,43 @@ sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); @@ -71,9 +85,9 @@ diff --git a/sftp-client.c b/sftp-client.c } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); -@@ -1078,9 +1110,9 @@ +@@ -1078,9 +1110,9 @@ sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) } - + char * -sftp_realpath(struct sftp_conn *conn, const char *path) +sftp_realpath(struct sftp_conn *conn, const char *path, int create_dir) @@ -81,9 +95,9 @@ diff --git a/sftp-client.c b/sftp-client.c - return sftp_realpath_expand(conn, path, 0); + return sftp_realpath_expand(conn, path, 0, create_dir); } - + int -@@ -1094,9 +1126,9 @@ +@@ -1094,9 +1126,9 @@ sftp_expand_path(struct sftp_conn *conn, const char *path) { if (!sftp_can_expand_path(conn)) { debug3_f("no server support, fallback to realpath"); @@ -93,18 +107,18 @@ diff --git a/sftp-client.c b/sftp-client.c - return sftp_realpath_expand(conn, path, 1); + return sftp_realpath_expand(conn, path, 1, 0); } - + int -@@ -2016,7 +2048,7 @@ +@@ -2016,7 +2048,7 @@ sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst, char *src_canon; int ret; - + - if ((src_canon = sftp_realpath(conn, src)) == NULL) { + if ((src_canon = sftp_realpath(conn, src, 0)) == NULL) { error("download \"%s\": path canonicalization failed", src); return -1; } -@@ -2365,12 +2397,12 @@ +@@ -2366,12 +2398,12 @@ upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, int sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int preserve_flag, int print_flag, int resume, int fsync_flag, @@ -113,47 +127,48 @@ diff --git a/sftp-client.c b/sftp-client.c { char *dst_canon; int ret; - + - if ((dst_canon = sftp_realpath(conn, dst)) == NULL) { + if ((dst_canon = sftp_realpath(conn, dst, create_dir)) == NULL) { error("upload \"%s\": path canonicalization failed", dst); return -1; } -@@ -2825,7 +2857,7 @@ +@@ -2826,7 +2858,7 @@ sftp_crossload_dir(struct sftp_conn *from, struct sftp_conn *to, char *from_path_canon; int ret; - + - if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) { + if ((from_path_canon = sftp_realpath(from, from_path, 0)) == NULL) { error("crossload \"%s\": path canonicalization failed", from_path); return -1; diff --git a/sftp-client.h b/sftp-client.h ---- a/sftp-client.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/sftp-client.h (date 1703111691284) -@@ -111,7 +111,7 @@ +index 74cdae7d..00ed6630 100644 +--- a/sftp-client.h ++++ b/sftp-client.h +@@ -111,7 +111,7 @@ int sftp_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); - + /* Canonicalise 'path' - caller must free result */ -char *sftp_realpath(struct sftp_conn *, const char *); +char *sftp_realpath(struct sftp_conn *, const char *, int); - + /* Canonicalisation with tilde expansion (requires server extension) */ char *sftp_expand_path(struct sftp_conn *, const char *); -@@ -163,7 +163,7 @@ +@@ -163,7 +163,7 @@ int sftp_upload(struct sftp_conn *, const char *, const char *, * times if 'pflag' is set */ int sftp_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 --git a/sftp.c b/sftp.c ---- a/sftp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/sftp.c (date 1703168795365) -@@ -807,7 +807,7 @@ +index bdedd141..322e6d1f 100644 +--- a/sftp.c ++++ b/sftp.c +@@ -809,7 +809,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, (rflag || global_rflag)) { if (sftp_upload_dir(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, 1, resume, @@ -162,7 +177,7 @@ diff --git a/sftp.c b/sftp.c err = -1; } else { if (sftp_upload(conn, g.gl_pathv[i], abs_dst, -@@ -1642,7 +1642,7 @@ +@@ -1644,7 +1644,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, if (path1 == NULL || *path1 == '\0') path1 = xstrdup(startdir); path1 = sftp_make_absolute(path1, *pwd); @@ -171,12 +186,15 @@ diff --git a/sftp.c b/sftp.c err = 1; break; } -@@ -2247,7 +2247,7 @@ +@@ -2249,7 +2249,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) } #endif /* USE_LIBEDIT */ - + - if ((remote_path = sftp_realpath(conn, ".")) == NULL) + if ((remote_path = sftp_realpath(conn, ".", 0)) == NULL) fatal("Need cwd"); startdir = xstrdup(remote_path); + +-- +2.49.0 diff --git a/openssh-8.7p1-minrsabits.patch b/0037-openssh-8.7p1-minrsabits.patch similarity index 63% rename from openssh-8.7p1-minrsabits.patch rename to 0037-openssh-8.7p1-minrsabits.patch index d8577d2..59e530b 100644 --- a/openssh-8.7p1-minrsabits.patch +++ b/0037-openssh-8.7p1-minrsabits.patch @@ -1,7 +1,18 @@ +From 286bc4a302b5130f732c857095ae665f7bea01dd Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 37/50] openssh-8.7p1-minrsabits + +--- + readconf.c | 1 + + servconf.c | 1 + + 2 files changed, 2 insertions(+) + diff --git a/readconf.c b/readconf.c ---- a/readconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/readconf.c (date 1703169891147) -@@ -326,6 +326,7 @@ +index 6c04ed43..f340bf50 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -343,6 +343,7 @@ static struct { { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, { "requiredrsasize", oRequiredRSASize }, @@ -10,9 +21,10 @@ diff --git a/readconf.c b/readconf.c { "obscurekeystroketiming", oObscureKeystrokeTiming }, { "channeltimeout", oChannelTimeout }, diff --git a/servconf.c b/servconf.c ---- a/servconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99) -+++ b/servconf.c (date 1703169891148) -@@ -691,6 +691,7 @@ +index 15c99b30..84891544 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -788,6 +788,7 @@ static struct { { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, @@ -20,3 +32,6 @@ diff --git a/servconf.c b/servconf.c { "channeltimeout", sChannelTimeout, SSHCFG_ALL }, { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, +-- +2.49.0 + diff --git a/0038-openssh-8.7p1-ibmca.patch b/0038-openssh-8.7p1-ibmca.patch new file mode 100644 index 0000000..74dd5b5 --- /dev/null +++ b/0038-openssh-8.7p1-ibmca.patch @@ -0,0 +1,25 @@ +From 26af04432f6404eb03780265a5cce948ecfec8dc Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 38/50] openssh-8.7p1-ibmca + +--- + openbsd-compat/bsd-closefrom.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c +index f6112458..417c2048 100644 +--- a/openbsd-compat/bsd-closefrom.c ++++ b/openbsd-compat/bsd-closefrom.c +@@ -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 +-- +2.49.0 + diff --git a/openssh-7.6p1-audit.patch b/0039-openssh-7.6p1-audit.patch similarity index 83% rename from openssh-7.6p1-audit.patch rename to 0039-openssh-7.6p1-audit.patch index 2c7ddc5..e4f89c7 100644 --- a/openssh-7.6p1-audit.patch +++ b/0039-openssh-7.6p1-audit.patch @@ -1,7 +1,57 @@ -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, +From b0505837bfa2dcdf07800634fa80c5cdb78799dc Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 39/50] openssh-7.6p1-audit + +--- + Makefile.in | 2 +- + audit-bsm.c | 45 ++++++- + audit-linux.c | 302 +++++++++++++++++++++++++++++++++++++++++++--- + audit.c | 129 ++++++++++++++++++-- + audit.h | 22 +++- + auditstub.c | 52 ++++++++ + auth.c | 3 - + auth.h | 4 + + 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 | 83 ++++++++++++- + session.h | 10 +- + sshd-session.c | 104 ++++++++++++++-- + sshd.c | 10 ++ + 27 files changed, 1258 insertions(+), 104 deletions(-) + create mode 100644 auditstub.c + +diff --git a/Makefile.in b/Makefile.in +index 6c417ef7..a2942392 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -119,7 +119,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kexsntrup761x25519.o kexmlkem768x25519.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 ccfcf6f7..a49abb92 100644 +--- a/audit-bsm.c ++++ b/audit-bsm.c +@@ -373,12 +373,25 @@ audit_connection_from(const char *host, int port) #endif } @@ -19,17 +69,16 @@ diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c /* not implemented */ } - void ++void +audit_count_session_open(void) +{ + /* not necessary */ +} + -+void + void audit_session_open(struct logininfo *li) { - /* not implemented */ -@@ -391,6 +404,12 @@ audit_session_close(struct logininfo *li +@@ -391,6 +404,12 @@ audit_session_close(struct logininfo *li) /* not implemented */ } @@ -42,7 +91,7 @@ diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c void audit_event(struct ssh *ssh, ssh_audit_event_t event) { -@@ -452,4 +471,28 @@ audit_event(struct ssh *ssh, ssh_audit_e +@@ -452,4 +471,28 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) debug("%s: unhandled event %d", __func__, event); } } @@ -71,234 +120,10 @@ diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c + /* not implemented */ +} #endif /* BSM */ -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) -+{ -+ mm_audit_unsupported_body(ssh, what); -+} -+ -+void -+audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) -+{ -+ mm_audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid()); -+} -+ -+void -+audit_session_key_free(struct ssh *ssh, int ctos) -+{ -+ mm_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 +diff --git a/audit-linux.c b/audit-linux.c +index 3fcbe5c5..d484b82b 100644 +--- a/audit-linux.c ++++ b/audit-linux.c @@ -33,27 +33,40 @@ #include "log.h" @@ -310,11 +135,10 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c +#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; @@ -348,7 +172,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c saved_errno = errno; close(audit_fd); -@@ -65,9 +78,96 @@ linux_audit_record_event(int uid, const +@@ -65,9 +78,96 @@ linux_audit_record_event(int uid, const char *username, const char *hostname, rc = 0; errno = saved_errno; @@ -446,7 +270,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c /* Below is the sshd audit API code */ void -@@ -76,49 +176,211 @@ audit_connection_from(const char *host, +@@ -76,49 +176,211 @@ audit_connection_from(const char *host, int port) /* not implemented */ } @@ -670,9 +494,238 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c + 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 +diff --git a/audit.c b/audit.c +index dd2f0355..d0433c3a 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) ++{ ++ mm_audit_unsupported_body(ssh, what); ++} ++ ++void ++audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) ++{ ++ mm_audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid()); ++} ++ ++void ++audit_session_key_free(struct ssh *ssh, int ctos) ++{ ++ mm_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); ++} ++ ++/* ++ * 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 --git a/audit.h b/audit.h +index 38cb5ad3..45d66ccf 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); ++ + 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 00000000..639a798d +--- /dev/null ++++ b/auditstub.c @@ -0,0 +1,52 @@ +/* $Id: auditstub.c,v 1.1 jfch Exp $ */ + @@ -726,23 +779,47 @@ diff -up openssh-8.6p1/auditstub.c.audit openssh-8.6p1/auditstub.c +audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) +{ +} -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(); +diff --git a/auth.c b/auth.c +index e4578169..e10e804f 100644 +--- a/auth.c ++++ b/auth.c +@@ -501,9 +501,6 @@ getpwnamallow(struct ssh *ssh, const char *user) + record_failed_login(ssh, user, + auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); + #endif -#ifdef SSH_AUDIT_EVENTS -- mm_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) +- 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 39163035..6be52d70 100644 +--- a/auth.h ++++ b/auth.h +@@ -215,6 +215,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 */ + int auth_activate_options(struct ssh *, struct sshauthopt *); +@@ -240,6 +242,8 @@ int auth_check_authkey_line(struct passwd *, struct sshkey *, + 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 --git a/auth2-hostbased.c b/auth2-hostbased.c +index a3be6e49..8cebaffd 100644 +--- a/auth2-hostbased.c ++++ b/auth2-hostbased.c +@@ -157,7 +157,7 @@ userauth_hostbased(struct ssh *ssh, const char *method) authenticated = 0; if (mm_hostbased_key_allowed(ssh, authctxt->pw, cuser, chost, key) && @@ -751,7 +828,7 @@ diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL) == 0) authenticated = 1; -@@ -175,6 +175,20 @@ done: +@@ -174,6 +174,20 @@ done: return authenticated; } @@ -772,10 +849,11 @@ diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c /* return 1 if given hostkey is allowed */ int hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, -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) +diff --git a/auth2-pubkey.c b/auth2-pubkey.c +index 0d5ae0df..99cb810f 100644 +--- a/auth2-pubkey.c ++++ b/auth2-pubkey.c +@@ -235,7 +235,7 @@ userauth_pubkey(struct ssh *ssh, const char *method) /* test for correct signature */ authenticated = 0; if (mm_user_key_allowed(ssh, pw, key, 1, &authopts) && @@ -784,7 +862,7 @@ diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c sshbuf_ptr(b), sshbuf_len(b), (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, ssh->compat, &sig_details) == 0) { -@@ -305,6 +305,20 @@ done: +@@ -328,6 +328,20 @@ done: return authenticated; } @@ -805,43 +883,24 @@ diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c static int match_principals_file(struct passwd *pw, char *file, struct sshkey_cert *cert, struct sshauthopt **authoptsp) -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 +diff --git a/auth2.c b/auth2.c +index 8ec41de2..4a8515ea 100644 +--- a/auth2.c ++++ b/auth2.c +@@ -310,9 +310,6 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) + 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 -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 */ - int auth_activate_options(struct ssh *, struct sshauthopt *); -@@ -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 +- mm_audit_event(ssh, SSH_INVALID_USER); +-#endif + } + #ifdef USE_PAM + if (options.use_pam) +diff --git a/cipher.c b/cipher.c +index 8a18da2d..57d55325 100644 +--- a/cipher.c ++++ b/cipher.c @@ -64,25 +64,6 @@ struct sshcipher_ctx { const struct sshcipher *cipher; }; @@ -868,7 +927,7 @@ diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c static const struct sshcipher ciphers[] = { #ifdef WITH_OPENSSL #ifndef OPENSSL_NO_DES -@@ -422,7 +403,7 @@ cipher_get_length(struct sshcipher_ctx * +@@ -420,7 +401,7 @@ cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, void cipher_free(struct sshcipher_ctx *cc) { @@ -877,9 +936,10 @@ diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c return; if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { chachapoly_free(cc->cp_ctx); -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 +diff --git a/cipher.h b/cipher.h +index 6533ff2b..2e05a021 100644 +--- a/cipher.h ++++ b/cipher.h @@ -47,7 +47,25 @@ #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 @@ -907,10 +967,11 @@ diff -up openssh-8.6p1/cipher.h.audit openssh-8.6p1/cipher.h struct sshcipher_ctx; const struct sshcipher *cipher_by_name(const char *); -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 @@ +diff --git a/kex.c b/kex.c +index 8b200ff4..62f607d6 100644 +--- a/kex.c ++++ b/kex.c +@@ -68,6 +68,7 @@ #include "sshbuf.h" #include "digest.h" #include "xmalloc.h" @@ -918,7 +979,7 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c /* prototype */ static int kex_choose_conf(struct ssh *, uint32_t seq); -@@ -816,12 +817,16 @@ kex_start_rekex(struct ssh *ssh) +@@ -821,12 +822,16 @@ kex_start_rekex(struct ssh *ssh) } static int @@ -937,7 +998,7 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c if ((enc->cipher = cipher_by_name(name)) == NULL) { error_f("unsupported cipher %s", name); free(name); -@@ -842,8 +847,12 @@ choose_mac(struct ssh *ssh, struct sshma +@@ -847,8 +852,12 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) { char *name = match_list(client, server, NULL); @@ -951,7 +1012,7 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c if (mac_setup(mac, name) < 0) { error_f("unsupported MAC %s", name); free(name); -@@ -856,12 +865,16 @@ choose_mac(struct ssh *ssh, struct sshma +@@ -861,12 +870,16 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) } static int @@ -970,7 +1031,7 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c #ifdef WITH_ZLIB if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; -@@ -1002,7 +1015,7 @@ kex_choose_conf(struct ssh *ssh) +@@ -1030,7 +1043,7 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) 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; @@ -979,7 +1040,7 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c sprop[nenc])) != 0) { kex->failed_choice = peer[nenc]; peer[nenc] = NULL; -@@ -1017,7 +1030,7 @@ kex_choose_conf(struct ssh *ssh) +@@ -1045,7 +1058,7 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) peer[nmac] = NULL; goto out; } @@ -988,7 +1049,7 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c sprop[ncomp])) != 0) { kex->failed_choice = peer[ncomp]; peer[ncomp] = NULL; -@@ -1040,6 +1053,10 @@ kex_choose_conf(struct ssh *ssh) +@@ -1068,6 +1081,10 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) 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); @@ -999,7 +1060,7 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c } /* XXX need runden? */ kex->we_need = need; -@@ -1297,6 +1314,36 @@ dump_digest(const char *msg, const u_cha +@@ -1337,6 +1354,36 @@ dump_digest(const char *msg, const u_char *digest, int len) } #endif @@ -1036,10 +1097,11 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c /* * Send a plaintext error message to the peer, suffixed by \r\n. * Only used during banner exchange, and there only for the server. -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 *); +diff --git a/kex.h b/kex.h +index 0e080ea3..6a55aadf 100644 +--- a/kex.h ++++ b/kex.h +@@ -255,6 +255,8 @@ int kexgss_client(struct ssh *); int kexgss_server(struct ssh *); #endif @@ -1048,9 +1110,10 @@ diff -up openssh-8.6p1/kex.h.audit openssh-8.6p1/kex.h int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); -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 +diff --git a/mac.c b/mac.c +index f3dda669..bf051baa 100644 +--- a/mac.c ++++ b/mac.c @@ -239,6 +239,20 @@ mac_clear(struct sshmac *mac) mac->umac_ctx = NULL; } @@ -1072,31 +1135,21 @@ diff -up openssh-8.6p1/mac.c.audit openssh-8.6p1/mac.c /* XXX copied from ciphers_valid */ #define MAC_SEP "," 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 +diff --git a/mac.h b/mac.h +index 0b119d7a..5fb593b9 100644 +--- a/mac.h ++++ b/mac.h +@@ -49,5 +49,6 @@ int mac_compute(struct sshmac *, u_int32_t, const u_char *, int, 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 -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 kexmlkem768x25519.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 +diff --git a/monitor.c b/monitor.c +index 43c10a4e..fbc35782 100644 +--- a/monitor.c ++++ b/monitor.c @@ -93,6 +93,7 @@ #include "compat.h" #include "ssh2.h" @@ -1105,8 +1158,8 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c #include "match.h" #include "ssherr.h" #include "sk-api.h" -@@ -107,6 +108,8 @@ extern u_int utmp_len; - extern struct sshbuf *loginmsg; +@@ -110,6 +111,8 @@ extern struct sshbuf *loginmsg; + extern struct include_list includes; extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ +extern void destroy_sensitive_data(struct ssh *); @@ -1114,7 +1167,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c /* State exported from the child */ static struct sshbuf *child_state; -@@ -157,6 +160,11 @@ int mm_answer_gss_updatecreds(struct ssh +@@ -154,6 +157,11 @@ int mm_answer_gss_updatecreds(struct ssh *, int, struct sshbuf *); #ifdef SSH_AUDIT_EVENTS int mm_answer_audit_event(struct ssh *, int, struct sshbuf *); int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); @@ -1126,7 +1179,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c #endif static Authctxt *authctxt; -@@ -215,6 +223,10 @@ struct mon_table mon_dispatch_proto20[] +@@ -214,6 +222,10 @@ struct mon_table mon_dispatch_proto20[] = { #endif #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, @@ -1137,7 +1190,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, -@@ -249,6 +261,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}, @@ -1149,7 +1202,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c #endif {0, 0, NULL} }; -@@ -1444,8 +1461,10 @@ mm_answer_keyverify(struct ssh *ssh, int +@@ -1569,8 +1586,10 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) int r, ret, req_presence = 0, req_verify = 0, valid_data = 0; int encoded_ret; struct sshkey_sig_details *sig_details = NULL; @@ -1161,7 +1214,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c (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) -@@ -1454,6 +1473,8 @@ mm_answer_keyverify(struct ssh *ssh, int +@@ -1579,6 +1598,8 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal_f("bad key, not previously allowed"); @@ -1170,7 +1223,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c /* Empty signature algorithm means NULL. */ if (*sigalg == '\0') { -@@ -1469,14 +1490,19 @@ mm_answer_keyverify(struct ssh *ssh, int +@@ -1594,14 +1615,19 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) case MM_USERKEY: valid_data = monitor_valid_userblob(ssh, data, datalen); auth_method = "publickey"; @@ -1190,16 +1243,16 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c break; } if (!valid_data) -@@ -1488,8 +1514,6 @@ mm_answer_keyverify(struct ssh *ssh, int +@@ -1613,8 +1639,6 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) 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", -@@ -1576,13 +1600,19 @@ mm_record_login(struct ssh *ssh, Session + debug3_f("%s %s signature using %s %s%s%s", auth_method, + sshkey_type(key), sigalg == NULL ? "default" : sigalg, + (ret == 0) ? "verified" : "unverified", +@@ -1702,13 +1726,19 @@ mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw) } static void @@ -1220,7 +1273,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c session_unused(s->self); } -@@ -1649,7 +1679,7 @@ mm_answer_pty(struct ssh *ssh, int sock, +@@ -1775,7 +1805,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) error: if (s != NULL) @@ -1229,7 +1282,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c if ((r = sshbuf_put_u32(m, 0)) != 0) fatal_fr(r, "assemble 0"); mm_request_send(sock, MONITOR_ANS_PTY, m); -@@ -1668,7 +1698,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, i +@@ -1794,7 +1824,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m) if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) fatal_fr(r, "parse tty"); if ((s = session_by_tty(tty)) != NULL) @@ -1238,7 +1291,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c sshbuf_reset(m); free(tty); return (0); -@@ -1690,6 +1720,8 @@ mm_answer_term(struct ssh *ssh, int sock +@@ -1816,6 +1846,8 @@ mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req) sshpam_cleanup(); #endif @@ -1247,7 +1300,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); -@@ -1736,12 +1768,47 @@ mm_answer_audit_command(struct ssh *ssh, +@@ -1862,12 +1894,47 @@ mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m) { char *cmd; int r; @@ -1296,7 +1349,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c free(cmd); return (0); } -@@ -1813,6 +1880,7 @@ monitor_apply_keystate(struct ssh *ssh, +@@ -1940,6 +2007,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) void mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { @@ -1304,7 +1357,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c debug3_f("Waiting for new keys"); if ((child_state = sshbuf_new()) == NULL) -@@ -1820,6 +1888,19 @@ mm_get_keystate(struct ssh *ssh, struct +@@ -1947,6 +2015,19 @@ mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, child_state); debug3_f("GOT new keys"); @@ -1324,7 +1377,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c } -@@ -2111,3 +2192,102 @@ mm_answer_gss_updatecreds(struct ssh *ss +@@ -2234,3 +2315,102 @@ mm_answer_gss_updatecreds(struct ssh *ssh, int socket, struct sshbuf *m) { #endif /* GSSAPI */ @@ -1427,10 +1480,11 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c + return 0; +} +#endif /* SSH_AUDIT_EVENTS */ -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 { +diff --git a/monitor.h b/monitor.h +index d4d631dd..2c64f07d 100644 +--- a/monitor.h ++++ b/monitor.h +@@ -66,7 +66,13 @@ enum monitor_reqtype { MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107, MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109, MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, @@ -1445,10 +1499,11 @@ diff -up openssh-8.6p1/monitor.h.audit openssh-8.6p1/monitor.h MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, -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 +diff --git a/monitor_wrap.c b/monitor_wrap.c +index b6e3b3f3..1a079c15 100644 +--- a/monitor_wrap.c ++++ b/monitor_wrap.c +@@ -567,7 +567,7 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, */ int @@ -1457,7 +1512,7 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c 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 *ke +@@ -583,7 +583,8 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, *sig_detailsp = NULL; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); @@ -1467,7 +1522,7 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c (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 *ke +@@ -616,6 +617,22 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, return 0; } @@ -1490,7 +1545,7 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c void mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { -@@ -921,11 +938,12 @@ mm_audit_event(struct ssh *ssh, ssh_audi +@@ -1032,11 +1049,12 @@ mm_audit_event(struct ssh *ssh, ssh_audit_event_t event) sshbuf_free(m); } @@ -1505,7 +1560,7 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c debug3("%s entering command %s", __func__, command); -@@ -935,6 +953,30 @@ mm_audit_run_command(const char *command +@@ -1046,6 +1064,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); @@ -1536,7 +1591,7 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c sshbuf_free(m); } #endif /* SSH_AUDIT_EVENTS */ -@@ -1095,3 +1137,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc +@@ -1294,3 +1336,83 @@ server_get_connection_info(struct ssh *ssh, int populate, int use_dns) return &ci; } @@ -1620,10 +1675,11 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c + sshbuf_free(m); +} +#endif /* SSH_AUDIT_EVENTS */ -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 +diff --git a/monitor_wrap.h b/monitor_wrap.h +index 672dce52..661ed63b 100644 +--- a/monitor_wrap.h ++++ b/monitor_wrap.h +@@ -58,7 +58,9 @@ int mm_user_key_allowed(struct ssh *ssh, struct passwd *, struct sshkey *, int, struct sshauthopt **); int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, const char *, struct sshkey *); @@ -1634,7 +1690,7 @@ diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); -@@ -86,7 +88,12 @@ void mm_sshpam_free_ctx(void *); +@@ -85,7 +87,12 @@ void mm_sshpam_free_ctx(void *); #ifdef SSH_AUDIT_EVENTS #include "audit.h" void mm_audit_event(struct ssh *, ssh_audit_event_t); @@ -1648,9 +1704,10 @@ diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h #endif struct Session; -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 +diff --git a/packet.c b/packet.c +index 9dea2cfc..344b5f54 100644 +--- a/packet.c ++++ b/packet.c @@ -81,6 +81,7 @@ #endif @@ -1659,7 +1716,7 @@ diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c #include "compat.h" #include "ssh2.h" #include "cipher.h" -@@ -506,6 +507,13 @@ ssh_packet_get_connection_out(struct ssh +@@ -506,6 +507,13 @@ ssh_packet_get_connection_out(struct ssh *ssh) return ssh->state->connection_out; } @@ -1673,7 +1730,7 @@ diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c /* * 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 *ss +@@ -675,22 +683,19 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) { struct session_state *state = ssh->state; u_int mode; @@ -1701,7 +1758,7 @@ diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c 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 *ss +@@ -726,8 +731,18 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) #endif /* WITH_ZLIB */ cipher_free(state->send_context); cipher_free(state->receive_context); @@ -1720,7 +1777,7 @@ diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c free(ssh->local_ipaddr); ssh->local_ipaddr = NULL; free(ssh->remote_ipaddr); -@@ -892,6 +907,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod +@@ -984,6 +999,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode) (unsigned long long)state->p_send.bytes, (unsigned long long)state->p_send.blocks); kex_free_newkeys(state->newkeys[mode]); @@ -1728,7 +1785,7 @@ diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c state->newkeys[mode] = NULL; } /* note that both bytes and the seqnr are not reset */ -@@ -2173,6 +2189,72 @@ ssh_packet_get_output(struct ssh *ssh) +@@ -2325,6 +2341,72 @@ ssh_packet_get_output(struct ssh *ssh) return (void *)ssh->state->output; } @@ -1801,19 +1858,21 @@ diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c /* Reset after_authentication and reset compression in post-auth privsep */ static int ssh_packet_set_postauth(struct ssh *ssh) -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 +diff --git a/packet.h b/packet.h +index 49bb87f0..44a39a9e 100644 +--- a/packet.h ++++ b/packet.h +@@ -223,4 +223,5 @@ const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); # undef EC_POINT #endif +void packet_destroy_all(struct ssh *, int, int); #endif /* PACKET_H */ -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; +diff --git a/session.c b/session.c +index 28bbb8a7..83fc9418 100644 +--- a/session.c ++++ b/session.c +@@ -145,7 +145,7 @@ extern char *__progname; extern int debug_flag; extern u_int utmp_len; extern int startup_pipe; @@ -1822,7 +1881,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; extern char *tun_fwd_ifnames; /* serverloop.c */ -@@ -644,6 +644,14 @@ do_exec_pty(struct ssh *ssh, Session *s, +@@ -653,6 +653,14 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) /* Parent. Close the slave side of the pseudo tty. */ close(ttyfd); @@ -1837,7 +1896,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c /* Enter interactive session. */ s->ptymaster = ptymaster; ssh_packet_set_interactive(ssh, 1, -@@ -736,15 +744,19 @@ do_exec(struct ssh *ssh, Session *s, con +@@ -745,15 +753,19 @@ do_exec(struct ssh *ssh, Session *s, const char *command) s->self); #ifdef SSH_AUDIT_EVENTS @@ -1859,11 +1918,10 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); -@@ -1550,8 +1562,11 @@ do_child(struct ssh *ssh, Session *s, co +@@ -1538,7 +1550,11 @@ do_child(struct ssh *ssh, Session *s, const char *command) sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); - /* remove hostkey from the child's memory */ -- destroy_sensitive_data(); + /* remove keys from memory */ + destroy_sensitive_data(ssh); ssh_packet_clear_keys(ssh); + /* Don't audit this - both us and the parent would be talking to the @@ -1872,7 +1930,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c /* Force a password change */ if (s->authctxt->force_pwchange) { -@@ -1763,6 +1778,9 @@ session_unused(int id) +@@ -1750,6 +1766,9 @@ session_unused(int id) sessions[id].ttyfd = -1; sessions[id].ptymaster = -1; sessions[id].x11_chanids = NULL; @@ -1882,10 +1940,11 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c sessions[id].next_unused = sessions_first_unused; sessions_first_unused = id; } -@@ -1843,6 +1861,19 @@ session_open(Authctxt *authctxt, int cha +@@ -1828,6 +1847,19 @@ session_open(Authctxt *authctxt, int chanid) + return 1; } - Session * ++Session * +session_by_id(int id) +{ + if (id >= 0 && id < sessions_nalloc) { @@ -1898,11 +1957,10 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c + return NULL; +} + -+Session * + Session * session_by_tty(char *tty) { - int i; -@@ -2450,6 +2481,32 @@ session_exit_message(struct ssh *ssh, Se +@@ -2445,6 +2477,32 @@ session_exit_message(struct ssh *ssh, Session *s, int status) chan_write_failed(ssh, c); } @@ -1935,7 +1993,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c void session_close(struct ssh *ssh, Session *s) { -@@ -2463,6 +2520,10 @@ session_close(struct ssh *ssh, Session * +@@ -2458,6 +2516,10 @@ session_close(struct ssh *ssh, Session *s) if (s->ttyfd != -1) session_pty_cleanup(s); @@ -1946,7 +2004,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c free(s->term); free(s->display); free(s->x11_chanids); -@@ -2537,14 +2598,14 @@ session_close_by_channel(struct ssh *ssh +@@ -2534,14 +2596,14 @@ session_close_by_channel(struct ssh *ssh, int id, int force, void *arg) } void @@ -1963,7 +2021,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c else session_close(ssh, s); } -@@ -2671,6 +2732,15 @@ do_authenticated2(struct ssh *ssh, Authc +@@ -2668,6 +2730,15 @@ do_authenticated2(struct ssh *ssh, Authctxt *authctxt) server_loop2(ssh, authctxt); } @@ -1979,7 +2037,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c void do_cleanup(struct ssh *ssh, Authctxt *authctxt) { -@@ -2734,7 +2804,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au +@@ -2731,7 +2802,7 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) * or if running in monitor. */ if (mm_is_monitor()) @@ -1988,9 +2046,10 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c } /* Return a name for the remote host that fits inside utmp_size */ -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 +diff --git a/session.h b/session.h +index 344a1ddf..a41c6efc 100644 +--- a/session.h ++++ b/session.h @@ -61,6 +61,12 @@ struct Session { char *name; char *val; @@ -2018,53 +2077,25 @@ diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h Session *session_by_tty(char *); void session_close(struct ssh *, Session *); void do_setusercontext(struct passwd *); -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 -@@ -279,6 +280,15 @@ close_listen_socks(void) - num_listen_socks = 0; - } - -+/* -+ * Is this process listening for clients (i.e. not specific to any specific -+ * client connection?) -+ */ -+int listening_for_clients(void) -+{ -+ return num_listen_socks > 0; -+} -+ - /* Allocate and initialise the children array */ - static void - child_alloc(void) -@@ -1204,6 +1259,7 @@ server_accept_loop(int *sock_in, int *so - if (received_sigterm) { - logit("Received signal %d; terminating.", - (int) received_sigterm); -+ /* destroy_sensitive_data(ssh, 0); FIXME */ - close_listen_socks(); - if (options.pid_file != NULL) - unlink(options.pid_file); -diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c ---- openssh-8.6p1/sshd-session.c.audit 2021-04-19 16:47:35.727061907 +0200 -+++ openssh-8.6p1/sshd-session.c 2021-04-19 16:47:35.759062152 +0200 -@@ -122,6 +122,7 @@ - #include "ssh-gss.h" - #endif - #include "monitor_wrap.h" -+#include "audit.h" - #include "ssh-sandbox.h" - #include "auth-options.h" - #include "version.h" -@@ -260,8 +261,44 @@ struct sshbuf *loginmsg; +diff --git a/sshd-session.c b/sshd-session.c +index 81d30152..a808ac9a 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -194,8 +194,8 @@ struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); struct sshbuf *loginmsg; /* Prototypes for various functions defined later in this file. */ -void destroy_sensitive_data(void); -void demote_sensitive_data(void); -+void destroy_sensitive_data(struct ssh *); -+void demote_sensitive_data(struct ssh *); -+ ++void destroy_sensitive_data(struct ssh *ssh); ++void demote_sensitive_data(struct ssh *ssh); + + /* XXX reduce to stub once postauth split */ + int +@@ -208,6 +208,41 @@ mm_is_monitor(void) + return (pmonitor && pmonitor->m_pid > 0); + } + +static int +sshkey_is_private(const struct sshkey *k) +{ @@ -2100,13 +2131,13 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c + } +} + - static void do_ssh2_kex(struct ssh *); - /* -@@ -377,18 +387,40 @@ grace_alarm_handler(int sig) + * Signal handler for the alarm after the login grace period has expired. + * As usual, this may only take signal-safe actions, even though it is +@@ -236,18 +271,40 @@ grace_alarm_handler(int sig) _exit(EXIT_LOGIN_GRACE); } - + -/* 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, @@ -2147,7 +2178,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c sshkey_free(sensitive_data.host_certificates[i]); sensitive_data.host_certificates[i] = NULL; } -@@ -397,20 +434,38 @@ destroy_sensitive_data(void) +@@ -256,20 +313,38 @@ destroy_sensitive_data(void) /* Demote private to public keys for network child */ void @@ -2187,43 +2218,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c } /* Certs do not need demotion */ } -@@ -438,7 +493,7 @@ reseed_prngs(void) - } - - static void --privsep_preauth_child(void) -+privsep_preauth_child(struct ssh *ssh) - { - gid_t gidset[1]; - -@@ -453,7 +508,7 @@ privsep_preauth_child(void) - reseed_prngs(); - - /* Demote the private keys to public keys. */ -- demote_sensitive_data(); -+ demote_sensitive_data(ssh); - - #ifdef WITH_SELINUX - sshd_selinux_change_privsep_preauth_context(); -@@ -492,7 +547,7 @@ privsep_preauth(struct ssh *ssh) - pmonitor->m_pkex = &ssh->kex; - - box = ssh_sandbox_init(pmonitor); -- pid = fork(); -+ pmonitor->m_pid = pid = fork(); - if (pid == -1) { - fatal("fork of unprivileged child failed"); - } else if (pid != 0) { -@@ -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); - -- privsep_preauth_child(); -+ privsep_preauth_child(ssh); - setproctitle("%s", "[net]"); - if (box != NULL) - ssh_sandbox_child(box); -@@ -589,7 +644,7 @@ privsep_postauth(struct ssh *ssh, Authct +@@ -463,7 +538,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) set_log_handler(mm_log_handler, pmonitor); /* Demote the private keys to public keys. */ @@ -2232,7 +2227,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c reseed_prngs(); -@@ -2333,6 +2389,9 @@ main(int ac, char **av) +@@ -1387,6 +1462,9 @@ main(int ac, char **av) do_authenticated(ssh, authctxt); /* The connection has been terminated. */ @@ -2242,7 +2237,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); -@@ -2513,6 +2572,14 @@ do_ssh2_kex(struct ssh *ssh) +@@ -1432,6 +1510,14 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, void cleanup_exit(int i) { @@ -2257,7 +2252,7 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c extern int auth_attempted; /* monitor.c */ if (the_active_state != NULL && the_authctxt != NULL) { -@@ -2525,7 +2593,9 @@ cleanup_exit(int i) +@@ -1448,7 +1534,9 @@ cleanup_exit(int i) } #ifdef SSH_AUDIT_EVENTS /* done after do_cleanup so it can cancel the PAM auth 'thread' */ @@ -2268,3 +2263,34 @@ diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif /* Override default fatal exit value when auth was attempted */ +diff --git a/sshd.c b/sshd.c +index c9ea8e38..8a99f0b2 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -217,6 +217,15 @@ close_listen_socks(void) + num_listen_socks = 0; + } + ++/* ++ * Is this process listening for clients (i.e. not specific to any specific ++ * client connection?) ++ */ ++int listening_for_clients(void) ++{ ++ return num_listen_socks > 0; ++} ++ + /* Allocate and initialise the children array */ + static void + child_alloc(void) +@@ -959,6 +968,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, + if (received_sigterm) { + logit("Received signal %d; terminating.", + (int) received_sigterm); ++ /* destroy_sensitive_data(ssh, 0); FIXME */ + close_listen_socks(); + if (options.pid_file != NULL) + unlink(options.pid_file); +-- +2.49.0 + diff --git a/openssh-7.1p2-audit-race-condition.patch b/0040-openssh-7.1p2-audit-race-condition.patch similarity index 73% rename from openssh-7.1p2-audit-race-condition.patch rename to 0040-openssh-7.1p2-audit-race-condition.patch index 57ad148..fe732a6 100644 --- a/openssh-7.1p2-audit-race-condition.patch +++ b/0040-openssh-7.1p2-audit-race-condition.patch @@ -1,7 +1,19 @@ -diff -up openssh-7.4p1/monitor_wrap.c.audit-race openssh-7.4p1/monitor_wrap.c ---- openssh-7.4p1/monitor_wrap.c.audit-race 2016-12-23 16:35:52.694685771 +0100 -+++ openssh-7.4p1/monitor_wrap.c 2016-12-23 16:35:52.697685772 +0100 -@@ -1107,4 +1107,50 @@ mm_audit_destroy_sensitive_data(const ch +From c288d4a26ad44dc481c9d18d2920c9d70474833c Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 40/50] openssh-7.1p2-audit-race-condition + +--- + monitor_wrap.c | 46 +++++++++++++++++++++++++++++++++++++ + monitor_wrap.h | 2 ++ + session.c | 61 ++++++++++++++++++++++++++++++++++++++++++++------ + 3 files changed, 102 insertions(+), 7 deletions(-) + +diff --git a/monitor_wrap.c b/monitor_wrap.c +index 1a079c15..768a59f9 100644 +--- a/monitor_wrap.c ++++ b/monitor_wrap.c +@@ -1415,4 +1415,50 @@ mm_audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, m); sshbuf_free(m); } @@ -52,10 +64,11 @@ diff -up openssh-7.4p1/monitor_wrap.c.audit-race openssh-7.4p1/monitor_wrap.c + pmonitor->m_recvfd = fd; +} #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-7.4p1/monitor_wrap.h.audit-race openssh-7.4p1/monitor_wrap.h ---- openssh-7.4p1/monitor_wrap.h.audit-race 2016-12-23 16:35:52.694685771 +0100 -+++ openssh-7.4p1/monitor_wrap.h 2016-12-23 16:35:52.698685772 +0100 -@@ -83,6 +83,8 @@ void mm_audit_unsupported_body(int); +diff --git a/monitor_wrap.h b/monitor_wrap.h +index 661ed63b..e957ba6e 100644 +--- a/monitor_wrap.h ++++ b/monitor_wrap.h +@@ -93,6 +93,8 @@ void mm_audit_unsupported_body(struct ssh *, int); void mm_audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t); void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t); void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); @@ -64,10 +77,11 @@ diff -up openssh-7.4p1/monitor_wrap.h.audit-race openssh-7.4p1/monitor_wrap.h #endif struct Session; -diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c ---- openssh-7.4p1/session.c.audit-race 2016-12-23 16:35:52.695685771 +0100 -+++ openssh-7.4p1/session.c 2016-12-23 16:37:26.339730596 +0100 -@@ -162,6 +162,10 @@ static Session *sessions = NULL; +diff --git a/session.c b/session.c +index 83fc9418..b4753d93 100644 +--- a/session.c ++++ b/session.c +@@ -167,6 +167,10 @@ static Session *sessions = NULL; login_cap_t *lc; #endif @@ -78,7 +92,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c static int is_child = 0; static int in_chroot = 0; static int have_dev_log = 1; -@@ -289,6 +293,8 @@ xauth_valid_string(const char *s) +@@ -390,6 +394,8 @@ xauth_valid_string(const char *s) return 1; } @@ -87,7 +101,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c #define USE_PIPES 1 /* * This is called to fork and execute a command when we have no tty. This -@@ -424,6 +430,8 @@ do_exec_no_pty(Session *s, const char *c +@@ -513,6 +519,8 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) close(err[0]); #endif @@ -96,7 +110,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c /* Do processing for the child (exec command etc). */ do_child(ssh, s, command); /* NOTREACHED */ -@@ -547,6 +555,9 @@ do_exec_pty(Session *s, const char *comm +@@ -630,6 +638,9 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) /* Close the extra descriptor for the pseudo tty. */ close(ttyfd); @@ -106,7 +120,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c /* record login, etc. similar to login(1) */ #ifndef HAVE_OSF_SIA do_login(ssh, s, command); -@@ -717,6 +728,8 @@ do_exec(Session *s, const char *command) +@@ -766,6 +777,8 @@ do_exec(struct ssh *ssh, Session *s, const char *command) } if (s->command != NULL && s->ptyfd == -1) s->command_handle = mm_audit_run_command(ssh, s->command); @@ -115,7 +129,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); -@@ -732,6 +745,20 @@ do_exec(Session *s, const char *command) +@@ -781,6 +794,20 @@ do_exec(struct ssh *ssh, Session *s, const char *command) */ sshbuf_reset(loginmsg); @@ -136,7 +150,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c return ret; } -@@ -1538,6 +1565,33 @@ child_close_fds(void) +@@ -1532,6 +1559,33 @@ child_close_fds(struct ssh *ssh) log_redirect_stderr_to(NULL); } @@ -151,7 +165,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c +#endif + + /* remove hostkey from the child's memory */ -+ destroy_sensitive_data(ssh); ++ /* FIXME beldmit destroy_sensitive_data(ssh); */ + /* + * We can audit this, because we hacked the pipe to direct the + * messages over postauth child. But this message requires answer @@ -170,11 +184,11 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c /* * Performs common processing for the child, such as setting up the * environment, closing extra file descriptors, setting the user and group -@@ -1554,13 +1608,6 @@ do_child(Session *s, const char *command +@@ -1549,13 +1603,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); -- /* remove hostkey from the child's memory */ +- /* remove keys from memory */ - destroy_sensitive_data(ssh); - ssh_packet_clear_keys(ssh); - /* Don't audit this - both us and the parent would be talking to the @@ -184,3 +198,6 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c /* Force a password change */ if (s->authctxt->force_pwchange) { do_setusercontext(pw); +-- +2.49.0 + diff --git a/openssh-9.0p1-audit-log.patch b/0041-openssh-9.0p1-audit-log.patch similarity index 85% rename from openssh-9.0p1-audit-log.patch rename to 0041-openssh-9.0p1-audit-log.patch index ae9550f..e04f31b 100644 --- a/openssh-9.0p1-audit-log.patch +++ b/0041-openssh-9.0p1-audit-log.patch @@ -1,7 +1,20 @@ -diff -up openssh-9.0p1/audit-bsm.c.patch openssh-9.0p1/audit-bsm.c ---- openssh-9.0p1/audit-bsm.c.patch 2022-10-24 15:02:16.544858331 +0200 -+++ openssh-9.0p1/audit-bsm.c 2022-10-24 14:51:43.685766639 +0200 -@@ -405,7 +405,7 @@ audit_session_close(struct logininfo *li +From 80d967a18261156573e7385f8e534a89d2767d67 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 41/50] openssh-9.0p1-audit-log + +--- + audit-bsm.c | 2 +- + audit-linux.c | 76 +++++++++++++++++++++++++++++++++++++++++++-------- + audit.c | 18 +++++++++--- + audit.h | 2 +- + 4 files changed, 81 insertions(+), 17 deletions(-) + +diff --git a/audit-bsm.c b/audit-bsm.c +index a49abb92..c6f56553 100644 +--- a/audit-bsm.c ++++ b/audit-bsm.c +@@ -405,7 +405,7 @@ audit_session_close(struct logininfo *li) } int @@ -10,51 +23,10 @@ diff -up openssh-9.0p1/audit-bsm.c.patch openssh-9.0p1/audit-bsm.c { /* not implemented */ } -diff -up openssh-9.0p1/audit.c.patch openssh-9.0p1/audit.c ---- openssh-9.0p1/audit.c.patch 2022-10-24 15:02:16.544858331 +0200 -+++ openssh-9.0p1/audit.c 2022-10-24 15:20:38.854548226 +0200 -@@ -116,12 +116,22 @@ audit_event_lookup(ssh_audit_event_t ev) - void - audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key) - { -- char *fp; -+ char *key_fp = NULL; -+ char *issuer_fp = NULL; -+ struct sshkey_cert *cert = NULL; - -- fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); -- if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0) -+ key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); -+ if (sshkey_is_cert(key) && key->cert != NULL && key->cert->signature_key != NULL) { -+ cert = key->cert; -+ issuer_fp = sshkey_fingerprint(cert->signature_key, -+ options.fingerprint_hash, SSH_FP_DEFAULT); -+ } -+ if (audit_keyusage(ssh, host_user, key_fp, cert, issuer_fp, (*rv == 0)) == 0) - *rv = -SSH_ERR_INTERNAL_ERROR; -- free(fp); -+ if (key_fp) -+ free(key_fp); -+ if (issuer_fp) -+ free(issuer_fp); - } - - void -diff -up openssh-9.0p1/audit.h.patch openssh-9.0p1/audit.h ---- openssh-9.0p1/audit.h.patch 2022-10-24 15:02:16.544858331 +0200 -+++ openssh-9.0p1/audit.h 2022-10-24 14:58:20.887565518 +0200 -@@ -64,7 +64,7 @@ void audit_session_close(struct logininf - 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); -+int audit_keyusage(struct ssh *, int, const char *, const struct sshkey_cert *, const 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 *); -diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c ---- openssh-9.9p1/audit-linux.c.xxx 2024-10-15 11:49:48.092151974 +0200 -+++ openssh-9.9p1/audit-linux.c 2024-10-15 12:08:17.179158343 +0200 +diff --git a/audit-linux.c b/audit-linux.c +index d484b82b..dcfde3a9 100644 +--- a/audit-linux.c ++++ b/audit-linux.c @@ -52,7 +52,7 @@ extern u_int utmp_len; const char *audit_username(void); @@ -64,7 +36,7 @@ diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c const char *ip, const char *ttyn, int success, int event) { int audit_fd, rc, saved_errno; -@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const c +@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const char *username, } rc = audit_log_acct_message(audit_fd, event, NULL, "login", username ? username : "(unknown)", @@ -87,7 +59,7 @@ diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c audit_fd = audit_open(); if (audit_fd < 0) { -@@ -150,14 +152,44 @@ audit_keyusage(struct ssh *ssh, int host +@@ -150,14 +152,44 @@ audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) else return 0; /* Must prevent login */ } @@ -135,7 +107,7 @@ diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c out: saved_errno = errno; audit_close(audit_fd); -@@ -179,26 +211,34 @@ audit_connection_from(const char *host, +@@ -179,26 +211,34 @@ audit_connection_from(const char *host, int port) int audit_run_command(struct ssh *ssh, const char *command) { @@ -217,7 +189,7 @@ diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); break; case SSH_AUTH_FAIL_PASSWD: -@@ -255,9 +305,11 @@ audit_event(struct ssh *ssh, ssh_audit_e +@@ -255,9 +305,11 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) if (user_login_count) { while (user_login_count--) linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, @@ -229,7 +201,7 @@ diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c ssh_remote_ipaddr(ssh), "ssh", 1, AUDIT_USER_LOGOUT); } -@@ -266,12 +318,14 @@ audit_event(struct ssh *ssh, ssh_audit_e +@@ -266,12 +318,14 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) case SSH_CONNECTION_ABANDON: case SSH_INVALID_USER: linux_audit_user_logxxx(-1, audit_username(), @@ -244,3 +216,50 @@ diff -up openssh-9.9p1/audit-linux.c.xxx openssh-9.9p1/audit-linux.c } void +diff --git a/audit.c b/audit.c +index d0433c3a..28d51a14 100644 +--- a/audit.c ++++ b/audit.c +@@ -116,12 +116,22 @@ audit_event_lookup(ssh_audit_event_t ev) + void + audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key) + { +- char *fp; ++ char *key_fp = NULL; ++ char *issuer_fp = NULL; ++ struct sshkey_cert *cert = NULL; + +- fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); +- if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0) ++ key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); ++ if (sshkey_is_cert(key) && key->cert != NULL && key->cert->signature_key != NULL) { ++ cert = key->cert; ++ issuer_fp = sshkey_fingerprint(cert->signature_key, ++ options.fingerprint_hash, SSH_FP_DEFAULT); ++ } ++ if (audit_keyusage(ssh, host_user, key_fp, cert, issuer_fp, (*rv == 0)) == 0) + *rv = -SSH_ERR_INTERNAL_ERROR; +- free(fp); ++ if (key_fp) ++ free(key_fp); ++ if (issuer_fp) ++ free(issuer_fp); + } + + void +diff --git a/audit.h b/audit.h +index 45d66ccf..05ac132c 100644 +--- a/audit.h ++++ b/audit.h +@@ -64,7 +64,7 @@ void audit_session_close(struct logininfo *); + 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); ++int audit_keyusage(struct ssh *, int, const char *, const struct sshkey_cert *, const 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 *); +-- +2.49.0 + diff --git a/openssh-7.7p1-fips.patch b/0042-openssh-7.7p1-fips.patch similarity index 77% rename from openssh-7.7p1-fips.patch rename to 0042-openssh-7.7p1-fips.patch index 5d8da08..f4729d7 100644 --- a/openssh-7.7p1-fips.patch +++ b/0042-openssh-7.7p1-fips.patch @@ -1,6 +1,33 @@ -diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c ---- openssh-8.6p1/dh.c.fips 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/dh.c 2021-05-06 12:12:10.107634472 +0200 +From 6e0e7462959e8bc6a99f50dbf9a5b42ae74c2c87 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 42/50] openssh-7.7p1-fips + +--- + dh.c | 41 ++++++++++++++++++++++ + dh.h | 1 + + kex-names.c | 6 +++- + kex.c | 3 +- + kexgen.c | 74 ++++++++++++++++++++++++++++++++-------- + kexgexc.c | 5 +++ + myproposal.h | 33 ++++++++++++++++++ + readconf.c | 16 ++++++--- + sandbox-seccomp-filter.c | 3 ++ + servconf.c | 16 ++++++--- + ssh-ed25519.c | 9 +++++ + ssh-keygen.c | 22 ++++++++++-- + ssh-rsa.c | 3 ++ + ssh.c | 5 +++ + sshconnect2.c | 61 ++++++++++++++++++--------------- + sshd-auth.c | 13 ++++--- + sshd.c | 13 +++++++ + sshkey.c | 37 ++++++++++++++++++++ + 18 files changed, 301 insertions(+), 60 deletions(-) + +diff --git a/dh.c b/dh.c +index 168dea1d..8c9a29fa 100644 +--- a/dh.c ++++ b/dh.c @@ -36,6 +36,7 @@ #include @@ -9,7 +36,7 @@ diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c #include "dh.h" #include "pathnames.h" -@@ -164,6 +164,12 @@ choose_dh(int min, int wantbits, int max +@@ -164,6 +165,12 @@ choose_dh(int min, int wantbits, int max) int best, bestcount, which, linenum; struct dhgroup dhg; @@ -22,7 +49,7 @@ diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c if ((f = fopen(get_moduli_filename(), "r")) == NULL) { logit("WARNING: could not open %s (%s), using fixed modulus", get_moduli_filename(), strerror(errno)); -@@ -502,4 +508,38 @@ dh_estimate(int bits) +@@ -502,4 +509,38 @@ dh_estimate(int bits) return 8192; } @@ -61,9 +88,10 @@ diff -up openssh-8.6p1/dh.c.fips openssh-8.6p1/dh.c +} + #endif /* WITH_OPENSSL */ -diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h ---- openssh-8.6p1/dh.h.fips 2021-05-06 12:08:36.498926877 +0200 -+++ openssh-8.6p1/dh.h 2021-05-06 12:11:28.393298005 +0200 +diff --git a/dh.h b/dh.h +index c6326a39..e51e292b 100644 +--- a/dh.h ++++ b/dh.h @@ -45,6 +45,7 @@ DH *dh_new_group_fallback(int); int dh_gen_key(DH *, int); @@ -72,10 +100,11 @@ diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h u_int dh_estimate(int); void dh_set_moduli_file(const char *); -diff -up openssh-8.6p1/kex-names.c.fips openssh-8.6p1/kex-names.c ---- openssh-8.6p1/kex-names.c.fips 2021-05-06 12:08:36.489926807 +0200 -+++ openssh-8.6p1/kex-names.c 2021-05-06 12:08:36.498926877 +0200 -@@ -39,6 +39,7 @@ +diff --git a/kex-names.c b/kex-names.c +index 6c0b7c2b..cd3902ad 100644 +--- a/kex-names.c ++++ b/kex-names.c +@@ -33,6 +33,7 @@ #ifdef WITH_OPENSSL #include @@ -83,7 +112,7 @@ diff -up openssh-8.6p1/kex-names.c.fips openssh-8.6p1/kex-names.c #include #endif -@@ -203,7 +203,10 @@ kex_names_valid(const char *names) +@@ -206,7 +207,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (kex_alg_by_name(p) == NULL) { @@ -95,9 +124,149 @@ diff -up openssh-8.6p1/kex-names.c.fips openssh-8.6p1/kex-names.c free(s); return 0; } -diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c ---- openssh-8.6p1/kexgexc.c.fips 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/kexgexc.c 2021-05-06 12:08:36.498926877 +0200 +diff --git a/kex.c b/kex.c +index 62f607d6..71fbe5cb 100644 +--- a/kex.c ++++ b/kex.c +@@ -40,6 +40,7 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include + # ifdef HAVE_EVP_KDF_CTX_NEW + # include + # include +@@ -109,7 +110,7 @@ kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX], + + /* Append EXT_INFO signalling to KexAlgorithms */ + if (kexalgos == NULL) +- kexalgos = defprop[PROPOSAL_KEX_ALGS]; ++ kexalgos = FIPS_mode() ? KEX_DEFAULT_KEX_FIPS : defprop[PROPOSAL_KEX_ALGS]; + if ((cp = kex_names_cat(kexalgos, ssh->kex->server ? + "ext-info-s,kex-strict-s-v00@openssh.com" : + "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) +diff --git a/kexgen.c b/kexgen.c +index 15df591c..eecdceba 100644 +--- a/kexgen.c ++++ b/kexgen.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "sshkey.h" + #include "kex.h" +@@ -115,13 +116,28 @@ kex_gen_client(struct ssh *ssh) + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_keypair(kex); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_keypair(kex); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_keypair(kex); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_keypair(kex); ++ } + break; + case KEX_KEM_MLKEM768X25519_SHA256: +- r = kex_kem_mlkem768x25519_keypair(kex); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768x25519_keypair(kex); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +@@ -189,15 +205,30 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_dec(kex, server_blob, &shared_secret); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_dec(kex, server_blob, +- &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_dec(kex, server_blob, ++ &shared_secret); ++ } + break; + case KEX_KEM_MLKEM768X25519_SHA256: +- r = kex_kem_mlkem768x25519_dec(kex, server_blob, +- &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768x25519_dec(kex, server_blob, ++ &shared_secret); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +@@ -312,16 +343,31 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) + break; + #endif + case KEX_C25519_SHA256: +- r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, +- &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ } + break; + case KEX_KEM_SNTRUP761X25519_SHA512: +- r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, +- &server_pubkey, &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, ++ &server_pubkey, &shared_secret); ++ } + break; + case KEX_KEM_MLKEM768X25519_SHA256: +- r = kex_kem_mlkem768x25519_enc(kex, client_pubkey, +- &server_pubkey, &shared_secret); ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768x25519_enc(kex, client_pubkey, ++ &server_pubkey, &shared_secret); ++ } + break; + default: + r = SSH_ERR_INVALID_ARGUMENT; +diff --git a/kexgexc.c b/kexgexc.c +index e99e0cf2..4c3feae0 100644 +--- a/kexgexc.c ++++ b/kexgexc.c @@ -28,6 +28,7 @@ #ifdef WITH_OPENSSL @@ -106,7 +275,7 @@ diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c #include #include -@@ -115,6 +116,10 @@ input_kex_dh_gex_group(int type, u_int32 +@@ -115,6 +116,10 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) r = SSH_ERR_ALLOC_FAIL; goto out; } @@ -117,10 +286,11 @@ diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c p = g = NULL; /* belong to kex->dh now */ /* generate and send 'e', client DH public key */ -diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h ---- openssh-8.6p1/myproposal.h.fips 2021-04-16 05:55:25.000000000 +0200 -+++ openssh-8.6p1/myproposal.h 2021-05-06 12:08:36.498926877 +0200 -@@ -57,6 +57,18 @@ +diff --git a/myproposal.h b/myproposal.h +index 8fe9276c..3e0ec682 100644 +--- a/myproposal.h ++++ b/myproposal.h +@@ -58,6 +58,18 @@ "rsa-sha2-512," \ "rsa-sha2-256" @@ -138,8 +308,8 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h + #define KEX_SERVER_ENCRYPT \ "chacha20-poly1305@openssh.com," \ - "aes128-ctr,aes192-ctr,aes256-ctr," \ -@@ -78,6 +92,27 @@ + "aes128-gcm@openssh.com,aes256-gcm@openssh.com," \ +@@ -79,6 +91,27 @@ #define KEX_CLIENT_MAC KEX_SERVER_MAC @@ -167,10 +337,11 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h /* Not a KEX value, but here so all the algorithm defaults are together */ #define SSH_ALLOWED_CA_SIGALGS \ "ssh-ed25519," \ -diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c ---- openssh-8.6p1/readconf.c.fips 2021-05-06 12:08:36.428926336 +0200 -+++ openssh-8.6p1/readconf.c 2021-05-06 12:08:36.499926885 +0200 -@@ -39,6 +39,7 @@ +diff --git a/readconf.c b/readconf.c +index f340bf50..ea9d293c 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -43,6 +43,7 @@ #include #include #include @@ -178,7 +349,7 @@ diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c #ifdef USE_SYSTEM_GLOB # include #else -@@ -2538,11 +2538,16 @@ fill_default_options(Options * options) +@@ -3043,11 +3044,16 @@ fill_default_options(Options * options) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); /* remove unsupported algos from default lists */ @@ -200,10 +371,11 @@ diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c #define ASSEMBLE(what, defaults, all) \ do { \ if ((r = kex_assemble_names(&options->what, \ -diff -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-seccomp-filter.c ---- openssh-8.6p1/sandbox-seccomp-filter.c.fips 2021-05-06 12:08:36.463926606 +0200 -+++ openssh-8.6p1/sandbox-seccomp-filter.c 2021-05-06 12:08:36.499926885 +0200 -@@ -160,6 +160,9 @@ static const struct sock_filter preauth_ +diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c +index 1fabf99d..ccb61586 100644 +--- a/sandbox-seccomp-filter.c ++++ b/sandbox-seccomp-filter.c +@@ -230,6 +230,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_open SC_DENY(__NR_open, EACCES), #endif @@ -213,10 +385,11 @@ diff -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-secco #ifdef __NR_openat SC_DENY(__NR_openat, EACCES), #endif -diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c ---- openssh-8.6p1/servconf.c.fips 2021-05-06 12:08:36.455926545 +0200 -+++ openssh-8.6p1/servconf.c 2021-05-06 12:08:36.500926893 +0200 -@@ -38,6 +38,7 @@ +diff --git a/servconf.c b/servconf.c +index 84891544..8b708cbf 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -37,6 +37,7 @@ #include #include #include @@ -224,7 +397,7 @@ diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c #ifdef HAVE_UTIL_H #include #endif -@@ -226,11 +226,16 @@ assemble_algorithms(ServerOptions *o) +@@ -247,11 +248,16 @@ assemble_algorithms(ServerOptions *o) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); /* remove unsupported algos from default lists */ @@ -246,10 +419,136 @@ diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c #define ASSEMBLE(what, defaults, all) \ do { \ if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ -diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c ---- openssh-8.6p1/ssh.c.fips 2021-05-06 12:08:36.467926637 +0200 -+++ openssh-8.6p1/ssh.c 2021-05-06 12:08:36.500926893 +0200 -@@ -77,6 +77,7 @@ +diff --git a/ssh-ed25519.c b/ssh-ed25519.c +index 22d8db02..41942f4e 100644 +--- a/ssh-ed25519.c ++++ b/ssh-ed25519.c +@@ -24,6 +24,7 @@ + + #include + #include ++#include + + #include "log.h" + #include "sshbuf.h" +@@ -164,6 +165,10 @@ ssh_ed25519_sign(struct sshkey *key, + key->ed25519_sk == NULL || + datalen >= INT_MAX - crypto_sign_ed25519_BYTES) + return SSH_ERR_INVALID_ARGUMENT; ++ if (FIPS_mode()) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } + smlen = slen = datalen + crypto_sign_ed25519_BYTES; + if ((sig = malloc(slen)) == NULL) + return SSH_ERR_ALLOC_FAIL; +@@ -221,6 +226,10 @@ ssh_ed25519_verify(const struct sshkey *key, + dlen >= INT_MAX - crypto_sign_ed25519_BYTES || + sig == NULL || siglen == 0) + return SSH_ERR_INVALID_ARGUMENT; ++ if (FIPS_mode()) { ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } + + if ((b = sshbuf_from(sig, siglen)) == NULL) + return SSH_ERR_ALLOC_FAIL; +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 16cff947..792aafde 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -20,6 +20,7 @@ + + #ifdef WITH_OPENSSL + #include ++#include + #include + #include "openbsd-compat/openssl-compat.h" + #endif +@@ -68,6 +69,7 @@ + #include "cipher.h" + + #define DEFAULT_KEY_TYPE_NAME "ed25519" ++#define FIPS_DEFAULT_KEY_TYPE_NAME "rsa" + + /* + * Default number of bits in the RSA, DSA and ECDSA keys. These value can be +@@ -202,6 +204,12 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) + #endif + } + #ifdef WITH_OPENSSL ++ if (FIPS_mode()) { ++ if (type == KEY_DSA) ++ fatal("DSA keys are not allowed in FIPS mode"); ++ if (type == KEY_ED25519 || type == KEY_ED25519_SK) ++ fatal("ED25519 keys are not allowed in FIPS mode"); ++ } + switch (type) { + case KEY_DSA: + if (*bitsp != 1024) +@@ -259,7 +267,7 @@ ask_filename(struct passwd *pw, const char *prompt) + char *name = NULL; + + if (key_type_name == NULL) +- name = _PATH_SSH_CLIENT_ID_ED25519; ++ name = FIPS_mode() ? _PATH_SSH_CLIENT_ID_RSA : _PATH_SSH_CLIENT_ID_ED25519; + else { + switch (sshkey_type_from_shortname(key_type_name)) { + #ifdef WITH_DSA +@@ -1144,9 +1152,17 @@ do_gen_all_hostkeys(struct passwd *pw) + first = 1; + printf("%s: generating new host keys: ", __progname); + } ++ type = sshkey_type_from_shortname(key_types[i].key_type); ++ ++ /* Skip the keys that are not supported in FIPS mode */ ++ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) { ++ logit("Skipping %s key in FIPS mode", ++ key_types[i].key_type_display); ++ goto next; ++ } ++ + printf("%s ", key_types[i].key_type_display); + fflush(stdout); +- type = sshkey_type_from_shortname(key_types[i].key_type); + if ((fd = mkstemp(prv_tmp)) == -1) { + error("Could not save your private key in %s: %s", + prv_tmp, strerror(errno)); +@@ -3849,7 +3865,7 @@ main(int argc, char **argv) + } + + if (key_type_name == NULL) +- key_type_name = DEFAULT_KEY_TYPE_NAME; ++ key_type_name = FIPS_mode() ? FIPS_DEFAULT_KEY_TYPE_NAME : DEFAULT_KEY_TYPE_NAME; + + type = sshkey_type_from_shortname(key_type_name); + type_bits_valid(type, key_type_name, &bits); +diff --git a/ssh-rsa.c b/ssh-rsa.c +index 3ad1fddc..6c2f771a 100644 +--- a/ssh-rsa.c ++++ b/ssh-rsa.c +@@ -23,6 +23,7 @@ + + #include + #include ++#include + + #include + #include +@@ -142,6 +143,8 @@ ssh_rsa_generate(struct sshkey *k, int bits) + goto out; + } + if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) { ++ if (FIPS_mode()) ++ logit_f("the key length might be unsupported by FIPS mode approved key generation method"); + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +diff --git a/ssh.c b/ssh.c +index 98b103c9..abc8b843 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -78,6 +78,7 @@ #include #include #endif @@ -257,7 +556,7 @@ diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" -@@ -1516,6 +1517,10 @@ main(int ac, char **av) +@@ -1642,6 +1643,10 @@ main(int ac, char **av) exit(0); } @@ -268,9 +567,10 @@ diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c /* Expand SecurityKeyProvider if it refers to an environment variable */ if (options.sk_provider != NULL && *options.sk_provider == '$' && strlen(options.sk_provider) > 1) { -diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c ---- openssh-8.6p1/sshconnect2.c.fips 2021-05-06 12:08:36.485926777 +0200 -+++ openssh-8.6p1/sshconnect2.c 2021-05-06 12:08:36.501926900 +0200 +diff --git a/sshconnect2.c b/sshconnect2.c +index 0af15bcc..14f7671a 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c @@ -45,6 +45,8 @@ #include #endif @@ -280,7 +580,7 @@ diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" -@@ -269,36 +271,41 @@ ssh_kex2(struct ssh *ssh, char *host, st +@@ -262,36 +264,41 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, #if defined(GSSAPI) && defined(WITH_OPENSSL) if (options.gss_keyex) { @@ -349,62 +649,19 @@ diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c } } #endif -diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c ---- openssh-8.6p1/sshd.c.fips 2021-05-06 12:08:36.493926838 +0200 -+++ openssh-8.6p1/sshd.c 2021-05-06 12:13:56.501492639 +0200 -@@ -66,6 +66,7 @@ - #endif - #include - #include -+#include - #include - #include - #include -@@ -77,6 +78,7 @@ +diff --git a/sshd-auth.c b/sshd-auth.c +index 897db9b4..eaf32981 100644 +--- a/sshd-auth.c ++++ b/sshd-auth.c +@@ -58,6 +58,7 @@ #ifdef WITH_OPENSSL - #include - #include -+#include - #include "openbsd-compat/openssl-compat.h" - #endif - -@@ -1931,6 +1931,13 @@ main(int ac, char **av) - &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) - do_log2_r(r, ll, "Unable to load host key \"%s\"", - options.host_key_files[i]); -+ if (FIPS_mode() && key != NULL && (sshkey_type_plain(key->type) == KEY_ED25519_SK -+ || sshkey_type_plain(key->type) == KEY_ED25519)) { -+ logit_f("sshd: Ed25519 keys are not allowed in FIPS mode, skipping %s", options.host_key_files[i]); -+ sshkey_free(key); -+ key = NULL; -+ continue; -+ } - if (sshkey_is_sk(key) && - key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { - debug("host key %s requires user presence, ignoring", -@@ -2110,6 +2113,10 @@ main(int ac, char **av) - /* Reinitialize the log (because of the fork above). */ - log_init(__progname, options.log_level, options.log_facility, log_stderr); - -+ if (FIPS_mode()) { -+ debug("FIPS mode initialized"); -+ } -+ - /* - * Chdir to the root directory so that the current disk can be - * unmounted if desired. -diff -up openssh-8.6p1/sshd-session.c.fips openssh-8.6p1/sshd-session.c ---- a/sshd-session.c.fips 2021-05-06 12:08:36.493926838 +0200 -+++ b/sshd-session.c 2021-05-06 12:13:56.501492639 +0200 -@@ -78,6 +79,7 @@ #include #include - #include +#include - #include "openbsd-compat/openssl-compat.h" #endif -@@ -2506,10 +2513,14 @@ do_ssh2_kex(struct ssh *ssh) + #include "xmalloc.h" +@@ -859,10 +860,14 @@ do_ssh2_kex(struct ssh *ssh) if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) orig = NULL; @@ -423,10 +680,56 @@ diff -up openssh-8.6p1/sshd-session.c.fips openssh-8.6p1/sshd-session.c if (gss && orig) xasprintf(&newstr, "%s,%s", gss, orig); -diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c ---- openssh-8.6p1/sshkey.c.fips 2021-05-06 12:08:36.493926838 +0200 -+++ openssh-8.6p1/sshkey.c 2021-05-06 12:08:36.502926908 +0200 -@@ -36,6 +36,7 @@ +diff --git a/sshd.c b/sshd.c +index 8a99f0b2..5ff0b5ff 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -52,6 +52,7 @@ + #endif + #include + #include ++#include + #include + #include + #include +@@ -63,6 +64,7 @@ + #ifdef WITH_OPENSSL + #include + #include ++#include + #include "openbsd-compat/openssl-compat.h" + #endif + +@@ -1611,6 +1613,13 @@ main(int ac, char **av) + &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) + do_log2_r(r, ll, "Unable to load host key \"%s\"", + options.host_key_files[i]); ++ if (FIPS_mode() && key != NULL && (sshkey_type_plain(key->type) == KEY_ED25519_SK ++ || sshkey_type_plain(key->type) == KEY_ED25519)) { ++ logit_f("sshd: Ed25519 keys are not allowed in FIPS mode, skipping %s", options.host_key_files[i]); ++ sshkey_free(key); ++ key = NULL; ++ continue; ++ } + if (sshkey_is_sk(key) && + key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { + debug("host key %s requires user presence, ignoring", +@@ -1830,6 +1839,10 @@ main(int ac, char **av) + /* Reinitialize the log (because of the fork above). */ + log_init(__progname, options.log_level, options.log_facility, log_stderr); + ++ if (FIPS_mode()) { ++ debug("FIPS mode initialized"); ++ } ++ + /* + * Chdir to the root directory so that the current disk can be + * unmounted if desired. +diff --git a/sshkey.c b/sshkey.c +index 4e41a78c..ca1cdb64 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -35,6 +35,7 @@ #include #include #include @@ -434,7 +737,7 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c #endif #include "crypto_api.h" -@@ -57,6 +58,7 @@ +@@ -59,6 +60,7 @@ #define SSHKEY_INTERNAL #include "sshkey.h" #include "match.h" @@ -442,7 +745,7 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c #include "ssh-sk.h" #ifdef WITH_XMSS -@@ -285,6 +285,18 @@ sshkey_alg_list(int certs_only, int plai +@@ -408,6 +410,18 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) impl = keyimpls[i]; if (impl->name == NULL || impl->type == KEY_NULL) continue; @@ -461,7 +764,7 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c if (!include_sigonly && impl->sigonly) continue; if ((certs_only && !impl->cert) || (plain_only && impl->cert)) -@@ -1503,6 +1503,20 @@ sshkey_read(struct sshkey *ret, char **c +@@ -1441,6 +1455,20 @@ sshkey_read(struct sshkey *ret, char **cpp) return SSH_ERR_EC_CURVE_MISMATCH; } @@ -482,7 +785,7 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c /* Fill in ret from parsed key */ sshkey_free_contents(ret); *ret = *k; -@@ -2916,6 +2916,11 @@ sshkey_sign(struct sshkey *key, +@@ -2275,6 +2303,11 @@ sshkey_sign(struct sshkey *key, *lenp = 0; if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; @@ -494,7 +797,7 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if ((r = sshkey_unshield_private(key)) != 0) -@@ -2973,6 +2978,10 @@ sshkey_verify(const struct sshkey *key, +@@ -2311,6 +2344,10 @@ sshkey_verify(const struct sshkey *key, *detailsp = NULL; if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; @@ -502,265 +805,9 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c + logit_f("Ed25519 keys are not allowed in FIPS mode"); + return SSH_ERR_INVALID_ARGUMENT; + } - if ((impl = sshkey_impl_from_key(key)) == NULL) - return SSH_ERR_KEY_TYPE_UNKNOWN; - return impl->funcs->verify(key, sig, siglen, data, dlen, -diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c ---- openssh-8.6p1/ssh-keygen.c.fips 2021-05-06 12:08:36.467926637 +0200 -+++ openssh-8.6p1/ssh-keygen.c 2021-05-06 12:08:36.503926916 +0200 -@@ -20,6 +20,7 @@ - - #ifdef WITH_OPENSSL - #include -+#include - #include - #include "openbsd-compat/openssl-compat.h" - #endif -@@ -69,6 +69,7 @@ - #include "cipher.h" - - #define DEFAULT_KEY_TYPE_NAME "ed25519" -+#define FIPS_DEFAULT_KEY_TYPE_NAME "rsa" - - /* - * Default number of bits in the RSA, DSA and ECDSA keys. These value can be -@@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na - #endif - } - #ifdef WITH_OPENSSL -+ if (FIPS_mode()) { -+ if (type == KEY_DSA) -+ fatal("DSA keys are not allowed in FIPS mode"); -+ if (type == KEY_ED25519 || type == KEY_ED25519_SK) -+ fatal("ED25519 keys are not allowed in FIPS mode"); -+ } - switch (type) { - case KEY_DSA: - if (*bitsp != 1024) -@@ -266,7 +267,7 @@ ask_filename(struct passwd *pw, const ch - char *name = NULL; - - if (key_type_name == NULL) -- name = _PATH_SSH_CLIENT_ID_ED25519; -+ name = FIPS_mode() ? _PATH_SSH_CLIENT_ID_RSA : _PATH_SSH_CLIENT_ID_ED25519; - else { - switch (sshkey_type_from_shortname(key_type_name)) { - #ifdef WITH_DSA -@@ -1098,9 +1104,17 @@ do_gen_all_hostkeys(struct passwd *pw) - first = 1; - printf("%s: generating new host keys: ", __progname); - } -+ type = sshkey_type_from_shortname(key_types[i].key_type); -+ -+ /* Skip the keys that are not supported in FIPS mode */ -+ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) { -+ logit("Skipping %s key in FIPS mode", -+ key_types[i].key_type_display); -+ goto next; -+ } -+ - printf("%s ", key_types[i].key_type_display); - fflush(stdout); -- type = sshkey_type_from_shortname(key_types[i].key_type); - if ((fd = mkstemp(prv_tmp)) == -1) { - error("Could not save your private key in %s: %s", - prv_tmp, strerror(errno)); -@@ -3830,7 +3831,7 @@ main(int argc, char **argv) - } - - if (key_type_name == NULL) -- key_type_name = DEFAULT_KEY_TYPE_NAME; -+ key_type_name = FIPS_mode() ? FIPS_DEFAULT_KEY_TYPE_NAME : DEFAULT_KEY_TYPE_NAME; - - type = sshkey_type_from_shortname(key_type_name); - type_bits_valid(type, key_type_name, &bits); -diff -up openssh-9.3p1/ssh-rsa.c.evpgenrsa openssh-9.3p1/ssh-rsa.c ---- openssh-9.3p1/ssh-rsa.c.evpgenrsa 2022-06-30 15:14:58.200518353 +0200 -+++ openssh-9.3p1/ssh-rsa.c 2022-06-30 15:24:31.499641196 +0200 -@@ -33,6 +33,7 @@ - - #include - #include -+#include - - #include - #include -@@ -1705,6 +1707,8 @@ ssh_rsa_generate(u_int bits, RSA - goto out; - } - if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) { -+ if (FIPS_mode()) -+ logit_f("the key length might be unsupported by FIPS mode approved key generation method"); - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -diff -up openssh-9.9p1/kexgen.c.xxx openssh-9.9p1/kexgen.c ---- openssh-9.9p1/kexgen.c.xxx 2024-10-09 10:35:56.285946080 +0200 -+++ openssh-9.9p1/kexgen.c 2024-10-09 10:41:52.792597194 +0200 -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - - #include "sshkey.h" - #include "kex.h" -@@ -115,13 +116,28 @@ kex_gen_client(struct ssh *ssh) - break; - #endif - case KEX_C25519_SHA256: -- r = kex_c25519_keypair(kex); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_c25519_keypair(kex); -+ } - break; - case KEX_KEM_SNTRUP761X25519_SHA512: -- r = kex_kem_sntrup761x25519_keypair(kex); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_kem_sntrup761x25519_keypair(kex); -+ } - break; - case KEX_KEM_MLKEM768X25519_SHA256: -- r = kex_kem_mlkem768x25519_keypair(kex); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_kem_mlkem768x25519_keypair(kex); -+ } - break; - default: - r = SSH_ERR_INVALID_ARGUMENT; -@@ -189,15 +205,30 @@ input_kex_gen_reply(int type, u_int32_t - break; - #endif - case KEX_C25519_SHA256: -- r = kex_c25519_dec(kex, server_blob, &shared_secret); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_c25519_dec(kex, server_blob, &shared_secret); -+ } - break; - case KEX_KEM_SNTRUP761X25519_SHA512: -- r = kex_kem_sntrup761x25519_dec(kex, server_blob, -- &shared_secret); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_kem_sntrup761x25519_dec(kex, server_blob, -+ &shared_secret); -+ } - break; - case KEX_KEM_MLKEM768X25519_SHA256: -- r = kex_kem_mlkem768x25519_dec(kex, server_blob, -- &shared_secret); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_kem_mlkem768x25519_dec(kex, server_blob, -+ &shared_secret); -+ } - break; - default: - r = SSH_ERR_INVALID_ARGUMENT; -@@ -312,16 +343,31 @@ input_kex_gen_init(int type, u_int32_t s - break; - #endif - case KEX_C25519_SHA256: -- r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, -- &shared_secret); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type c25519 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, -+ &shared_secret); -+ } - break; - case KEX_KEM_SNTRUP761X25519_SHA512: -- r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, -- &server_pubkey, &shared_secret); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type sntrup761 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_kem_sntrup761x25519_enc(kex, client_pubkey, -+ &server_pubkey, &shared_secret); -+ } - break; - case KEX_KEM_MLKEM768X25519_SHA256: -- r = kex_kem_mlkem768x25519_enc(kex, client_pubkey, -- &server_pubkey, &shared_secret); -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { -+ r = kex_kem_mlkem768x25519_enc(kex, client_pubkey, -+ &server_pubkey, &shared_secret); -+ } - break; - default: - r = SSH_ERR_INVALID_ARGUMENT; -diff -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c ---- openssh-8.7p1/ssh-ed25519.c.fips3 2022-07-11 16:53:41.428343304 +0200 -+++ openssh-8.7p1/ssh-ed25519.c 2022-07-11 16:56:09.284663661 +0200 -@@ -24,6 +24,7 @@ - - #include - #include -+#include - - #include "log.h" - #include "sshbuf.h" -@@ -52,6 +53,10 @@ ssh_ed25519_sign(const struct sshkey *ke - key->ed25519_sk == NULL || - datalen >= INT_MAX - crypto_sign_ed25519_BYTES) - return SSH_ERR_INVALID_ARGUMENT; -+ if (FIPS_mode()) { -+ logit_f("Ed25519 keys are not allowed in FIPS mode"); -+ return SSH_ERR_INVALID_ARGUMENT; -+ } - smlen = slen = datalen + crypto_sign_ed25519_BYTES; - if ((sig = malloc(slen)) == NULL) - return SSH_ERR_ALLOC_FAIL; -@@ -108,6 +113,10 @@ ssh_ed25519_verify(const struct sshkey * - dlen >= INT_MAX - crypto_sign_ed25519_BYTES || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; -+ if (FIPS_mode()) { -+ logit_f("Ed25519 keys are not allowed in FIPS mode"); -+ return SSH_ERR_INVALID_ARGUMENT; -+ } - - if ((b = sshbuf_from(sig, siglen)) == NULL) - return SSH_ERR_ALLOC_FAIL; -diff -up openssh-9.9p1/kex.c.xxx openssh-9.9p1/kex.c ---- openssh-9.9p1/kex.c.xxx 2024-10-11 12:44:08.087426597 +0200 -+++ openssh-9.9p1/kex.c 2024-10-11 14:00:10.404714521 +0200 -@@ -40,6 +40,7 @@ - #ifdef WITH_OPENSSL - #include - #include -+#include - # ifdef HAVE_EVP_KDF_CTX_NEW - # include - # include -@@ -109,7 +110,7 @@ kex_proposal_populate_entries(struct ssh - - /* Append EXT_INFO signalling to KexAlgorithms */ - if (kexalgos == NULL) -- kexalgos = defprop[PROPOSAL_KEX_ALGS]; -+ kexalgos = FIPS_mode() ? KEX_DEFAULT_KEX_FIPS : defprop[PROPOSAL_KEX_ALGS]; - if ((cp = kex_names_cat(kexalgos, ssh->kex->server ? - "ext-info-s,kex-strict-s-v00@openssh.com" : - "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) + if ((impl = sshkey_impl_from_key(key)) == NULL) + return SSH_ERR_KEY_TYPE_UNKNOWN; + return impl->funcs->verify(key, sig, siglen, data, dlen, +-- +2.49.0 + diff --git a/0043-openssh-8.7p1-ssh-manpage.patch b/0043-openssh-8.7p1-ssh-manpage.patch new file mode 100644 index 0000000..89c6ea1 --- /dev/null +++ b/0043-openssh-8.7p1-ssh-manpage.patch @@ -0,0 +1,47 @@ +From 299a602802d7c7d121306eb2aeae1502871a35cb Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 43/50] openssh-8.7p1-ssh-manpage + +--- + ssh.1 | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/ssh.1 b/ssh.1 +index 6a9fbdc5..755cdef2 100644 +--- a/ssh.1 ++++ b/ssh.1 +@@ -510,12 +510,12 @@ For full details of the options listed below, and their possible values, see + .It BatchMode + .It BindAddress + .It BindInterface +-.It CASignatureAlgorithms + .It CanonicalDomains + .It CanonicalizeFallbackLocal + .It CanonicalizeHostname + .It CanonicalizeMaxDots + .It CanonicalizePermittedCNAMEs ++.It CASignatureAlgorithms + .It CertificateFile + .It ChannelTimeout + .It CheckHostIP +@@ -528,6 +528,7 @@ For full details of the options listed below, and their possible values, see + .It ControlPath + .It ControlPersist + .It DynamicForward ++.It EnableSSHKeysign + .It EnableEscapeCommandline + .It EnableSSHKeysign + .It EscapeChar +@@ -588,6 +589,8 @@ For full details of the options listed below, and their possible values, see + .It RemoteCommand + .It RemoteForward + .It RequestTTY ++.It RevokedHostKeys ++.It SecurityKeyProvider + .It RequiredRSASize + .It RevokedHostKeys + .It SecurityKeyProvider +-- +2.49.0 + diff --git a/openssh-8.7p1-negotiate-supported-algs.patch b/0044-openssh-8.7p1-negotiate-supported-algs.patch similarity index 74% rename from openssh-8.7p1-negotiate-supported-algs.patch rename to 0044-openssh-8.7p1-negotiate-supported-algs.patch index c4d86e7..f4c3b8a 100644 --- a/openssh-8.7p1-negotiate-supported-algs.patch +++ b/0044-openssh-8.7p1-negotiate-supported-algs.patch @@ -1,6 +1,17 @@ -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 +From 5c92430c08ac392b5b2ace899cc043247c923734 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 44/50] openssh-8.7p1-negotiate-supported-algs + +--- + regress/hostkey-agent.sh | 32 +++++++++++++++++++++++++------- + sshconnect2.c | 17 +++++++++++++++-- + 2 files changed, 40 insertions(+), 9 deletions(-) + +diff --git a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh +index 28dcfe17..b9e716dc 100644 +--- a/regress/hostkey-agent.sh ++++ b/regress/hostkey-agent.sh @@ -17,8 +17,21 @@ trace "make CA key" ${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA" @@ -24,7 +35,7 @@ diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostke ${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 +@@ -32,12 +45,16 @@ rm $OBJ/agent-ca # Don't need CA private any more either unset SSH_AUTH_SOCK @@ -44,10 +55,10 @@ diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostke ( 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 +@@ -50,15 +67,16 @@ for k in $SSH_KEYTYPES ; do done - SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com'` + SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com' | maybe_filter_sk` +SSH_ACCEPTED_CERTTYPES=`echo "$SSH_CERTTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"` # Prepare sshd_proxy for certificates. @@ -63,7 +74,7 @@ diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostke 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" >> +@@ -70,7 +88,7 @@ echo "HostKeyAlgorithms $HOSTKEYALGS" >> $OBJ/sshd_proxy ( printf '@cert-authority localhost-with-alias ' ; cat $OBJ/agent-ca.pub) > $OBJ/known_hosts @@ -72,10 +83,11 @@ diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostke 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 +diff --git a/sshconnect2.c b/sshconnect2.c +index 14f7671a..ad3f560f 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -221,7 +221,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, const struct ssh_conn_info *cinfo) { char *myproposal[PROPOSAL_MAX]; @@ -84,7 +96,7 @@ diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c int r, use_known_hosts_order = 0; #if defined(GSSAPI) && defined(WITH_OPENSSL) -@@ -260,10 +260,22 @@ ssh_kex2(struct ssh *ssh, char *host, st +@@ -257,10 +257,22 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, if (use_known_hosts_order) hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo); @@ -108,7 +120,7 @@ diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c #if defined(GSSAPI) && defined(WITH_OPENSSL) if (options.gss_keyex) { -@@ -303,6 +315,7 @@ ssh_kex2(struct ssh *ssh, char *host, st +@@ -304,6 +316,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, #endif free(hkalgs); @@ -116,3 +128,6 @@ diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) +-- +2.49.0 + diff --git a/openssh-9.0p1-evp-fips-kex.patch b/0045-openssh-9.0p1-evp-fips-kex.patch similarity index 90% rename from openssh-9.0p1-evp-fips-kex.patch rename to 0045-openssh-9.0p1-evp-fips-kex.patch index 36fd1cf..610cea0 100644 --- a/openssh-9.0p1-evp-fips-kex.patch +++ b/0045-openssh-9.0p1-evp-fips-kex.patch @@ -1,6 +1,20 @@ -diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/dh.c openssh-9.0p1-patched/dh.c ---- openssh-9.0p1/dh.c 2023-05-25 09:24:28.730868316 +0200 -+++ openssh-9.0p1-patched/dh.c 2023-05-25 09:23:44.841379532 +0200 +From be23afbab800c9b5ffea56b3f410a04156c08df2 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 45/50] openssh-9.0p1-evp-fips-kex + +--- + dh.c | 98 +++++++++++++++++++++++++++++++++----- + kex.c | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + kex.h | 6 +++ + kexdh.c | 52 ++++++++++++++++++-- + kexecdh.c | 129 ++++++++++++++++++++++++++++++++++++++++---------- + 5 files changed, 382 insertions(+), 42 deletions(-) + +diff --git a/dh.c b/dh.c +index 8c9a29fa..ea0a0b09 100644 +--- a/dh.c ++++ b/dh.c @@ -37,6 +37,9 @@ #include #include @@ -11,7 +25,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x #include "dh.h" #include "pathnames.h" -@@ -290,10 +293,15 @@ +@@ -290,10 +293,15 @@ dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) int dh_gen_key(DH *dh, int need) { @@ -30,7 +44,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x if (need < 0 || dh_p == NULL || (pbits = BN_num_bits(dh_p)) <= 0 || -@@ -301,19 +309,85 @@ +@@ -301,19 +309,85 @@ dh_gen_key(DH *dh, int need) return SSH_ERR_INVALID_ARGUMENT; if (need < 256) need = 256; @@ -125,10 +139,11 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x } DH * -diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.c openssh-9.0p1-patched/kex.c ---- openssh-9.0p1/kex.c 2023-05-25 09:24:28.731868327 +0200 -+++ openssh-9.0p1-patched/kex.c 2023-05-25 09:23:44.841379532 +0200 -@@ -1623,3 +1623,142 @@ +diff --git a/kex.c b/kex.c +index 71fbe5cb..ce6a7b81 100644 +--- a/kex.c ++++ b/kex.c +@@ -1614,3 +1614,142 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, return r; } @@ -271,9 +286,34 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x + return r; +} +#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.0p1/kexdh.c openssh-9.0p1-patched/kexdh.c ---- openssh-9.0p1/kexdh.c 2023-05-25 09:24:28.674867692 +0200 -+++ openssh-9.0p1-patched/kexdh.c 2023-05-25 09:25:28.494533889 +0200 +diff --git a/kex.h b/kex.h +index 6a55aadf..48f3bb87 100644 +--- a/kex.h ++++ b/kex.h +@@ -37,6 +37,9 @@ + # include + # include + # include ++# include ++# include ++# include + # ifdef OPENSSL_HAS_ECC + # include + # else /* OPENSSL_HAS_ECC */ +@@ -311,6 +314,9 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], + const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); ++int kex_create_evp_dh(EVP_PKEY **, const BIGNUM *, const BIGNUM *, ++ const BIGNUM *, const BIGNUM *, const BIGNUM *); ++int kex_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey); + + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) + void dump_digest(const char *, const u_char *, int); +diff --git a/kexdh.c b/kexdh.c +index 0faab21b..32e1de51 100644 +--- a/kexdh.c ++++ b/kexdh.c @@ -35,6 +35,10 @@ #include "openbsd-compat/openssl-compat.h" @@ -285,7 +325,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x #include "sshkey.h" #include "kex.h" -@@ -83,9 +87,12 @@ +@@ -83,9 +87,12 @@ int kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) { BIGNUM *shared_secret = NULL; @@ -299,7 +339,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x #ifdef DEBUG_KEXDH fprintf(stderr, "dh_pub= "); -@@ -100,24 +107,59 @@ +@@ -100,24 +107,59 @@ kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) r = SSH_ERR_MESSAGE_INCOMPLETE; goto out; } @@ -363,32 +403,10 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x return r; } -diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.h openssh-9.0p1-patched/kex.h ---- openssh-9.0p1/kex.h 2023-05-25 09:24:28.725868260 +0200 -+++ openssh-9.0p1-patched/kex.h 2023-05-25 09:23:44.841379532 +0200 -@@ -33,6 +33,9 @@ - # include - # include - # include -+# include -+# include -+# include - # ifdef OPENSSL_HAS_ECC - # include - # else /* OPENSSL_HAS_ECC */ -@@ -283,6 +286,9@@ - const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) - __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) - __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); -+int kex_create_evp_dh(EVP_PKEY **, const BIGNUM *, const BIGNUM *, -+ const BIGNUM *, const BIGNUM *, const BIGNUM *); -+int kex_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey); - - #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) - void dump_digest(const char *, const u_char *, int); -diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../openssh-8.7p1/kexecdh.c ./kexecdh.c ---- ../openssh-8.7p1/kexecdh.c 2021-08-20 06:03:49.000000000 +0200 -+++ ./kexecdh.c 2023-04-13 14:30:14.882449593 +0200 +diff --git a/kexecdh.c b/kexecdh.c +index efb2e55a..d92ba54f 100644 +--- a/kexecdh.c ++++ b/kexecdh.c @@ -35,17 +35,57 @@ #include @@ -447,7 +465,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x int kex_ecdh_keypair(struct kex *kex) { -@@ -55,11 +95,7 @@ +@@ -55,11 +95,7 @@ kex_ecdh_keypair(struct kex *kex) struct sshbuf *buf = NULL; int r; @@ -460,7 +478,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } -@@ -101,11 +137,7 @@ +@@ -101,11 +137,7 @@ kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob, *server_blobp = NULL; *shared_secretp = NULL; @@ -473,7 +491,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } -@@ -140,11 +172,21 @@ +@@ -140,11 +172,21 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, { struct sshbuf *buf = NULL; BIGNUM *shared_secret = NULL; @@ -498,7 +516,7 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x *shared_secretp = NULL; if ((buf = sshbuf_new()) == NULL) { -@@ -153,45 +195,82 @@ +@@ -153,45 +195,82 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, } if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0) goto out; @@ -593,3 +611,6 @@ diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x sshbuf_free(buf); return r; } +-- +2.49.0 + diff --git a/openssh-8.7p1-nohostsha1proof.patch b/0046-openssh-8.7p1-nohostsha1proof.patch similarity index 69% rename from openssh-8.7p1-nohostsha1proof.patch rename to 0046-openssh-8.7p1-nohostsha1proof.patch index dae0932..9e75c8a 100644 --- a/openssh-8.7p1-nohostsha1proof.patch +++ b/0046-openssh-8.7p1-nohostsha1proof.patch @@ -1,7 +1,27 @@ -diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c ---- openssh-8.7p1/compat.c.sshrsacheck 2023-01-12 13:29:06.338710923 +0100 -+++ openssh-8.7p1/compat.c 2023-01-12 13:29:06.357711165 +0100 -@@ -43,6 +43,7 @@ void +From e4ca3b9dba1cc832a9974493c91207d42e218a68 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 46/50] openssh-8.7p1-nohostsha1proof + +--- + compat.c | 6 +++++ + compat.h | 2 +- + monitor.c | 27 ++++++++++++++++------ + regress/unittests/kex/test_kex.c | 3 ++- + regress/unittests/sshkey/test_file.c | 3 ++- + regress/unittests/sshkey/test_fuzz.c | 3 ++- + regress/unittests/sshkey/test_sshkey.c | 32 +++++++++++++++++--------- + serverloop.c | 6 ++++- + ssh-rsa.c | 3 ++- + sshconnect2.c | 8 +++++++ + sshd-session.c | 21 +++++++++++++++++ + 11 files changed, 90 insertions(+), 24 deletions(-) + +diff --git a/compat.c b/compat.c +index b59f0bfc..4e611dc3 100644 +--- a/compat.c ++++ b/compat.c +@@ -42,6 +42,7 @@ void compat_banner(struct ssh *ssh, const char *version) { int i; @@ -9,7 +29,7 @@ diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c static struct { char *pat; int bugs; -@@ -145,16 +146,21 @@ compat_banner(struct ssh *ssh, const cha +@@ -125,16 +126,21 @@ compat_banner(struct ssh *ssh, const char *version) }; /* process table, return first match */ @@ -31,9 +51,10 @@ diff -up openssh-8.7p1/compat.c.sshrsacheck openssh-8.7p1/compat.c } /* Always returns pointer to allocated memory, caller must free. */ -diff -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h ---- openssh-8.7p1/compat.h.sshrsacheck 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/compat.h 2023-01-12 13:29:06.358711178 +0100 +diff --git a/compat.h b/compat.h +index 1a19060f..2e6db5bf 100644 +--- a/compat.h ++++ b/compat.h @@ -30,7 +30,7 @@ #define SSH_BUG_UTF8TTYMODE 0x00000001 #define SSH_BUG_SIGTYPE 0x00000002 @@ -43,24 +64,28 @@ diff -up openssh-8.7p1/compat.h.sshrsacheck openssh-8.7p1/compat.h #define SSH_OLD_SESSIONID 0x00000010 /* #define unused 0x00000020 */ #define SSH_BUG_DEBUG 0x00000040 -diff -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c ---- openssh-8.7p1/monitor.c.sshrsacheck 2023-01-20 13:07:54.279676981 +0100 -+++ openssh-8.7p1/monitor.c 2023-01-20 15:01:07.007821379 +0100 -@@ -660,11 +660,12 @@ mm_answer_sign(struct ssh *ssh, int sock - struct sshkey *key; +diff --git a/monitor.c b/monitor.c +index fbc35782..19cb058e 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -747,11 +747,12 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) + struct sshkey *pubkey, *key; struct sshbuf *sigbuf = NULL; u_char *p = NULL, *signature = NULL; - char *alg = NULL; +- size_t datlen, siglen; +- int r, is_proof = 0, keyid; +- u_int compat; + char *alg = NULL, *effective_alg; - size_t datlen, siglen, alglen; - int r, is_proof = 0; - u_int keyid, compat; ++ size_t datlen, siglen, alglen; ++ int r, is_proof = 0; ++ u_int keyid, compat; const char proof_req[] = "hostkeys-prove-00@openssh.com"; + const char safe_rsa[] = "rsa-sha2-256"; debug3_f("entering"); -@@ -719,18 +720,30 @@ mm_answer_sign(struct ssh *ssh, int sock +@@ -809,18 +810,30 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) } if ((key = get_hostkey_by_index(keyid)) != NULL) { @@ -94,10 +119,11 @@ diff -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c is_proof ? "hostkey proof" : "KEX", siglen); sshbuf_reset(m); -diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p1/regress/unittests/kex/test_kex.c ---- openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck 2023-01-26 13:34:52.645743677 +0100 -+++ openssh-8.7p1/regress/unittests/kex/test_kex.c 2023-01-26 13:36:56.220745823 +0100 -@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype, +diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c +index caf8f57f..09016aea 100644 +--- a/regress/unittests/kex/test_kex.c ++++ b/regress/unittests/kex/test_kex.c +@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype, int bits) memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); if (kex != NULL) kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; @@ -107,10 +133,11 @@ diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p ASSERT_PTR_NE(keyname, NULL); kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); -diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_file.c ---- openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck 2023-01-26 12:04:55.946343408 +0100 -+++ openssh-8.7p1/regress/unittests/sshkey/test_file.c 2023-01-26 12:06:35.235164432 +0100 -@@ -110,6 +110,7 @@ sshkey_file_tests(void) +diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c +index 3babe604..cc80fe97 100644 +--- a/regress/unittests/sshkey/test_file.c ++++ b/regress/unittests/sshkey/test_file.c +@@ -109,6 +109,7 @@ sshkey_file_tests(void) sshkey_free(k2); TEST_DONE(); @@ -118,7 +145,7 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh- TEST_START("load RSA cert with SHA1 signature"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0); ASSERT_PTR_NE(k2, NULL); -@@ -117,7 +118,7 @@ sshkey_file_tests(void) +@@ -116,7 +117,7 @@ sshkey_file_tests(void) ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa"); sshkey_free(k2); @@ -127,10 +154,11 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh- TEST_START("load RSA cert with SHA512 signature"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0); -diff -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c ---- openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck 2023-01-26 12:10:37.533168013 +0100 -+++ openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c 2023-01-26 12:15:35.637631860 +0100 -@@ -333,13 +333,14 @@ sshkey_fuzz_tests(void) +diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c +index 0aff7c9b..951122e1 100644 +--- a/regress/unittests/sshkey/test_fuzz.c ++++ b/regress/unittests/sshkey/test_fuzz.c +@@ -338,13 +338,14 @@ sshkey_fuzz_tests(void) TEST_DONE(); #ifdef WITH_OPENSSL @@ -146,10 +174,11 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh- TEST_START("fuzz RSA SHA256 sig"); buf = load_file("rsa_1"); -diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c ---- openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck 2023-01-26 11:02:52.339413463 +0100 -+++ openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c 2023-01-26 11:58:42.324253896 +0100 -@@ -60,6 +60,9 @@ build_cert(struct sshbuf *b, struct sshk +diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c +index 5bf4b65c..6d0a35bb 100644 +--- a/regress/unittests/sshkey/test_sshkey.c ++++ b/regress/unittests/sshkey/test_sshkey.c +@@ -61,6 +61,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type, u_char *sigblob; size_t siglen; @@ -159,7 +188,7 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss ca_buf = sshbuf_new(); ASSERT_PTR_NE(ca_buf, NULL); ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0); -@@ -101,8 +104,9 @@ build_cert(struct sshbuf *b, struct sshk +@@ -102,8 +105,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type, ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, @@ -171,7 +200,7 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss free(sigblob); sshbuf_free(ca_buf); -@@ -119,16 +123,22 @@ signature_test(struct sshkey *k, struct +@@ -120,16 +124,22 @@ signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg, { size_t len; u_char *sig; @@ -202,7 +231,7 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss free(sig); } -@@ -514,7 +524,7 @@ sshkey_tests(void) +@@ -526,7 +536,7 @@ sshkey_tests(void) ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, NULL), 0); k3 = get_private("rsa_1"); @@ -211,9 +240,10 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4), SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); ASSERT_PTR_EQ(k4, NULL); -diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c ---- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100 -+++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100 +diff --git a/serverloop.c b/serverloop.c +index 40ddfb04..9c5b1567 100644 +--- a/serverloop.c ++++ b/serverloop.c @@ -80,6 +80,7 @@ #include "auth-options.h" #include "serverloop.h" @@ -222,10 +252,11 @@ diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c extern ServerOptions options; -@@ -737,6 +737,10 @@ server_input_hostkeys_prove(struct ssh * +@@ -699,7 +700,10 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) sigalg = "rsa-sha2-256"; } +- + if (ssh->compat & SSH_RH_RSASIGSHA && sigalg == NULL) { + sigalg = "rsa-sha2-512"; + debug3_f("SHA1 signature is not supported, falling back to %s", sigalg); @@ -233,10 +264,25 @@ diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c debug3_f("sign %s key (index %d) using sigalg %s", sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); if ((r = sshbuf_put_cstring(sigbuf, -diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c ---- openssh-8.7p1/sshconnect2.c.sshrsacheck 2023-01-25 15:33:29.140353651 +0100 -+++ openssh-8.7p1/sshconnect2.c 2023-01-25 15:59:34.225364883 +0100 -@@ -1461,6 +1464,14 @@ identity_sign(struct identity *id, u_cha +diff --git a/ssh-rsa.c b/ssh-rsa.c +index 6c2f771a..8dd4ab01 100644 +--- a/ssh-rsa.c ++++ b/ssh-rsa.c +@@ -509,7 +509,8 @@ ssh_rsa_verify(const struct sshkey *key, + ret = SSH_ERR_INVALID_ARGUMENT; + goto out; + } +- if (hash_alg != want_alg) { ++ if (hash_alg != want_alg && want_alg != SSH_DIGEST_SHA1) { ++ debug_f("Unexpected digest algorithm: got %d, wanted %d", hash_alg, want_alg); + ret = SSH_ERR_SIGNATURE_INVALID; + goto out; + } +diff --git a/sshconnect2.c b/sshconnect2.c +index ad3f560f..3941e089 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -1434,6 +1434,14 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, retried = 1; goto retry_pin; } @@ -251,23 +297,11 @@ diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c goto out; } -diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c ---- openssh-8.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100 -+++ openssh-8.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100 -@@ -254,7 +254,8 @@ ssh_rsa_verify(const struct sshkey *key, - ret = SSH_ERR_INVALID_ARGUMENT; - goto out; - } -- if (hash_alg != want_alg) { -+ if (hash_alg != want_alg && want_alg != SSH_DIGEST_SHA1) { -+ debug_f("Unexpected digest algorithm: got %d, wanted %d", hash_alg, want_alg); - ret = SSH_ERR_SIGNATURE_INVALID; - goto out; - } -diff -up openssh-9.8p1/sshd-session.c.xxx openssh-9.8p1/sshd-session.c ---- openssh-9.8p1/sshd-session.c.xxx 2024-07-23 15:08:14.794350818 +0200 -+++ openssh-9.8p1/sshd-session.c 2024-07-23 15:40:21.658456636 +0200 -@@ -1305,6 +1305,27 @@ main(int ac, char **av) +diff --git a/sshd-session.c b/sshd-session.c +index a808ac9a..c3349a8a 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -1316,6 +1316,27 @@ main(int ac, char **av) check_ip_options(ssh); @@ -295,3 +329,6 @@ diff -up openssh-9.8p1/sshd-session.c.xxx openssh-9.8p1/sshd-session.c /* Prepare the channels layer */ channel_init_channels(ssh); channel_set_af(ssh, options.address_family); +-- +2.49.0 + diff --git a/0047-openssh-9.6p1-pam-rhost.patch b/0047-openssh-9.6p1-pam-rhost.patch new file mode 100644 index 0000000..968e60a --- /dev/null +++ b/0047-openssh-9.6p1-pam-rhost.patch @@ -0,0 +1,25 @@ +From 497de886faaddec60b7ad1013396c7d4f3145968 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 47/50] openssh-9.6p1-pam-rhost + +--- + auth-pam.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/auth-pam.c b/auth-pam.c +index a042c3c8..a321e0d3 100644 +--- a/auth-pam.c ++++ b/auth-pam.c +@@ -741,7 +741,7 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt) + sshpam_laddr = get_local_ipaddr( + ssh_packet_get_connection_in(ssh)); + } +- if (sshpam_rhost != NULL) { ++ if (sshpam_rhost != NULL && strcmp(sshpam_rhost, "UNKNOWN") != 0) { + debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost); + sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, + sshpam_rhost); +-- +2.49.0 + diff --git a/0048-openssh-9.9p1-separate-keysign.patch b/0048-openssh-9.9p1-separate-keysign.patch new file mode 100644 index 0000000..8d0f691 --- /dev/null +++ b/0048-openssh-9.9p1-separate-keysign.patch @@ -0,0 +1,25 @@ +From b97b1040bc0918fe9be89cdb482d046270e92d9c Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 48/50] openssh-9.9p1-separate-keysign + +--- + ssh_config.5 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ssh_config.5 b/ssh_config.5 +index a43b2a27..9d5da2a6 100644 +--- a/ssh_config.5 ++++ b/ssh_config.5 +@@ -797,7 +797,7 @@ or + This option should be placed in the non-hostspecific section. + See + .Xr ssh-keysign 8 +-for more information. ++for more information. ssh-keysign should be installed explicitly. + .It Cm EscapeChar + Sets the escape character (default: + .Ql ~ ) . +-- +2.49.0 + diff --git a/openssh-9.9p1-openssl-mlkem.patch b/0049-openssh-9.9p1-openssl-mlkem.patch similarity index 94% rename from openssh-9.9p1-openssl-mlkem.patch rename to 0049-openssh-9.9p1-openssl-mlkem.patch index e39bb67..e04d194 100644 --- a/openssh-9.9p1-openssl-mlkem.patch +++ b/0049-openssh-9.9p1-openssl-mlkem.patch @@ -1,8 +1,18 @@ +From 0a621a2ccb8444e4c6da906b0e112e0522658122 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 49/50] openssh-9.9p1-openssl-mlkem + +--- + kex-names.c | 20 +++ + kexmlkem768x25519.c | 291 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 311 insertions(+) + diff --git a/kex-names.c b/kex-names.c -index ec840c1f..c0d3be11 100644 +index cd3902ad..36a953ab 100644 --- a/kex-names.c +++ b/kex-names.c -@@ -90,6 +90,19 @@ static const struct kexalg kexalgs[] = { +@@ -108,6 +108,19 @@ static const struct kexalg gss_kexalgs[] = { { NULL, 0, -1, -1}, }; @@ -22,7 +32,7 @@ index ec840c1f..c0d3be11 100644 static char * kex_alg_list_internal(char sep, const struct kexalg *algs) { -@@ -98,6 +111,9 @@ kex_alg_list_internal(char sep, const struct kexalg *algs) +@@ -116,6 +129,9 @@ kex_alg_list_internal(char sep, const struct kexalg *algs) const struct kexalg *k; for (k = algs; k->name != NULL; k++) { @@ -32,7 +42,7 @@ index ec840c1f..c0d3be11 100644 if (ret != NULL) ret[rlen++] = sep; nlen = strlen(k->name); -@@ -117,6 +133,10 @@ kex_alg_by_name(const char *name) +@@ -147,6 +163,10 @@ kex_alg_by_name(const char *name) { const struct kexalg *k; @@ -383,3 +393,6 @@ index 2b5d3960..670049dc 100644 } #else /* USE_MLKEM768X25519 */ int +-- +2.49.0 + diff --git a/0050-openssh-9.9p2-error_processing.patch b/0050-openssh-9.9p2-error_processing.patch new file mode 100644 index 0000000..aed1c30 --- /dev/null +++ b/0050-openssh-9.9p2-error_processing.patch @@ -0,0 +1,25 @@ +From fd32e753ae7f3b314712e6aa8b2bed3c1fca1ef5 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Fri, 16 May 2025 14:53:54 +0200 +Subject: [PATCH 50/51] openssh-9.9p2-error_processing + +--- + ssh-agent.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ssh-agent.c b/ssh-agent.c +index 798bf9b6..dfb6ac72 100644 +--- a/ssh-agent.c ++++ b/ssh-agent.c +@@ -1377,6 +1377,8 @@ process_add_identity(SocketEntry *e) + if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || + k == NULL || + (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { ++ if (!r) /* k == NULL */ ++ r = SSH_ERR_INTERNAL_ERROR; + error_fr(r, "parse"); + goto out; + } +-- +2.49.0 + diff --git a/1000-openssh-coverity.patch b/1000-openssh-coverity.patch new file mode 100644 index 0000000..88362eb --- /dev/null +++ b/1000-openssh-coverity.patch @@ -0,0 +1,257 @@ +From 24c411970682dc67873c36bac05b4b460d68a628 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Thu, 15 May 2025 13:43:29 +0200 +Subject: [PATCH 50/50] openssh-6.7p1-coverity + +--- + auth-krb5.c | 2 ++ + gss-genr.c | 3 ++- + krl.c | 3 +++ + loginrec.c | 2 ++ + misc.c | 3 +++ + monitor.c | 4 ++-- + openbsd-compat/bindresvport.c | 2 +- + openbsd-compat/bsd-pselect.c | 8 ++++---- + readconf.c | 1 + + servconf.c | 5 +++-- + serverloop.c | 2 +- + ssh-agent.c | 1 + + ssh-keygen.c | 3 +++ + 13 files changed, 28 insertions(+), 11 deletions(-) + +diff --git a/auth-krb5.c b/auth-krb5.c +index bae153c9..209a3265 100644 +--- a/auth-krb5.c ++++ b/auth-krb5.c +@@ -427,6 +427,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm + umask(old_umask); + if (tmpfd == -1) { + logit("mkstemp(): %.100s", strerror(oerrno)); ++ free(ccname); + return oerrno; + } + +@@ -434,6 +435,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm + oerrno = errno; + logit("fchmod(): %.100s", strerror(oerrno)); + close(tmpfd); ++ free(ccname); + return oerrno; + } + /* make sure the KRB5CCNAME is set for non-standard location */ +diff --git a/gss-genr.c b/gss-genr.c +index 3034370c..c357e973 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, + enclen = __b64_ntop(digest, + ssh_digest_bytes(SSH_DIGEST_MD5), encoded, + ssh_digest_bytes(SSH_DIGEST_MD5) * 2); +- ++#pragma GCC diagnostic ignored "-Wstringop-overflow" + cp = strncpy(s, kex, strlen(kex)); ++#pragma GCC diagnostic pop + for ((p = strsep(&cp, ",")); p && *p != '\0'; + (p = strsep(&cp, ","))) { + if (sshbuf_len(buf) != 0 && +diff --git a/krl.c b/krl.c +index 0d0f6953..d8517f12 100644 +--- a/krl.c ++++ b/krl.c +@@ -1202,6 +1202,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) + return r; + erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); + free(rb.blob); ++ rb.blob = NULL; /* make coverity happy */ + if (erb != NULL) { + KRL_DBG(("revoked by key SHA1")); + return SSH_ERR_KEY_REVOKED; +@@ -1212,6 +1213,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) + return r; + erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb); + free(rb.blob); ++ rb.blob = NULL; /* make coverity happy */ + if (erb != NULL) { + KRL_DBG(("revoked by key SHA256")); + return SSH_ERR_KEY_REVOKED; +@@ -1223,6 +1225,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) + return r; + erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); + free(rb.blob); ++ rb.blob = NULL; /* make coverity happy */ + if (erb != NULL) { + KRL_DBG(("revoked by explicit key")); + return SSH_ERR_KEY_REVOKED; +diff --git a/loginrec.c b/loginrec.c +index c4a9bd48..2583612c 100644 +--- a/loginrec.c ++++ b/loginrec.c +@@ -683,9 +683,11 @@ construct_utmp(struct logininfo *li, + */ + + /* Use strncpy because we don't necessarily want null termination */ ++ /* coverity[buffer_size_warning : FALSE] */ + strncpy(ut->ut_name, li->username, + MIN_SIZEOF(ut->ut_name, li->username)); + # ifdef HAVE_HOST_IN_UTMP ++ /* coverity[buffer_size_warning : FALSE] */ + strncpy(ut->ut_host, li->hostname, + MIN_SIZEOF(ut->ut_host, li->hostname)); + # endif +diff --git a/misc.c b/misc.c +index 09722962..cd71c1b2 100644 +--- a/misc.c ++++ b/misc.c +@@ -1556,6 +1556,8 @@ sanitise_stdfd(void) + } + if (nullfd > STDERR_FILENO) + close(nullfd); ++ /* coverity[leaked_handle : FALSE]*/ ++ /* coverity[leaked_handle : FALSE]*/ + } + + char * +@@ -2749,6 +2751,7 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) + } + if (devnull > STDERR_FILENO) + close(devnull); ++ /* coverity[leaked_handle : FALSE]*/ + return ret; + } + +diff --git a/monitor.c b/monitor.c +index 19cb058e..58fbac9d 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -415,7 +415,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) + mm_get_keystate(ssh, pmonitor); + + /* Drain any buffered messages from the child */ +- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) ++ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) + ; + + if (pmonitor->m_recvfd >= 0) +@@ -1813,7 +1813,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) + s->ptymaster = s->ptyfd; + + debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd); +- ++ /* coverity[leaked_handle : FALSE] */ + return (0); + + error: +diff --git a/openbsd-compat/bindresvport.c b/openbsd-compat/bindresvport.c +index 346c7fe5..f42792fd 100644 +--- a/openbsd-compat/bindresvport.c ++++ b/openbsd-compat/bindresvport.c +@@ -59,7 +59,7 @@ bindresvport_sa(int sd, struct sockaddr *sa) + struct sockaddr_in6 *in6; + u_int16_t *portp; + u_int16_t port; +- socklen_t salen; ++ socklen_t salen = sizeof(struct sockaddr_storage); + int i; + + if (sa == NULL) { +diff --git a/openbsd-compat/bsd-pselect.c b/openbsd-compat/bsd-pselect.c +index 26bdc3e0..8e2939b9 100644 +--- a/openbsd-compat/bsd-pselect.c ++++ b/openbsd-compat/bsd-pselect.c +@@ -85,13 +85,13 @@ pselect_notify_setup(void) + static void + pselect_notify_parent(void) + { +- if (notify_pipe[1] != -1) ++ if (notify_pipe[1] >= 0) + (void)write(notify_pipe[1], "", 1); + } + static void + pselect_notify_prepare(fd_set *readset) + { +- if (notify_pipe[0] != -1) ++ if (notify_pipe[0] >= 0) + FD_SET(notify_pipe[0], readset); + } + static void +@@ -99,8 +99,8 @@ pselect_notify_done(fd_set *readset) + { + char c; + +- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) { +- while (read(notify_pipe[0], &c, 1) != -1) ++ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) { ++ while (read(notify_pipe[0], &c, 1) >= 0) + debug2_f("reading"); + FD_CLR(notify_pipe[0], readset); + } +diff --git a/readconf.c b/readconf.c +index ea9d293c..9680c38c 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -2164,6 +2164,7 @@ parse_pubkey_algos: + } else if (r != 0) { + error("%.200s line %d: glob failed for %s.", + filename, linenum, arg2); ++ free(arg2); + goto out; + } + free(arg2); +diff --git a/servconf.c b/servconf.c +index 8b708cbf..e7e4ad04 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -2293,8 +2293,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, + if (*activep && *charptr == NULL) { + *charptr = tilde_expand_filename(arg, getuid()); + /* increase optional counter */ +- if (intptr != NULL) +- *intptr = *intptr + 1; ++ /* DEAD CODE intptr is still NULL ;) ++ if (intptr != NULL) ++ *intptr = *intptr + 1; */ + } + break; + +diff --git a/serverloop.c b/serverloop.c +index 9c5b1567..768ee9fa 100644 +--- a/serverloop.c ++++ b/serverloop.c +@@ -511,7 +511,7 @@ server_request_tun(struct ssh *ssh) + debug_f("invalid tun"); + goto done; + } +- if (auth_opts->force_tun_device != -1) { ++ if (auth_opts->force_tun_device >= 0) { + if (tun != SSH_TUNID_ANY && + auth_opts->force_tun_device != (int)tun) + goto done; +diff --git a/ssh-agent.c b/ssh-agent.c +index 798bf9b6..0e39dff7 100644 +--- a/ssh-agent.c ++++ b/ssh-agent.c +@@ -1593,6 +1593,7 @@ sanitize_pkcs11_provider(const char *provider) + + if (pkcs11_uri_parse(provider, uri) != 0) { + error("Failed to parse PKCS#11 URI"); ++ pkcs11_uri_cleanup(uri); + return NULL; + } + /* validate also provider from URI */ +diff --git a/ssh-keygen.c b/ssh-keygen.c +index 792aafde..96b3474d 100644 +--- a/ssh-keygen.c ++++ b/ssh-keygen.c +@@ -2424,6 +2424,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; +-- +2.49.0 + diff --git a/openssh-5.8p2-sigpipe.patch b/openssh-5.8p2-sigpipe.patch deleted file mode 100644 index 554e346..0000000 --- a/openssh-5.8p2-sigpipe.patch +++ /dev/null @@ -1,14 +0,0 @@ -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 -@@ -715,6 +715,9 @@ main(int argc, char **argv) - if (maxfd > fdlim_get(0)) - fdlim_set(maxfd); - fdcon = xcalloc(maxfd, sizeof(con)); -+ -+ signal(SIGPIPE, SIG_IGN); -+ - read_wait = xcalloc(maxfd, sizeof(struct pollfd)); - for (j = 0; j < maxfd; j++) - read_wait[j].fd = -1; - diff --git a/openssh-6.4p1-fromto-remote.patch b/openssh-6.4p1-fromto-remote.patch deleted file mode 100644 index 4a7d849..0000000 --- a/openssh-6.4p1-fromto-remote.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/scp.c b/scp.c -index d98fa67..25d347b 100644 ---- a/scp.c -+++ b/scp.c -@@ -638,7 +638,10 @@ toremote(char *targ, int argc, char **argv) - addargs(&alist, "%s", ssh_program); - addargs(&alist, "-x"); - addargs(&alist, "-oClearAllForwardings=yes"); -- addargs(&alist, "-n"); -+ if (isatty(fileno(stdin))) -+ addargs(&alist, "-t"); -+ else -+ addargs(&alist, "-n"); - for (j = 0; j < remote_remote_args.num; j++) { - addargs(&alist, "%s", - remote_remote_args.list[j]); diff --git a/openssh-6.6.1p1-scp-non-existing-directory.patch b/openssh-6.6.1p1-scp-non-existing-directory.patch deleted file mode 100644 index bb55c0b..0000000 --- a/openssh-6.6.1p1-scp-non-existing-directory.patch +++ /dev/null @@ -1,14 +0,0 @@ ---- a/scp.c -+++ a/scp.c -@@ -1084,6 +1084,10 @@ sink(int argc, char **argv) - free(vect[0]); - continue; - } -+ if (buf[0] == 'C' && ! exists && np[strlen(np)-1] == '/') { -+ errno = ENOTDIR; -+ goto bad; -+ } - omode = mode; - mode |= S_IWUSR; - if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { --- diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch deleted file mode 100644 index ffe0c69..0000000 --- a/openssh-6.7p1-coverity.patch +++ /dev/null @@ -1,248 +0,0 @@ -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)); -+ free(ccname); - return oerrno; - } - -@@ -433,6 +434,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, - oerrno = errno; - logit("fchmod(): %.100s", strerror(oerrno)); - close(tmpfd); -+ free(ccname); - return oerrno; - } - /* make sure the KRB5CCNAME is set for non-standard location */ -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); -- -+#pragma GCC diagnostic ignored "-Wstringop-overflow" - cp = strncpy(s, kex, strlen(kex)); -+#pragma GCC diagnostic pop - for ((p = strsep(&cp, ",")); p && *p != '\0'; - (p = strsep(&cp, ","))) { - if (sshbuf_len(buf) != 0 && -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 -@@ -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); -+ rb.blob = NULL; /* make coverity happy */ - 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, cons - return r; - erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb); - free(rb.blob); -+ rb.blob = NULL; /* make coverity happy */ - 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, cons - return r; - erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); - free(rb.blob); -+ rb.blob = NULL; /* make coverity happy */ - if (erb != NULL) { - KRL_DBG(("revoked by explicit key")); - return SSH_ERR_KEY_REVOKED; -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 */ -+ /* coverity[buffer_size_warning : FALSE] */ - strncpy(ut->ut_name, li->username, - MIN_SIZEOF(ut->ut_name, li->username)); - # ifdef HAVE_HOST_IN_UTMP -+ /* coverity[buffer_size_warning : FALSE] */ - strncpy(ut->ut_host, li->hostname, - MIN_SIZEOF(ut->ut_host, li->hostname)); - # endif -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); -+ /* coverity[leaked_handle : FALSE]*/ -+ /* coverity[leaked_handle : FALSE]*/ - } - - char * -@@ -2511,6 +2513,7 @@ stdfd_devnull(int do_stdin, int do_stdou - } - if (devnull > STDERR_FILENO) - close(devnull); -+ /* coverity[leaked_handle : FALSE]*/ - return ret; - } - -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 */ -- while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) -+ while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) - ; - - if (pmonitor->m_recvfd >= 0) -@@ -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); -- -+ /* coverity[leaked_handle : FALSE] */ - return (0); - - error: -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; -- socklen_t salen; -+ socklen_t salen = sizeof(struct sockaddr_storage); - int i; - - if (sa == NULL) { -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) - { -- if (notify_pipe[1] != -1) -+ if (notify_pipe[1] >= 0) - (void)write(notify_pipe[1], "", 1); - } - static void - pselect_notify_prepare(fd_set *readset) - { -- if (notify_pipe[0] != -1) -+ if (notify_pipe[0] >= 0) - FD_SET(notify_pipe[0], readset); - } - static void -@@ -127,8 +127,8 @@ pselect_notify_done(fd_set *readset) - { - char c; - -- if (notify_pipe[0] != -1 && FD_ISSET(notify_pipe[0], readset)) { -- while (read(notify_pipe[0], &c, 1) != -1) -+ if (notify_pipe[0] >= 0 && FD_ISSET(notify_pipe[0], readset)) { -+ while (read(notify_pipe[0], &c, 1) >= 0) - debug2_f("reading"); - FD_CLR(notify_pipe[0], readset); - } -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); -+ free(arg2); - goto out; - } - free(arg2); -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 */ -- if (intptr != NULL) -- *intptr = *intptr + 1; -+ /* DEAD CODE intptr is still NULL ;) -+ if (intptr != NULL) -+ *intptr = *intptr + 1; */ - } - break; - -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; - } -- if (auth_opts->force_tun_device != -1) { -+ if (auth_opts->force_tun_device >= 0) { - if (tun != SSH_TUNID_ANY && - auth_opts->force_tun_device != (int)tun) - goto done; -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"); -+ pkcs11_uri_cleanup(uri); - return NULL; - } - /* validate also provider from URI */ -diff -up openssh-7.4p1/sshd-session.c.coverity openssh-7.4p1/sshd-session.c ---- openssh-7.4p1/sshd-session.c.coverity 2016-12-23 16:40:26.897788690 +0100 -+++ openssh-7.4p1/sshd-session.c 2016-12-23 16:40:26.904788692 +0100 -@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt) - - privsep_preauth_child(ssh); - setproctitle("%s", "[net]"); -- if (box != NULL) -+ if (box != NULL) { - ssh_sandbox_child(box); -+ free(box); -+ } - - return 0; - } -@@ -2519,8 +2524,11 @@ do_ssh2_kex(struct ssh *ssh) - - if (newstr) - myproposal[PROPOSAL_KEX_ALGS] = newstr; -- else -+ else { - fatal("No supported key exchange algorithms"); -+ free(gss); -+ } -+ /* coverity[leaked_storage: FALSE]*/ - } - #endif - -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-6.8p1-sshdT-output.patch b/openssh-6.8p1-sshdT-output.patch deleted file mode 100644 index 156e66d..0000000 --- a/openssh-6.8p1-sshdT-output.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up openssh/servconf.c.sshdt openssh/servconf.c ---- openssh/servconf.c.sshdt 2015-06-24 11:42:29.041078704 +0200 -+++ openssh/servconf.c 2015-06-24 11:44:39.734745802 +0200 -@@ -2317,7 +2317,7 @@ dump_config(ServerOptions *o) - dump_cfg_string(sXAuthLocation, o->xauth_location); - dump_cfg_string(sCiphers, o->ciphers); - dump_cfg_string(sMacs, o->macs); -- dump_cfg_string(sBanner, o->banner); -+ dump_cfg_string(sBanner, o->banner != NULL ? o->banner : "none"); - dump_cfg_string(sForceCommand, o->adm_forced_command); - dump_cfg_string(sChrootDirectory, o->chroot_directory); - dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); diff --git a/openssh-7.5p1-sandbox.patch b/openssh-7.5p1-sandbox.patch deleted file mode 100644 index 90640a0..0000000 --- a/openssh-7.5p1-sandbox.patch +++ /dev/null @@ -1,86 +0,0 @@ -In order to use the OpenSSL-ibmpkcs11 engine it is needed to allow flock -and ipc calls, because this engine calls OpenCryptoki (a PKCS#11 -implementation) which calls the libraries that will communicate with the -crypto cards. OpenCryptoki makes use of flock and ipc and, as of now, -this is only need on s390 architecture. - -Signed-off-by: Eduardo Barretto ---- - sandbox-seccomp-filter.c | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index ca75cc7..6e7de31 100644 ---- a/sandbox-seccomp-filter.c -+++ b/sandbox-seccomp-filter.c -@@ -166,6 +166,9 @@ static const struct sock_filter preauth_insns[] = { - #ifdef __NR_exit_group - SC_ALLOW(__NR_exit_group), - #endif -+#if defined(__NR_flock) && defined(__s390__) -+ SC_ALLOW(__NR_flock), -+#endif - #ifdef __NR_futex - SC_FUTEX(__NR_futex), - #endif -@@ -178,6 +181,9 @@ static const struct sock_filter preauth_insns[] = { - #ifdef __NR_gettimeofday - SC_ALLOW(__NR_gettimeofday), - #endif -+#if defined(__NR_ipc) && defined(__s390__) -+ SC_ALLOW(__NR_ipc), -+#endif - #ifdef __NR_getuid - SC_ALLOW(__NR_getuid), - #endif --- -1.9.1 - -getuid and geteuid are needed when using an openssl engine that calls a -crypto card, e.g. ICA (libica). -Those syscalls are also needed by the distros for audit code. - -Signed-off-by: Eduardo Barretto ---- - sandbox-seccomp-filter.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index 6e7de31..e86aa2c 100644 ---- a/sandbox-seccomp-filter.c -+++ b/sandbox-seccomp-filter.c -@@ -175,6 +175,18 @@ static const struct sock_filter preauth_insns[] = { - #ifdef __NR_getpid - SC_ALLOW(__NR_getpid), - #endif -+#ifdef __NR_getuid -+ SC_ALLOW(__NR_getuid), -+#endif -+#ifdef __NR_getuid32 -+ SC_ALLOW(__NR_getuid32), -+#endif -+#ifdef __NR_geteuid -+ SC_ALLOW(__NR_geteuid), -+#endif -+#ifdef __NR_geteuid32 -+ SC_ALLOW(__NR_geteuid32), -+#endif - #ifdef __NR_getrandom - SC_ALLOW(__NR_getrandom), - #endif --- 1.9.1 -1.9.1 -diff -up openssh-7.6p1/sandbox-seccomp-filter.c.sandbox openssh-7.6p1/sandbox-seccomp-filter.c ---- openssh-7.6p1/sandbox-seccomp-filter.c.sandbox 2017-12-12 13:59:30.563874059 +0100 -+++ openssh-7.6p1/sandbox-seccomp-filter.c 2017-12-12 13:59:14.842784083 +0100 -@@ -190,6 +190,9 @@ static const struct sock_filter preauth_ - #ifdef __NR_geteuid32 - SC_ALLOW(__NR_geteuid32), - #endif -+#ifdef __NR_gettid -+ SC_ALLOW(__NR_gettid), -+#endif - #ifdef __NR_getrandom - SC_ALLOW(__NR_getrandom), - #endif - diff --git a/openssh-8.0p1-keygen-strip-doseol.patch b/openssh-8.0p1-keygen-strip-doseol.patch deleted file mode 100644 index 3117a7a..0000000 --- a/openssh-8.0p1-keygen-strip-doseol.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up openssh-8.0p1/ssh-keygen.c.strip-doseol openssh-8.0p1/ssh-keygen.c ---- openssh-8.0p1/ssh-keygen.c.strip-doseol 2021-03-18 17:41:34.472404994 +0100 -+++ openssh-8.0p1/ssh-keygen.c 2021-03-18 17:41:55.255538761 +0100 -@@ -901,7 +901,7 @@ do_fingerprint(struct passwd *pw) - while (getline(&line, &linesize, f) != -1) { - lnum++; - cp = line; -- cp[strcspn(cp, "\n")] = '\0'; -+ cp[strcspn(cp, "\r\n")] = '\0'; - /* Trim leading space and comments */ - cp = line + strspn(line, " \t"); - if (*cp == '#' || *cp == '\0') diff --git a/openssh-8.7p1-ibmca.patch b/openssh-8.7p1-ibmca.patch deleted file mode 100644 index 88914bf..0000000 --- a/openssh-8.7p1-ibmca.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- 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-ssh-manpage.patch b/openssh-8.7p1-ssh-manpage.patch deleted file mode 100644 index c7f6f1e..0000000 --- a/openssh-8.7p1-ssh-manpage.patch +++ /dev/null @@ -1,53 +0,0 @@ -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.6p1-pam-rhost.patch b/openssh-9.6p1-pam-rhost.patch deleted file mode 100644 index b1b0d04..0000000 --- a/openssh-9.6p1-pam-rhost.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 26f366e263e575c4e1a18e2e64ba418f58878b37 Mon Sep 17 00:00:00 2001 -From: Daan De Meyer -Date: Mon, 20 Mar 2023 20:22:14 +0100 -Subject: [PATCH] Only set PAM_RHOST if the remote host is not "UNKNOWN" - -When using sshd's -i option with stdio that is not a AF_INET/AF_INET6 -socket, auth_get_canonical_hostname() returns "UNKNOWN" which is then -set as the value of PAM_RHOST, causing pam to try to do a reverse DNS -query of "UNKNOWN", which times out multiple times, causing a -substantial slowdown when logging in. - -To fix this, let's only set PAM_RHOST if the hostname is not "UNKNOWN". ---- - auth-pam.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/auth-pam.c b/auth-pam.c -index e143304e3..39b4e4563 100644 ---- a/auth-pam.c -+++ b/auth-pam.c -@@ -735,7 +735,7 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt) - sshpam_laddr = get_local_ipaddr( - ssh_packet_get_connection_in(ssh)); - } -- if (sshpam_rhost != NULL) { -+ if (sshpam_rhost != NULL && strcmp(sshpam_rhost, "UNKNOWN") != 0) { - debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost); - sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, - sshpam_rhost); --- -2.44.0 - diff --git a/openssh-9.9p1-match-regression.patch b/openssh-9.9p1-match-regression.patch deleted file mode 100644 index 73ea964..0000000 --- a/openssh-9.9p1-match-regression.patch +++ /dev/null @@ -1,471 +0,0 @@ -diff --git a/misc.c b/misc.c -index afdf5142..1b4b55c5 100644 ---- a/misc.c -+++ b/misc.c -@@ -107,6 +107,27 @@ rtrim(char *s) - } - } - -+/* -+ * returns pointer to character after 'prefix' in 's' or otherwise NULL -+ * if the prefix is not present. -+ */ -+const char * -+strprefix(const char *s, const char *prefix, int ignorecase) -+{ -+ size_t prefixlen; -+ -+ if ((prefixlen = strlen(prefix)) == 0) -+ return s; -+ if (ignorecase) { -+ if (strncasecmp(s, prefix, prefixlen) != 0) -+ return NULL; -+ } else { -+ if (strncmp(s, prefix, prefixlen) != 0) -+ return NULL; -+ } -+ return s + prefixlen; -+} -+ - /* set/unset filedescriptor to non-blocking */ - int - set_nonblock(int fd) -diff --git a/misc.h b/misc.h -index 11340389..efecdf1a 100644 ---- a/misc.h -+++ b/misc.h -@@ -56,6 +56,7 @@ struct ForwardOptions { - char *chop(char *); - void rtrim(char *); - void skip_space(char **); -+const char *strprefix(const char *, const char *, int); - char *strdelim(char **); - char *strdelimw(char **); - int set_nonblock(int); -diff --git a/readconf.c b/readconf.c -index 3d9cc6db..9f559269 100644 ---- a/readconf.c -+++ b/readconf.c -@@ -710,7 +710,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, - struct passwd *pw, const char *host_arg, const char *original_host, - int final_pass, int *want_final_pass, const char *filename, int linenum) - { -- char *arg, *oattrib, *attrib, *cmd, *host, *criteria; -+ char *arg, *oattrib = NULL, *attrib = NULL, *cmd, *host, *criteria; - const char *ruser; - int r, this_result, result = 1, attributes = 0, negate; - -@@ -731,7 +731,8 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, - - debug2("checking match for '%s' host %s originally %s", - full_line, host, original_host); -- while ((oattrib = attrib = argv_next(acp, avp)) != NULL) { -+ while ((attrib = argv_next(acp, avp)) != NULL) { -+ attrib = oattrib = xstrdup(attrib); - /* Terminate on comment */ - if (*attrib == '#') { - argv_consume(acp); -@@ -777,9 +778,23 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, - this_result ? "" : "not ", oattrib); - continue; - } -+ -+ /* Keep this list in sync with below */ -+ if (strprefix(attrib, "host=", 1) != NULL || -+ strprefix(attrib, "originalhost=", 1) != NULL || -+ strprefix(attrib, "user=", 1) != NULL || -+ strprefix(attrib, "localuser=", 1) != NULL || -+ strprefix(attrib, "localnetwork=", 1) != NULL || -+ strprefix(attrib, "tagged=", 1) != NULL || -+ strprefix(attrib, "exec=", 1) != NULL) { -+ arg = strchr(attrib, '='); -+ *(arg++) = '\0'; -+ } else { -+ arg = argv_next(acp, avp); -+ } -+ - /* All other criteria require an argument */ -- if ((arg = argv_next(acp, avp)) == NULL || -- *arg == '\0' || *arg == '#') { -+ if (arg == NULL || *arg == '\0' || *arg == '#') { - error("Missing Match criteria for %s", attrib); - result = -1; - goto out; -@@ -856,6 +871,8 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, - criteria == NULL ? "" : criteria, - criteria == NULL ? "" : "\""); - free(criteria); -+ free(oattrib); -+ oattrib = attrib = NULL; - } - if (attributes == 0) { - error("One or more attributes required for Match"); -@@ -865,6 +882,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp, - out: - if (result != -1) - debug2("match %sfound", result ? "" : "not "); -+ free(oattrib); - free(host); - return result; - } -diff --git a/servconf.c b/servconf.c -index 89b8413e..dd774f46 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: servconf.c,v 1.418 2024/09/15 03:09:44 djm Exp $ */ -+/* $OpenBSD: servconf.c,v 1.419 2024/09/25 01:24:04 djm Exp $ */ - /* - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland - * All rights reserved -@@ -1033,7 +1033,7 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, - int line, struct connection_info *ci) - { - int result = 1, attributes = 0, port; -- char *arg, *attrib; -+ char *arg, *attrib = NULL, *oattrib; - - if (ci == NULL) - debug3("checking syntax for 'Match %s'", full_line); -@@ -1047,7 +1047,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, - ci->laddress ? ci->laddress : "(null)", ci->lport); - } - -- while ((attrib = argv_next(acp, avp)) != NULL) { -+ while ((oattrib = argv_next(acp, avp)) != NULL) { -+ attrib = xstrdup(oattrib); - /* Terminate on comment */ - if (*attrib == '#') { - argv_consume(acp); /* mark all arguments consumed */ -@@ -1062,16 +1063,20 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, - *arg != '\0' && *arg != '#')) { - error("'all' cannot be combined with other " - "Match attributes"); -- return -1; -+ result = -1; -+ goto out; - } - if (arg != NULL && *arg == '#') - argv_consume(acp); /* consume remaining args */ -- return 1; -+ result = 1; -+ goto out; - } - /* Criterion "invalid-user" also has no argument */ - if (strcasecmp(attrib, "invalid-user") == 0) { -- if (ci == NULL) -+ if (ci == NULL) { -+ result = 0; - continue; -+ } - if (ci->user_invalid == 0) - result = 0; - else -@@ -1078,11 +1081,26 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, - debug("matched invalid-user at line %d", line); - continue; - } -+ -+ /* Keep this list in sync with below */ -+ if (strprefix(attrib, "user=", 1) != NULL || -+ strprefix(attrib, "group=", 1) != NULL || -+ strprefix(attrib, "host=", 1) != NULL || -+ strprefix(attrib, "address=", 1) != NULL || -+ strprefix(attrib, "localaddress=", 1) != NULL || -+ strprefix(attrib, "localport=", 1) != NULL || -+ strprefix(attrib, "rdomain=", 1) != NULL) { -+ arg = strchr(attrib, '='); -+ *(arg++) = '\0'; -+ } else { -+ arg = argv_next(acp, avp); -+ } -+ - /* All other criteria require an argument */ -- if ((arg = argv_next(acp, avp)) == NULL || -- *arg == '\0' || *arg == '#') { -+ if (arg == NULL || *arg == '\0' || *arg == '#') { - error("Missing Match criteria for %s", attrib); -- return -1; -+ result = -1; -+ goto out; - } - if (strcasecmp(attrib, "user") == 0) { - if (ci == NULL || (ci->test && ci->user == NULL)) { -@@ -1105,7 +1123,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, - match_test_missing_fatal("Group", "user"); - switch (match_cfg_line_group(arg, line, ci->user)) { - case -1: -- return -1; -+ result = -1; -+ goto out; - case 0: - result = 0; - } -@@ -1141,7 +1160,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, - result = 0; - break; - case -2: -- return -1; -+ result = -1; -+ goto out; - } - } else if (strcasecmp(attrib, "localaddress") == 0){ - if (ci == NULL || (ci->test && ci->laddress == NULL)) { -@@ -1166,13 +1186,15 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, - result = 0; - break; - case -2: -- return -1; -+ result = -1; -+ goto out; - } - } else if (strcasecmp(attrib, "localport") == 0) { - if ((port = a2port(arg)) == -1) { - error("Invalid LocalPort '%s' on Match line", - arg); -- return -1; -+ result = -1; -+ goto out; - } - if (ci == NULL || (ci->test && ci->lport == -1)) { - result = 0; -@@ -1200,16 +1222,21 @@ match_cfg_line(const char *full_line, int *acp, char ***avp, - debug("user %.100s matched 'RDomain %.100s' at " - "line %d", ci->rdomain, arg, line); - } else { -- error("Unsupported Match attribute %s", attrib); -- return -1; -+ error("Unsupported Match attribute %s", oattrib); -+ result = -1; -+ goto out; - } -+ free(attrib); -+ attrib = NULL; - } - if (attributes == 0) { - error("One or more attributes required for Match"); - return -1; - } -- if (ci != NULL) -+ out: -+ if (ci != NULL && result != -1) - debug3("match %sfound", result ? "" : "not "); -+ free(attrib); - return result; - } - -diff --git a/regress/cfginclude.sh b/regress/cfginclude.sh -index d442cdd6..97fd816f 100644 ---- a/regress/cfginclude.sh -+++ b/regress/cfginclude.sh -@@ -1,4 +1,4 @@ --# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $ -+# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm Exp $ - # Placed in the Public Domain. - - tid="config include" -@@ -10,7 +10,7 @@ cat > $OBJ/ssh_config.i << _EOF - Match host a - Hostname aa - --Match host b # comment -+Match host=b # comment - Hostname bb - Include $OBJ/ssh_config.i.* - -@@ -18,7 +18,7 @@ Match host c - Include $OBJ/ssh_config.i.* - Hostname cc - --Match host m -+Match host=m !user xxxyfake - Include $OBJ/ssh_config.i.* # comment - - Host d -@@ -41,7 +41,7 @@ Match host xxxxxx - _EOF - - cat > $OBJ/ssh_config.i.1 << _EOF --Match host a -+Match host=a - Hostname aaa - - Match host b -@@ -64,10 +64,10 @@ cat > $OBJ/ssh_config.i.2 << _EOF - Match host a - Hostname aaaa - --Match host b -+Match host=b !user blahblahfake - Hostname bbbb - --Match host c -+Match host=c - Hostname cccc - - Host d -@@ -142,7 +142,7 @@ trial a aa - - # cleanup - rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out --# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $ -+# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm Exp $ - # Placed in the Public Domain. - - tid="config include" -diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh -index 05a66685..2737a5f9 100644 ---- a/regress/cfgmatch.sh -+++ b/regress/cfgmatch.sh -@@ -1,4 +1,4 @@ --# $OpenBSD: cfgmatch.sh,v 1.13 2021/06/08 06:52:43 djm Exp $ -+# $OpenBSD: cfgmatch.sh,v 1.14 2024/09/27 01:05:54 djm Exp $ - # Placed in the Public Domain. - - tid="sshd_config match" -@@ -26,7 +26,7 @@ start_client() - kill $client_pid - fatal "timeout waiting for background ssh" - fi -- done -+ done - } - - stop_client() -@@ -119,40 +119,42 @@ stop_client - # requires knowledge of actual group memberships user running the test). - params="user:user:u1 host:host:h1 address:addr:1.2.3.4 \ - localaddress:laddr:5.6.7.8 rdomain:rdomain:rdom1" --cp $OBJ/sshd_proxy_bak $OBJ/sshd_config --echo 'Banner /nomatch' >>$OBJ/sshd_config --for i in $params; do -- config=`echo $i | cut -f1 -d:` -- criteria=`echo $i | cut -f2 -d:` -- value=`echo $i | cut -f3 -d:` -- cat >>$OBJ/sshd_config </dev/null || \ -+ fail "validate config for w/out spec" -+ -+ # Test matching each criteria. -+ for i in $params; do -+ testcriteria=`echo $i | cut -f2 -d:` -+ expected=/`echo $i | cut -f3 -d:` -+ spec="" -+ for j in $params; do -+ config=`echo $j | cut -f1 -d:` -+ criteria=`echo $j | cut -f2 -d:` -+ value=`echo $j | cut -f3 -d:` -+ if [ "$criteria" = "$testcriteria" ]; then -+ spec="$criteria=$value,$spec" -+ else -+ spec="$criteria=1$value,$spec" -+ fi -+ done -+ trace "test spec $spec" -+ result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \ -+ awk '$1=="banner"{print $2}'` -+ if [ "$result" != "$expected" ]; then -+ fail "match $config expected $expected got $result" - fi - done -- trace "test spec $spec" -- result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \ -- awk '$1=="banner"{print $2}'` -- if [ "$result" != "$expected" ]; then -- fail "match $config expected $expected got $result" -- fi - done -diff --git a/regress/servcfginclude.sh b/regress/servcfginclude.sh -index 518a703d..f67c3caa 100644 ---- a/regress/servcfginclude.sh -+++ b/regress/servcfginclude.sh -@@ -4,14 +4,14 @@ tid="server config include" - - cat > $OBJ/sshd_config.i << _EOF - HostKey $OBJ/host.ssh-ed25519 --Match host a -+Match host=a - Banner /aa - - Match host b - Banner /bb - Include $OBJ/sshd_config.i.* # comment - --Match host c -+Match host=c - Include $OBJ/sshd_config.i.* # comment - Banner /cc - -@@ -25,7 +25,7 @@ Match Host e - Banner /ee - Include $OBJ/sshd_config.i.* - --Match Host f -+Match Host=f - Include $OBJ/sshd_config.i.* - Banner /ff - -@@ -47,13 +47,13 @@ Match host b - Match host c - Banner /ccc - --Match Host d -+Match Host=d - Banner /ddd - - Match Host e - Banner /eee - --Match Host f -+Match Host=f - Banner /fff - _EOF - -@@ -61,13 +61,13 @@ cat > $OBJ/sshd_config.i.2 << _EOF - Match host a - Banner /aaaa - --Match host b -+Match host=b - Banner /bbbb - - Match host c # comment - Banner /cccc - --Match Host d -+Match Host=d - Banner /dddd - - Match Host e diff --git a/openssh-9.9p1-mlkembe.patch b/openssh-9.9p1-mlkembe.patch deleted file mode 100644 index aa0c26c..0000000 --- a/openssh-9.9p1-mlkembe.patch +++ /dev/null @@ -1,98 +0,0 @@ -diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c -index 679446e9..2b5d3960 100644 ---- a/kexmlkem768x25519.c -+++ b/kexmlkem768x25519.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: kexmlkem768x25519.c,v 1.1 2024/09/02 12:13:56 djm Exp $ */ -+/* $OpenBSD: kexmlkem768x25519.c,v 1.2 2024/10/27 02:06:59 djm Exp $ */ - /* - * Copyright (c) 2023 Markus Friedl. All rights reserved. - * -@@ -34,6 +34,9 @@ - #include - #include - #include -+#ifdef HAVE_ENDIAN_H -+# include -+#endif - - #include "sshkey.h" - #include "kex.h" -diff --git a/libcrux_mlkem768_sha3.h b/libcrux_mlkem768_sha3.h -index a82d60e8..b8ac1436 100644 ---- a/libcrux_mlkem768_sha3.h -+++ b/libcrux_mlkem768_sha3.h -@@ -1,4 +1,5 @@ --/* $OpenBSD: libcrux_mlkem768_sha3.h,v 1.1 2024/09/02 12:13:56 djm Exp $ */ -+/* $OpenBSD: libcrux_mlkem768_sha3.h,v 1.2 2024/10/27 02:06:01 djm Exp $ */ -+ - /* Extracted from libcrux revision 84c5d87b3092c59294345aa269ceefe0eb97cc35 */ - - /* -@@ -160,18 +161,19 @@ static inline void Eurydice_slice_to_array3(uint8_t *dst_tag, char *dst_ok, - // CORE STUFF (conversions, endianness, ...) - - static inline void core_num__u64_9__to_le_bytes(uint64_t v, uint8_t buf[8]) { -+ v = htole64(v); - memcpy(buf, &v, sizeof(v)); - } - static inline uint64_t core_num__u64_9__from_le_bytes(uint8_t buf[8]) { - uint64_t v; - memcpy(&v, buf, sizeof(v)); -- return v; -+ return le64toh(v); - } - - static inline uint32_t core_num__u32_8__from_le_bytes(uint8_t buf[4]) { - uint32_t v; - memcpy(&v, buf, sizeof(v)); -- return v; -+ return le32toh(v); - } - - static inline uint32_t core_num__u8_6__count_ones(uint8_t x0) { -diff --git a/mlkem768.sh b/mlkem768.sh -index 2fdc2831..3d12b2ed 100644 ---- a/mlkem768.sh -+++ b/mlkem768.sh -@@ -1,9 +1,10 @@ - #!/bin/sh --# $OpenBSD: mlkem768.sh,v 1.2 2024/09/04 05:11:33 djm Exp $ -+# $OpenBSD: mlkem768.sh,v 1.3 2024/10/27 02:06:01 djm Exp $ - # Placed in the Public Domain. - # - --WANT_LIBCRUX_REVISION="origin/main" -+#WANT_LIBCRUX_REVISION="origin/main" -+WANT_LIBCRUX_REVISION="84c5d87b3092c59294345aa269ceefe0eb97cc35" - - FILES=" - libcrux/libcrux-ml-kem/cg/eurydice_glue.h -@@ -47,6 +48,7 @@ echo '#define KRML_NOINLINE __attribute__((noinline, unused))' - echo '#define KRML_HOST_EPRINTF(...)' - echo '#define KRML_HOST_EXIT(x) fatal_f("internal error")' - echo -+ - for i in $FILES; do - echo "/* from $i */" - # Changes to all files: -@@ -56,11 +58,16 @@ for i in $FILES; do - -e 's/[ ]*$//' \ - $i | \ - case "$i" in -- # XXX per-file handling goes here. -+ */libcrux-ml-kem/cg/eurydice_glue.h) -+ # Replace endian functions with versions that work. -+ perl -0777 -pe 's/(static inline void core_num__u64_9__to_le_bytes.*\n)([^}]*\n)/\1 v = htole64(v);\n\2/' | -+ perl -0777 -pe 's/(static inline uint64_t core_num__u64_9__from_le_bytes.*?)return v;/\1return le64toh(v);/s' | -+ perl -0777 -pe 's/(static inline uint32_t core_num__u32_8__from_le_bytes.*?)return v;/\1return le32toh(v);/s' -+ ;; - # Default: pass through. - *) -- cat -- ;; -+ cat -+ ;; - esac - echo - done diff --git a/openssh-9.9p1-separate-keysign.patch b/openssh-9.9p1-separate-keysign.patch deleted file mode 100644 index ff0e35f..0000000 --- a/openssh-9.9p1-separate-keysign.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up openssh-9.9p1/ssh_config.5.xxx openssh-9.9p1/ssh_config.5 ---- openssh-9.9p1/ssh_config.5.xxx 2024-10-11 12:01:14.260566303 +0200 -+++ openssh-9.9p1/ssh_config.5 2024-10-11 12:01:59.725654775 +0200 -@@ -759,7 +759,7 @@ or - This option should be placed in the non-hostspecific section. - See - .Xr ssh-keysign 8 --for more information. -+for more information. ssh-keysign should be installed explicitly. - .It Cm EscapeChar - Sets the escape character (default: - .Ql ~ ) . diff --git a/openssh-9.9p2-error_processing.patch b/openssh-9.9p2-error_processing.patch deleted file mode 100644 index dd71716..0000000 --- a/openssh-9.9p2-error_processing.patch +++ /dev/null @@ -1,161 +0,0 @@ -diff --git a/krl.c b/krl.c -index e2efdf06..0d0f6953 100644 ---- a/krl.c -+++ b/krl.c -@@ -674,6 +674,7 @@ revoked_certs_generate(struct revoked_certs *rc, struct sshbuf *buf) - break; - case KRL_SECTION_CERT_SERIAL_BITMAP: - if (rs->lo - bitmap_start > INT_MAX) { -+ r = SSH_ERR_INVALID_FORMAT; - error_f("insane bitmap gap"); - goto out; - } -@@ -1059,6 +1060,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp) - } - - if ((krl = ssh_krl_init()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; - error_f("alloc failed"); - goto out; - } -diff --git a/packet.c b/packet.c -index 486f8515..9dea2cfc 100644 ---- a/packet.c -+++ b/packet.c -@@ -1864,6 +1864,14 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p) - if ((r = sshpkt_get_string_direct(ssh, &d, &len)) != 0) - return r; - DBG(debug("Received SSH2_MSG_PING len %zu", len)); -+ if (!ssh->state->after_authentication) { -+ DBG(debug("Won't reply to PING in preauth")); -+ break; -+ } -+ if (ssh_packet_is_rekeying(ssh)) { -+ DBG(debug("Won't reply to PING during KEX")); -+ break; -+ } - if ((r = sshpkt_start(ssh, SSH2_MSG_PONG)) != 0 || - (r = sshpkt_put_string(ssh, d, len)) != 0 || - (r = sshpkt_send(ssh)) != 0) -diff --git a/ssh-agent.c b/ssh-agent.c -index 48973b2c..c27c5a95 100644 ---- a/ssh-agent.c -+++ b/ssh-agent.c -@@ -1220,6 +1220,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, - "restrict-destination-v00@openssh.com") == 0) { - if (*dcsp != NULL) { - error_f("%s already set", ext_name); -+ r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshbuf_froms(m, &b)) != 0) { -@@ -1229,6 +1230,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, - while (sshbuf_len(b) != 0) { - if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) { - error_f("too many %s constraints", ext_name); -+ r = SSH_ERR_INVALID_FORMAT; - goto out; - } - *dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1, -@@ -1246,6 +1248,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, - } - if (*certs != NULL) { - error_f("%s already set", ext_name); -+ r = SSH_ERR_INVALID_FORMAT; - goto out; - } - if ((r = sshbuf_get_u8(m, &v)) != 0 || -@@ -1257,6 +1260,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp, - while (sshbuf_len(b) != 0) { - if (*ncerts >= AGENT_MAX_EXT_CERTS) { - error_f("too many %s constraints", ext_name); -+ r = SSH_ERR_INVALID_FORMAT; - goto out; - } - *certs = xrecallocarray(*certs, *ncerts, *ncerts + 1, -@@ -1360,6 +1360,8 @@ process_add_identity(SocketEntry *e) - if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || - k == NULL || - (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { -+ if (!r) /* k == NULL */ -+ r = SSH_ERR_INTERNAL_ERROR; - error_fr(r, "parse"); - goto out; - } -@@ -1757,6 +1761,7 @@ process_ext_session_bind(SocketEntry *e) - /* record new key/sid */ - if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) { - error_f("too many session IDs recorded"); -+ r = -1; - goto out; - } - e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids, -diff --git a/ssh-sk-client.c b/ssh-sk-client.c -index 321fe53a..06fad221 100644 ---- a/ssh-sk-client.c -+++ b/ssh-sk-client.c -@@ -439,6 +439,7 @@ sshsk_load_resident(const char *provider_path, const char *device, - } - if ((srk = calloc(1, sizeof(*srk))) == NULL) { - error_f("calloc failed"); -+ r = SSH_ERR_ALLOC_FAIL; - goto out; - } - srk->key = key; -@@ -450,6 +451,7 @@ sshsk_load_resident(const char *provider_path, const char *device, - if ((tmp = recallocarray(srks, nsrks, nsrks + 1, - sizeof(*srks))) == NULL) { - error_f("recallocarray keys failed"); -+ r = SSH_ERR_ALLOC_FAIL; - goto out; - } - debug_f("srks[%zu]: %s %s uidlen %zu", nsrks, -diff --git a/sshconnect2.c b/sshconnect2.c -index a69c4da1..1ee6000a 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -99,7 +99,7 @@ verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) - options.required_rsa_size)) != 0) - fatal_r(r, "Bad server host key"); - if (verify_host_key(xxx_host, xxx_hostaddr, hostkey, -- xxx_conn_info) == -1) -+ xxx_conn_info) != 0) - fatal("Host key verification failed."); - return 0; - } -@@ -699,6 +699,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) - - if ((pktype = sshkey_type_from_name(pkalg)) == KEY_UNSPEC) { - debug_f("server sent unknown pkalg %s", pkalg); -+ r = SSH_ERR_INVALID_FORMAT; - goto done; - } - if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { -@@ -709,6 +710,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) - error("input_userauth_pk_ok: type mismatch " - "for decoded key (received %d, expected %d)", - key->type, pktype); -+ r = SSH_ERR_INVALID_FORMAT; - goto done; - } - -@@ -728,6 +730,7 @@ input_userauth_pk_ok(int type, u_int32_t seq, struct ssh *ssh) - SSH_FP_DEFAULT); - error_f("server replied with unknown key: %s %s", - sshkey_type(key), fp == NULL ? "" : fp); -+ r = SSH_ERR_INVALID_FORMAT; - goto done; - } - ident = format_identity(id); -diff --git a/sshsig.c b/sshsig.c -index 6e03c0b0..3da005d6 100644 ---- a/sshsig.c -+++ b/sshsig.c -@@ -879,6 +879,7 @@ cert_filter_principals(const char *path, u_long linenum, - } - if ((principals = sshbuf_dup_string(nprincipals)) == NULL) { - error_f("buffer error"); -+ r = SSH_ERR_ALLOC_FAIL; - goto out; - } - /* success */ diff --git a/openssh.spec b/openssh.spec index ffa1fa7..b561504 100644 --- a/openssh.spec +++ b/openssh.spec @@ -38,12 +38,12 @@ # rpm -ba|--rebuild --define "static_openssl 1" %{?static_openssl:%global static_libcrypto 1} -%global openssh_ver 9.9p1 +%global openssh_ver 10.0p1 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 15%{?dist} +Release: 1%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -65,146 +65,118 @@ Source21: ssh-host-keys-migration.service Source22: parallel_test.sh Source23: parallel_test.Makefile -#https://bugzilla.mindrot.org/show_bug.cgi?id=2581 -Patch100: openssh-6.7p1-coverity.patch - -#https://bugzilla.mindrot.org/show_bug.cgi?id=1402 -# https://bugzilla.redhat.com/show_bug.cgi?id=1171248 -# record pfs= field in CRYPTO_SESSION audit event -Patch200: openssh-7.6p1-audit.patch -# Audit race condition in forked child (#1310684) -Patch201: openssh-7.1p2-audit-race-condition.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=2049947 -Patch202: openssh-9.0p1-audit-log.patch - #https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX) -Patch400: openssh-7.8p1-role-mls.patch +Patch0001: 0001-openssh-7.8p1-role-mls.patch #https://bugzilla.redhat.com/show_bug.cgi?id=781634 -Patch404: openssh-6.6p1-privsep-selinux.patch -#? -Patch502: openssh-6.6p1-keycat.patch - +Patch0002: 0002-openssh-6.6p1-privsep-selinux.patch +Patch0003: 0003-openssh-6.6p1-keycat.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1644 -Patch601: openssh-6.6p1-allow-ip-opts.patch +Patch0004: 0004-openssh-6.6p1-allow-ip-opts.patch #(drop?) https://bugzilla.mindrot.org/show_bug.cgi?id=1925 -Patch606: openssh-5.9p1-ipv6man.patch -#? -Patch607: openssh-5.8p2-sigpipe.patch +Patch0005: 0005-openssh-5.9p1-ipv6man.patch +Patch0006: 0006-openssh-5.8p2-sigpipe.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1789 -Patch609: openssh-7.2p2-x11.patch - -#? -Patch700: openssh-7.7p1-fips.patch -#? -Patch702: openssh-5.1p1-askpass-progress.patch +Patch0007: 0007-openssh-7.2p2-x11.patch +Patch0008: 0008-openssh-5.1p1-askpass-progress.patch #https://bugzilla.redhat.com/show_bug.cgi?id=198332 -Patch703: openssh-4.3p2-askpass-grab-info.patch +Patch0009: 0009-openssh-4.3p2-askpass-grab-info.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX) -Patch707: openssh-8.7p1-redhat.patch +Patch0010: 0010-openssh-8.7p1-redhat.patch # warn users for unsupported UsePAM=no (#757545) -Patch711: openssh-7.8p1-UsePAM-warning.patch - +Patch0011: 0011-openssh-7.8p1-UsePAM-warning.patch # GSSAPI Key Exchange (RFC 4462 + RFC 8732) # from https://github.com/openssh-gsskex/openssh-gsskex/tree/fedora/master # and # Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures # upstream MR: # https://github.com/openssh-gsskex/openssh-gsskex/pull/21 -Patch800: openssh-9.6p1-gssapi-keyex.patch +Patch0012: 0012-openssh-9.6p1-gssapi-keyex.patch #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html -Patch801: openssh-6.6p1-force_krb.patch -# add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843) -# CVE-2014-9278 -Patch802: openssh-6.6p1-GSSAPIEnablek5users.patch +Patch0013: 0013-openssh-6.6p1-force_krb.patch # Improve ccache handling in openssh (#991186, #1199363, #1566494) # https://bugzilla.mindrot.org/show_bug.cgi?id=2775 -Patch804: openssh-7.7p1-gssapi-new-unique.patch +Patch0014: 0014-openssh-7.7p1-gssapi-new-unique.patch # Respect k5login_directory option in krk5.conf (#1328243) -Patch805: openssh-7.2p2-k5login_directory.patch - +Patch0015: 0015-openssh-7.2p2-k5login_directory.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 -Patch901: openssh-6.6p1-kuserok.patch +Patch0016: 0016-openssh-6.6p1-kuserok.patch # Use tty allocation for a remote scp (#985650) -Patch906: openssh-6.4p1-fromto-remote.patch +Patch0017: 0017-openssh-6.4p1-fromto-remote.patch # privsep_preauth: use SELinux context from selinux-policy (#1008580) -Patch916: openssh-6.6.1p1-selinux-contexts.patch +Patch0018: 0018-openssh-6.6.1p1-selinux-contexts.patch # log via monitor in chroots without /dev/log (#2681) -Patch918: openssh-6.6.1p1-log-in-chroot.patch +Patch0019: 0019-openssh-6.6.1p1-log-in-chroot.patch # scp file into non-existing directory (#1142223) -Patch919: openssh-6.6.1p1-scp-non-existing-directory.patch +Patch0020: 0020-openssh-6.6.1p1-scp-non-existing-directory.patch +# add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843) +# CVE-2014-9278 +Patch0021: 0021-openssh-6.6p1-GSSAPIEnablek5users.patch # apply upstream patch and make sshd -T more consistent (#1187521) -Patch922: openssh-6.8p1-sshdT-output.patch +Patch0022: 0022-openssh-6.8p1-sshdT-output.patch # Add sftp option to force mode of created files (#1191055) -Patch926: openssh-6.7p1-sftp-force-permission.patch +Patch0023: 0023-openssh-6.7p1-sftp-force-permission.patch # make s390 use /dev/ crypto devices -- ignore closefrom -Patch939: openssh-7.2p2-s390-closefrom.patch +Patch0024: 0024-openssh-7.2p2-s390-closefrom.patch # Move MAX_DISPLAYS to a configuration option (#1341302) -Patch944: openssh-7.3p1-x11-max-displays.patch +Patch0025: 0025-openssh-7.3p1-x11-max-displays.patch # Pass inetd flags for SELinux down to openbsd compat level -Patch949: openssh-7.6p1-cleanup-selinux.patch +Patch0026: 0026-openssh-7.6p1-cleanup-selinux.patch # Sandbox adjustments for s390 and audit -Patch950: openssh-7.5p1-sandbox.patch +Patch0027: 0027-openssh-7.5p1-sandbox.patch # PKCS#11 URIs (upstream #2817, 2nd iteration) # https://github.com/Jakuje/openssh-portable/commits/jjelen-pkcs11 # git show > ~/devel/fedora/openssh/openssh-8.0p1-pkcs11-uri.patch -Patch951: openssh-8.0p1-pkcs11-uri.patch +Patch0028: 0028-openssh-8.0p1-pkcs11-uri.patch # Unbreak scp between two IPv6 hosts (#1620333) -Patch953: openssh-7.8p1-scp-ipv6.patch +Patch0029: 0029-openssh-7.8p1-scp-ipv6.patch # Mention crypto-policies in manual pages (#1668325) # clarify rhbz#2068423 on the man page of ssh_config -Patch962: openssh-8.0p1-crypto-policies.patch +Patch0030: 0030-openssh-8.0p1-crypto-policies.patch # Use OpenSSL KDF (#1631761) -Patch964: openssh-8.0p1-openssl-kdf.patch +Patch0031: 0031-openssh-8.0p1-openssl-kdf.patch # sk-dummy.so built with -fvisibility=hidden does not work -Patch965: openssh-8.2p1-visibility.patch +Patch0032: 0032-openssh-8.2p1-visibility.patch # Do not break X11 without IPv6 -Patch966: openssh-8.2p1-x11-without-ipv6.patch -# ssh-keygen printing fingerprint issue with Windows keys (#1901518) -Patch974: openssh-8.0p1-keygen-strip-doseol.patch +Patch0033: 0033-openssh-8.2p1-x11-without-ipv6.patch # sshd provides PAM an incorrect error code (#1879503) -Patch975: openssh-8.0p1-preserve-pam-errors.patch - +Patch0034: 0034-openssh-8.0p1-preserve-pam-errors.patch # Implement kill switch for SCP protocol -Patch977: openssh-8.7p1-scp-kill-switch.patch - +Patch0035: 0035-openssh-8.7p1-scp-kill-switch.patch # Workaround for lack of sftp_realpath in older versions of RHEL # https://bugzilla.redhat.com/show_bug.cgi?id=2038854 # https://github.com/openssh/openssh-portable/pull/299 # downstream only -Patch981: openssh-8.7p1-recursive-scp.patch -# https://github.com/djmdjm/openssh-wip/pull/13 -Patch982: openssh-8.7p1-minrsabits.patch +Patch0036: 0036-openssh-8.7p1-recursive-scp.patch +# Downstream alias for MinRSABits +Patch0037: 0037-openssh-8.7p1-minrsabits.patch # downstream only, IBMCA tentative fix # From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14 -Patch984: openssh-8.7p1-ibmca.patch - +Patch0038: 0038-openssh-8.7p1-ibmca.patch +#https://bugzilla.mindrot.org/show_bug.cgi?id=1402 +# https://bugzilla.redhat.com/show_bug.cgi?id=1171248 +# record pfs= field in CRYPTO_SESSION audit event +Patch0039: 0039-openssh-7.6p1-audit.patch +# Audit race condition in forked child (#1310684) +Patch0040: 0040-openssh-7.1p2-audit-race-condition.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=2049947 +Patch0041: 0041-openssh-9.0p1-audit-log.patch +Patch0042: 0042-openssh-7.7p1-fips.patch # Add missing options from ssh_config into ssh manpage # upstream bug: # https://bugzilla.mindrot.org/show_bug.cgi?id=3455 -Patch1002: openssh-8.7p1-ssh-manpage.patch - +Patch0043: 0043-openssh-8.7p1-ssh-manpage.patch # Don't propose disallowed algorithms during hostkey negotiation # upstream MR: # https://github.com/openssh/openssh-portable/pull/323 -Patch1006: openssh-8.7p1-negotiate-supported-algs.patch - -Patch1012: openssh-9.0p1-evp-fips-kex.patch -Patch1014: openssh-8.7p1-nohostsha1proof.patch - -Patch1015: openssh-9.6p1-pam-rhost.patch -Patch1016: openssh-9.9p1-separate-keysign.patch -# upstream cf3e48ee8ba1beeccddd2f203b558fa102be67a2 -# upstream 0c3927c45f8a57b511c874c4d51a8c89414f74ef -Patch1017: openssh-9.9p1-mlkembe.patch -# upstream 3f02368e8e9121847727c46b280efc280e5eb615 -# upstream 67a115e7a56dbdc3f5a58c64b29231151f3670f5 -Patch1020: openssh-9.9p1-match-regression.patch -# upstream 6ce00f0c2ecbb9f75023dbe627ee6460bcec78c2 -# upstream 0832aac79517611dd4de93ad0a83577994d9c907 -# added https://www.openwall.com/lists/oss-security/2025/02/22/1 -Patch1021: openssh-9.9p2-error_processing.patch -# Downstream patch, OpenSSL based MLKEM implementation -Patch1022: openssh-9.9p1-openssl-mlkem.patch +Patch0044: 0044-openssh-8.7p1-negotiate-supported-algs.patch +Patch0045: 0045-openssh-9.0p1-evp-fips-kex.patch +Patch0046: 0046-openssh-8.7p1-nohostsha1proof.patch +Patch0047: 0047-openssh-9.6p1-pam-rhost.patch +Patch0048: 0048-openssh-9.9p1-separate-keysign.patch +Patch0049: 0049-openssh-9.9p1-openssl-mlkem.patch +# https://www.openwall.com/lists/oss-security/2025/02/22/1 +#https://bugzilla.mindrot.org/show_bug.cgi?id=2581 +Patch1000: 1000-openssh-coverity.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -327,73 +299,7 @@ This package contains a test SK driver used for OpenSSH test purposes %prep gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} -%setup -q - -%patch -P 400 -p1 -b .role-mls -%patch -P 404 -p1 -b .privsep-selinux - -%patch -P 502 -p1 -b .keycat - -%patch -P 601 -p1 -b .ip-opts -%patch -P 606 -p1 -b .ipv6man -%patch -P 607 -p1 -b .sigpipe -%patch -P 609 -p1 -b .x11 -%patch -P 702 -p1 -b .progress -%patch -P 703 -p1 -b .grab-info -%patch -P 707 -p1 -b .redhat -%patch -P 711 -p1 -b .log-usepam-no -# -%patch -P 800 -p1 -b .gsskex -%patch -P 801 -p1 -b .force_krb -%patch -P 804 -p1 -b .ccache_name -%patch -P 805 -p1 -b .k5login -# -%patch -P 901 -p1 -b .kuserok -%patch -P 906 -p1 -b .fromto-remote -%patch -P 916 -p1 -b .contexts -%patch -P 918 -p1 -b .log-in-chroot -%patch -P 919 -p1 -b .scp -%patch -P 802 -p1 -b .GSSAPIEnablek5users -%patch -P 922 -p1 -b .sshdt -%patch -P 926 -p1 -b .sftp-force-mode -%patch -P 939 -p1 -b .s390-dev -%patch -P 944 -p1 -b .x11max -%patch -P 949 -p1 -b .refactor -%patch -P 950 -p1 -b .sandbox -%patch -P 951 -p1 -b .pkcs11-uri -%patch -P 953 -p1 -b .scp-ipv6 -%patch -P 962 -p1 -b .crypto-policies -%patch -P 964 -p1 -b .openssl-kdf -%patch -P 965 -p1 -b .visibility -%patch -P 966 -p1 -b .x11-ipv6 -%patch -P 974 -p1 -b .keygen-strip-doseol -%patch -P 975 -p1 -b .preserve-pam-errors - -%patch -P 977 -p1 -b .kill-scp - -%patch -P 981 -p1 -b .scp-sftpdirs -%patch -P 982 -p1 -b .minrsabits -%patch -P 984 -p1 -b .ibmca - -%patch -P 200 -p1 -b .audit -%patch -P 201 -p1 -b .audit-race -%patch -P 202 -p1 -b .audit-log -%patch -P 700 -p1 -b .fips - -%patch -P 1002 -p1 -b .ssh-manpage - -%patch -P 1006 -p1 -b .negotiate-supported-algs - -%patch -P 1012 -p1 -b .evp-fips-dh -%patch -P 1014 -p1 -b .nosha1hostproof -%patch -P 1015 -p1 -b .pam-rhost -%patch -P 1016 -p1 -b .sep-keysign -%patch -P 1017 -p1 -b .mlkembe -%patch -P 1020 -p1 -b .match -%patch -P 1021 -p1 -b .errcode_set -%patch -P 1022 -p1 -b .openssl-mlkem - -%patch -P 100 -p1 -b .coverity +%autosetup -T -b 0 -p1 autoreconf @@ -633,6 +539,7 @@ test -f %{sysconfig_anaconda} && \ %dir %attr(0711,root,root) %{_datadir}/empty.sshd %attr(0755,root,root) %{_sbindir}/sshd %attr(0755,root,root) %{_libexecdir}/openssh/sshd-session +%attr(0755,root,root) %{_libexecdir}/openssh/sshd-auth %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server %attr(0755,root,root) %{_libexecdir}/openssh/sshd-keygen %attr(0644,root,root) %{_mandir}/man5/sshd_config.5* @@ -671,6 +578,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Fri May 16 2025 Dmitry Belyavskiy - 10.0p1-1 +- Rebase to OpenSSH 10.0p1 + * Thu Apr 17 2025 Dmitry Belyavskiy - 9.9p1-15 - Require OpenSSL 3.5 to support PQ crypto - Suppress systemd warning on restart sshd diff --git a/sources b/sources index e88b6d9..10b461b 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (openssh-9.9p1.tar.gz) = 3cc0ed97f3e29ecbd882eca79239f02eb5a1606fce4f3119ddc3c5e86128aa3ff12dc85000879fccc87b60e7d651cfe37376607ac66075fede2118deaa685d6d -SHA512 (openssh-9.9p1.tar.gz.asc) = 916e975c54eb68c0b2f0b0006522b241cbe54c4caa88d31537a6278490c93d9d732c2ab3a080ac084bf75cbdd5402901ec68583cbe7c7cde4a8e40e7a8b78c28 +SHA512 (openssh-10.0p1.tar.gz) = 2daa1fcf95793b23810142077e68ddfabdf3732b207ef4f033a027f72d733d0e9bcdb6f757e7f3a5934b972de05bfaae3baae381cfc7a400cd8ab4d4e277a0ed +SHA512 (openssh-10.0p1.tar.gz.asc) = 6ab9deb4233ff159e55a18c9fc07d5ff8a41723dad74aa3d803e1476b585f5662aba34f8a7a1f5fe1d248f3ff3cd663f2c2fb8e399c6a4723b6215b0eb423d13 SHA512 (gpgkey-736060BA.gpg) = df44f3fdbcd1d596705348c7f5aed3f738c5f626a55955e0642f7c6c082995cf36a1b1891bb41b8715cb2aff34fef1c877e0eff0d3507dd00a055ba695757a21 From b5114ee608ffd23e627df6ad469d650e36db4c00 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 19 May 2025 10:15:02 +0200 Subject: [PATCH 67/80] Provide better diagnostics for non-supported private keys (https://github.com/openssh/openssh-portable/pull/564) --- ...error-for-non-supported-private-keys.patch | 27 +++++++++++++++++++ openssh.spec | 6 ++++- 2 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 0051-Provide-better-error-for-non-supported-private-keys.patch diff --git a/0051-Provide-better-error-for-non-supported-private-keys.patch b/0051-Provide-better-error-for-non-supported-private-keys.patch new file mode 100644 index 0000000..9c1aa4d --- /dev/null +++ b/0051-Provide-better-error-for-non-supported-private-keys.patch @@ -0,0 +1,27 @@ +From 4965cdbc1ee1e6a0c665797bb8b944d96d3d411f Mon Sep 17 00:00:00 2001 +From: Zoltan Fridrich +Date: Wed, 16 Apr 2025 15:11:59 +0200 +Subject: [PATCH 51/53] Provide better error for non-supported private keys + +Signed-off-by: Zoltan Fridrich +--- + sshkey.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/sshkey.c b/sshkey.c +index ca1cdb642..aada474e0 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -3582,6 +3582,9 @@ translate_libcrypto_error(unsigned long pem_err) + return SSH_ERR_LIBCRYPTO_ERROR; + } + case ERR_LIB_ASN1: ++#ifdef ERR_LIB_OSSL_DECODER ++ case ERR_LIB_OSSL_DECODER: ++#endif + return SSH_ERR_INVALID_FORMAT; + } + return SSH_ERR_LIBCRYPTO_ERROR; +-- +2.49.0 + diff --git a/openssh.spec b/openssh.spec index b561504..41b4503 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 1%{?dist} +Release: 2%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -578,6 +578,10 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Mon May 19 2025 Dmitry Belyavskiy - 10.0p1-2 +- Provide better diagnostics for non-supported private keys + (https://github.com/openssh/openssh-portable/pull/564) + * Fri May 16 2025 Dmitry Belyavskiy - 10.0p1-1 - Rebase to OpenSSH 10.0p1 From 367846c9c68cba75af5f53108917ab0f6d082def Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 19 May 2025 10:16:23 +0200 Subject: [PATCH 68/80] Ignore too short hostkeys in known_hosts file (https://github.com/openssh/openssh-portable/pull/567) --- ...ore-bad-hostkeys-in-known_hosts-file.patch | 86 +++++++++++++++++++ openssh.spec | 2 + 2 files changed, 88 insertions(+) create mode 100644 0052-Ignore-bad-hostkeys-in-known_hosts-file.patch diff --git a/0052-Ignore-bad-hostkeys-in-known_hosts-file.patch b/0052-Ignore-bad-hostkeys-in-known_hosts-file.patch new file mode 100644 index 0000000..f071225 --- /dev/null +++ b/0052-Ignore-bad-hostkeys-in-known_hosts-file.patch @@ -0,0 +1,86 @@ +From 9ed09ef158a113e21be7b3fefa7c5f932632749b Mon Sep 17 00:00:00 2001 +From: Zoltan Fridrich +Date: Mon, 5 May 2025 11:52:25 +0200 +Subject: [PATCH 52/53] Ignore bad hostkeys in known_hosts file + +Signed-off-by: Zoltan Fridrich +--- + hostfile.c | 15 +++++++++++++++ + hostfile.h | 1 + + ssh.c | 2 ++ + 3 files changed, 18 insertions(+) + +diff --git a/hostfile.c b/hostfile.c +index c5669c703..5c402f501 100644 +--- a/hostfile.c ++++ b/hostfile.c +@@ -63,6 +63,14 @@ + #include "hmac.h" + #include "sshbuf.h" + ++static int required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; ++ ++void ++hostfile_set_minimum_rsa_size(int size) ++{ ++ required_rsa_size = size; ++} ++ + /* XXX hmac is too easy to dictionary attack; use bcrypt? */ + + static int +@@ -233,6 +241,7 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx) + struct load_callback_ctx *ctx = (struct load_callback_ctx *)_ctx; + struct hostkeys *hostkeys = ctx->hostkeys; + struct hostkey_entry *tmp; ++ int r = 0; + + if (l->status == HKF_STATUS_INVALID) { + /* XXX make this verbose() in the future */ +@@ -241,6 +250,12 @@ record_hostkey(struct hostkey_foreach_line *l, void *_ctx) + return 0; + } + ++ if ((r = sshkey_check_rsa_length(l->key, required_rsa_size)) != 0) { ++ debug2_f("%s:%ld: ignoring hostkey: %s", ++ l->path, l->linenum, ssh_err(r)); ++ return 0; ++ } ++ + debug3_f("found %skey type %s in file %s:%lu", + l->marker == MRK_NONE ? "" : + (l->marker == MRK_CA ? "ca " : "revoked "), +diff --git a/hostfile.h b/hostfile.h +index a24a4e329..0e9b1a19a 100644 +--- a/hostfile.h ++++ b/hostfile.h +@@ -119,5 +119,6 @@ int hostkeys_foreach_file(const char *path, FILE *f, + const char *host, const char *ip, u_int options, u_int note); + + void hostfile_create_user_ssh_dir(const char *, int); ++void hostfile_set_minimum_rsa_size(int); + + #endif +diff --git a/ssh.c b/ssh.c +index abc8b8439..33787a8d4 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -110,6 +110,7 @@ + #include "ssherr.h" + #include "myproposal.h" + #include "utf8.h" ++#include "hostfile.h" + + #ifdef ENABLE_PKCS11 + #include "ssh-pkcs11.h" +@@ -1397,6 +1398,7 @@ main(int ac, char **av) + options.update_hostkeys = 0; + } + } ++ hostfile_set_minimum_rsa_size(options.required_rsa_size); + if (options.connection_attempts <= 0) + fatal("Invalid number of ConnectionAttempts"); + +-- +2.49.0 + diff --git a/openssh.spec b/openssh.spec index 41b4503..0338f23 100644 --- a/openssh.spec +++ b/openssh.spec @@ -581,6 +581,8 @@ test -f %{sysconfig_anaconda} && \ * Mon May 19 2025 Dmitry Belyavskiy - 10.0p1-2 - Provide better diagnostics for non-supported private keys (https://github.com/openssh/openssh-portable/pull/564) +- Ignore too short hostkeys in known_hosts file + (https://github.com/openssh/openssh-portable/pull/567) * Fri May 16 2025 Dmitry Belyavskiy - 10.0p1-1 - Rebase to OpenSSH 10.0p1 From e0b2e06f74e89c0f5f17d5324c4caa9874f6203f Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 19 May 2025 10:28:13 +0200 Subject: [PATCH 69/80] Switch to systemd-socket activation for ssh-agent Resolves: rhbz#2181353 --- openssh.spec | 2 ++ ssh-agent.service | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openssh.spec b/openssh.spec index 0338f23..956bb60 100644 --- a/openssh.spec +++ b/openssh.spec @@ -583,6 +583,8 @@ test -f %{sysconfig_anaconda} && \ (https://github.com/openssh/openssh-portable/pull/564) - Ignore too short hostkeys in known_hosts file (https://github.com/openssh/openssh-portable/pull/567) +- Switch to systemd-socket activation for ssh-agent + Resolves: rhbz#2181353 * Fri May 16 2025 Dmitry Belyavskiy - 10.0p1-1 - Rebase to OpenSSH 10.0p1 diff --git a/ssh-agent.service b/ssh-agent.service index 812303c..d0c38dd 100644 --- a/ssh-agent.service +++ b/ssh-agent.service @@ -8,9 +8,7 @@ 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 -D -a $SSH_AUTH_SOCK +ExecStart=/usr/bin/ssh-agent -D PassEnvironment=SSH_AGENT_PID SuccessExitStatus=2 Type=simple From 4d148ba0d3f987b904daea92920be70159725c75 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 9 Jun 2025 15:15:42 +0200 Subject: [PATCH 70/80] Apply patches forgot at the previous respin --- openssh.spec | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/openssh.spec b/openssh.spec index 956bb60..0b2b1bd 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 2%{?dist} +Release: 3%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -175,6 +175,12 @@ Patch0047: 0047-openssh-9.6p1-pam-rhost.patch Patch0048: 0048-openssh-9.9p1-separate-keysign.patch Patch0049: 0049-openssh-9.9p1-openssl-mlkem.patch # https://www.openwall.com/lists/oss-security/2025/02/22/1 +Patch0050: 0050-openssh-9.9p2-error_processing.patch +# https://github.com/openssh/openssh-portable/pull/564 +Patch0051: 0051-Provide-better-error-for-non-supported-private-keys.patch +# https://github.com/openssh/openssh-portable/pull/567 +Patch0052: 0052-Ignore-bad-hostkeys-in-known_hosts-file.patch + #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 Patch1000: 1000-openssh-coverity.patch @@ -578,6 +584,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Mon Jun 09 2025 Dmitry Belyavskiy - 10.0p1-3 +- Apply patches forgot in previous respin + * Mon May 19 2025 Dmitry Belyavskiy - 10.0p1-2 - Provide better diagnostics for non-supported private keys (https://github.com/openssh/openssh-portable/pull/564) From f42621e54e6901441ce80ff6a8451f0fa2a09ac0 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 9 Jun 2025 15:17:04 +0200 Subject: [PATCH 71/80] Support authentication indicators in GSSAPI --- ...-authentication-indicators-in-GSSAPI.patch | 450 ++++++++++++++++++ openssh.spec | 2 + 2 files changed, 452 insertions(+) create mode 100644 0053-support-authentication-indicators-in-GSSAPI.patch diff --git a/0053-support-authentication-indicators-in-GSSAPI.patch b/0053-support-authentication-indicators-in-GSSAPI.patch new file mode 100644 index 0000000..237e45d --- /dev/null +++ b/0053-support-authentication-indicators-in-GSSAPI.patch @@ -0,0 +1,450 @@ +From 5d5a66e96ad03132f65371070f4fa475f10207d9 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Mon, 10 Jun 2024 23:00:03 +0300 +Subject: [PATCH] support authentication indicators in GSSAPI + +RFC 6680 defines a set of GSSAPI extensions to handle attributes +associated with the GSSAPI names. MIT Kerberos and FreeIPA use +name attributes to add information about pre-authentication methods used +to acquire the initial Kerberos ticket. The attribute 'auth-indicators' +may contain list of strings that KDC has associated with the ticket +issuance process. + +Use authentication indicators to authorise or deny access to SSH server. +GSSAPIIndicators setting allows to specify a list of possible indicators +that a Kerberos ticket presented must or must not contain. More details +on the syntax are provided in sshd_config(5) man page. + +Fixes: https://bugzilla.mindrot.org/show_bug.cgi?id=2696 + +Signed-off-by: Alexander Bokovoy +--- + configure.ac | 1 + + gss-serv-krb5.c | 64 +++++++++++++++++++++++++++--- + gss-serv.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++- + servconf.c | 15 ++++++- + servconf.h | 2 + + ssh-gss.h | 7 ++++ + sshd_config.5 | 44 +++++++++++++++++++++ + 7 files changed, 228 insertions(+), 8 deletions(-) + +diff --git a/configure.ac b/configure.ac +index d92a85809..2cbe20bf3 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -5004,6 +5004,7 @@ AC_ARG_WITH([kerberos5], + AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h]) + AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h]) + AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h]) ++ AC_CHECK_HEADERS([gssapi_ext.h gssapi/gssapi_ext.h]) + + AC_SEARCH_LIBS([k_hasafs], [kafs], [AC_DEFINE([USE_AFS], [1], + [Define this if you want to use libkafs' AFS support])]) +diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c +index 03188d9b3..2c786ef14 100644 +--- a/gss-serv-krb5.c ++++ b/gss-serv-krb5.c +@@ -43,6 +43,7 @@ + #include "log.h" + #include "misc.h" + #include "servconf.h" ++#include "match.h" + + #include "ssh-gss.h" + +@@ -87,6 +88,32 @@ ssh_gssapi_krb5_init(void) + return 1; + } + ++/* Check if any of the indicators in the Kerberos ticket match ++ * one of indicators in the list of allowed/denied rules. ++ * In case of the match, apply the decision from the rule. ++ * In case of no indicator from the ticket matching the rule, deny ++ */ ++ ++static int ++ssh_gssapi_check_indicators(ssh_gssapi_client *client, int *matched) ++{ ++ int ret; ++ u_int i; ++ ++ /* Check indicators */ ++ for (i = 0; client->indicators[i] != NULL; i++) { ++ ret = match_pattern_list(client->indicators[i], ++ options.gss_indicators, 1); ++ /* negative or positive match */ ++ if (ret != 0) { ++ *matched = i; ++ return ret; ++ } ++ } ++ /* No rule matched */ ++ return 0; ++} ++ + /* Check if this user is OK to login. This only works with krb5 - other + * GSSAPI mechanisms will need their own. + * Returns true if the user is OK to log in, otherwise returns 0 +@@ -193,7 +220,7 @@ static int + ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) + { + krb5_principal princ; +- int retval; ++ int retval, matched; + const char *errmsg; + int k5login_exists; + +@@ -216,17 +243,42 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) + if (k5login_exists && + ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)) { + retval = 1; +- logit("Authorized to %s, krb5 principal %s (krb5_kuserok)", +- name, (char *)client->displayname.value); ++ errmsg = "krb5_kuserok"; + } else if (ssh_gssapi_krb5_cmdok(princ, client->exportedname.value, + name, k5login_exists)) { + retval = 1; +- logit("Authorized to %s, krb5 principal %s " +- "(ssh_gssapi_krb5_cmdok)", +- name, (char *)client->displayname.value); ++ errmsg = "ssh_gssapi_krb5_cmdok"; + } else + retval = 0; + ++ if ((retval == 1) && (options.gss_indicators != NULL)) { ++ /* At this point the configuration enforces presence of indicators ++ * so we drop the authorization result again */ ++ retval = 0; ++ if (client->indicators) { ++ matched = -1; ++ retval = ssh_gssapi_check_indicators(client, &matched); ++ if (retval != 0) { ++ retval = (retval == 1); ++ logit("Ticket contains indicator %s, " ++ "krb5 principal %s is %s", ++ client->indicators[matched], ++ (char *)client->displayname.value, ++ retval ? "allowed" : "denied"); ++ goto cont; ++ } ++ } ++ if (retval == 0) { ++ logit("GSSAPI authentication indicators enforced " ++ "but not matched. krb5 principal %s denied", ++ (char *)client->displayname.value); ++ } ++ } ++cont: ++ if (retval == 1) { ++ logit("Authorized to %s, krb5 principal %s (%s)", ++ name, (char *)client->displayname.value, errmsg); ++ } + krb5_free_principal(krb_context, princ); + return retval; + } +diff --git a/gss-serv.c b/gss-serv.c +index 9d5435eda..5c0491cf1 100644 +--- a/gss-serv.c ++++ b/gss-serv.c +@@ -54,7 +54,7 @@ extern ServerOptions options; + + static ssh_gssapi_client gssapi_client = + { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL, +- GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0}; ++ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0, NULL}; + + ssh_gssapi_mech gssapi_null_mech = + { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; +@@ -296,6 +296,92 @@ ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name) + return GSS_S_COMPLETE; + } + ++ ++/* Extract authentication indicators from the Kerberos ticket. Authentication ++ * indicators are GSSAPI name attributes for the name "auth-indicators". ++ * Multiple indicators might be present in the ticket. ++ * Each indicator is a utf8 string. */ ++ ++#define AUTH_INDICATORS_TAG "auth-indicators" ++ ++/* Privileged (called from accept_secure_ctx) */ ++static OM_uint32 ++ssh_gssapi_getindicators(Gssctxt *ctx, gss_name_t gss_name, ssh_gssapi_client *client) ++{ ++ gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET; ++ gss_buffer_desc value = GSS_C_EMPTY_BUFFER; ++ gss_buffer_desc display_value = GSS_C_EMPTY_BUFFER; ++ int is_mechname, authenticated, complete, more; ++ size_t count, i; ++ ++ ctx->major = gss_inquire_name(&ctx->minor, gss_name, ++ &is_mechname, NULL, &attrs); ++ if (ctx->major != GSS_S_COMPLETE) { ++ return (ctx->major); ++ } ++ ++ if (attrs == GSS_C_NO_BUFFER_SET) { ++ /* No indicators in the ticket */ ++ return (0); ++ } ++ ++ count = 0; ++ for (i = 0; i < attrs->count; i++) { ++ /* skip anything but auth-indicators */ ++ if (((sizeof(AUTH_INDICATORS_TAG) - 1) != attrs->elements[i].length) || ++ strncmp(AUTH_INDICATORS_TAG, ++ attrs->elements[i].value, ++ sizeof(AUTH_INDICATORS_TAG) - 1) != 0) ++ continue; ++ count++; ++ } ++ ++ if (count == 0) { ++ /* No auth-indicators in the ticket */ ++ (void) gss_release_buffer_set(&ctx->minor, &attrs); ++ return (0); ++ } ++ ++ client->indicators = recallocarray(NULL, 0, count + 1, sizeof(char*)); ++ count = 0; ++ for (i = 0; i < attrs->count; i++) { ++ authenticated = 0; ++ complete = 0; ++ more = -1; ++ /* skip anything but auth-indicators */ ++ if (((sizeof(AUTH_INDICATORS_TAG) - 1) != attrs->elements[i].length) || ++ strncmp(AUTH_INDICATORS_TAG, ++ attrs->elements[i].value, ++ sizeof(AUTH_INDICATORS_TAG) - 1) != 0) ++ continue; ++ /* retrieve all indicators */ ++ while (more != 0) { ++ value.value = NULL; ++ display_value.value = NULL; ++ ctx->major = gss_get_name_attribute(&ctx->minor, gss_name, ++ &attrs->elements[i], &authenticated, ++ &complete, &value, &display_value, &more); ++ if (ctx->major != GSS_S_COMPLETE) { ++ goto out; ++ } ++ ++ if ((value.value != NULL) && authenticated) { ++ client->indicators[count] = xmalloc(value.length + 1); ++ memcpy(client->indicators[count], value.value, value.length); ++ client->indicators[count][value.length] = '\0'; ++ count++; ++ } ++ } ++ } ++ ++out: ++ (void) gss_release_buffer(&ctx->minor, &value); ++ (void) gss_release_buffer(&ctx->minor, &display_value); ++ (void) gss_release_buffer_set(&ctx->minor, &attrs); ++ return (ctx->major); ++} ++ ++ + /* Extract the client details from a given context. This can only reliably + * be called once for a context */ + +@@ -385,6 +471,12 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) + } + + gss_release_buffer(&ctx->minor, &ename); ++ /* Retrieve authentication indicators, if they exist */ ++ if ((ctx->major = ssh_gssapi_getindicators(ctx, ++ ctx->client, client))) { ++ ssh_gssapi_error(ctx); ++ return (ctx->major); ++ } + + /* We can't copy this structure, so we just move the pointer to it */ + client->creds = ctx->client_creds; +@@ -447,6 +539,7 @@ int + ssh_gssapi_userok(char *user, struct passwd *pw, int kex) + { + OM_uint32 lmin; ++ size_t i; + + (void) kex; /* used in privilege separation */ + +@@ -465,6 +558,14 @@ ssh_gssapi_userok(char *user, struct passwd *pw, int kex) + gss_release_buffer(&lmin, &gssapi_client.displayname); + gss_release_buffer(&lmin, &gssapi_client.exportedname); + gss_release_cred(&lmin, &gssapi_client.creds); ++ ++ if (gssapi_client.indicators != NULL) { ++ for(i = 0; gssapi_client.indicators[i] != NULL; i++) { ++ free(gssapi_client.indicators[i]); ++ } ++ free(gssapi_client.indicators); ++ } ++ + explicit_bzero(&gssapi_client, + sizeof(ssh_gssapi_client)); + return 0; +diff --git a/servconf.c b/servconf.c +index e7e4ad046..aab653244 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -147,6 +147,7 @@ initialize_server_options(ServerOptions *options) + options->gss_strict_acceptor = -1; + options->gss_store_rekey = -1; + options->gss_kex_algorithms = NULL; ++ options->gss_indicators = NULL; + options->use_kuserok = -1; + options->enable_k5users = -1; + options->password_authentication = -1; +@@ -598,7 +599,7 @@ typedef enum { + sPerSourcePenalties, sPerSourcePenaltyExemptList, + sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, + sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor, +- sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, ++ sGssKeyEx, sGssIndicators, sGssKexAlgorithms, sGssStoreRekey, + sAcceptEnv, sSetEnv, sPermitTunnel, + sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, + sUsePrivilegeSeparation, sAllowAgentForwarding, +@@ -694,6 +695,7 @@ static struct { + { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, + { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, + { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL }, ++ { "gssapiindicators", sGssIndicators, SSHCFG_ALL }, + #else + { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, + { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, +@@ -703,6 +705,7 @@ static struct { + { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, + { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL }, + { "gssapienablek5users", sUnsupported, SSHCFG_ALL }, ++ { "gssapiindicators", sUnsupported, SSHCFG_ALL }, + #endif + { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, + { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, +@@ -1730,6 +1733,15 @@ process_server_config_line_depth(ServerOptions *options, char *line, + options->gss_kex_algorithms = xstrdup(arg); + break; + ++ case sGssIndicators: ++ arg = argv_next(&ac, &av); ++ if (!arg || *arg == '\0') ++ fatal("%s line %d: %s missing argument.", ++ filename, linenum, keyword); ++ if (options->gss_indicators == NULL) ++ options->gss_indicators = xstrdup(arg); ++ break; ++ + case sPasswordAuthentication: + intptr = &options->password_authentication; + goto parse_flag; +@@ -3351,6 +3363,7 @@ dump_config(ServerOptions *o) + dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); + dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); + dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms); ++ dump_cfg_string(sGssIndicators, o->gss_indicators); + #endif + dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); + dump_cfg_fmtint(sKbdInteractiveAuthentication, +diff --git a/servconf.h b/servconf.h +index 7c7e5d434..7c41df417 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -181,6 +181,7 @@ typedef struct { + char **allow_groups; + u_int num_deny_groups; + char **deny_groups; ++ char *gss_indicators; + + u_int num_subsystems; + char **subsystem_name; +@@ -310,6 +311,7 @@ TAILQ_HEAD(include_list, include_item); + M_CP_STROPT(routing_domain); \ + M_CP_STROPT(permit_user_env_allowlist); \ + M_CP_STROPT(pam_service_name); \ ++ M_CP_STROPT(gss_indicators); \ + M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \ + M_CP_STRARRAYOPT(allow_users, num_allow_users); \ + M_CP_STRARRAYOPT(deny_users, num_deny_users); \ +diff --git a/ssh-gss.h b/ssh-gss.h +index a894e23c9..59cf46d47 100644 +--- a/ssh-gss.h ++++ b/ssh-gss.h +@@ -34,6 +34,12 @@ + #include + #endif + ++#ifdef HAVE_GSSAPI_EXT_H ++#include ++#elif defined(HAVE_GSSAPI_GSSAPI_EXT_H) ++#include ++#endif ++ + #ifdef KRB5 + # ifndef HEIMDAL + # ifdef HAVE_GSSAPI_GENERIC_H +@@ -107,6 +113,7 @@ typedef struct { + ssh_gssapi_ccache store; + int used; + int updated; ++ char **indicators; /* auth indicators */ + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +diff --git a/sshd_config.5 b/sshd_config.5 +index 583a01cdb..90ab87edd 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -785,6 +785,50 @@ gss-nistp256-sha256- + gss-curve25519-sha256- + .Ed + This option only applies to connections using GSSAPI. ++.It Cm GSSAPIIndicators ++Specifies whether to accept or deny GSSAPI authenticated access if Kerberos ++mechanism is used and Kerberos ticket contains a particular set of ++authentication indicators. The values can be specified as a comma-separated list ++.Cm [!]name1,[!]name2,... . ++When indicator's name is prefixed with !, the authentication indicator 'name' ++will deny access to the system. Otherwise, one of non-negated authentication ++indicators must be present in the Kerberos ticket to allow access. If ++.Cm GSSAPIIndicators ++is defined, a Kerberos ticket that has indicators but does not match the ++policy will get denial. If at least one indicator is configured, whether for ++access or denial, tickets without authentication indicators will be explicitly ++rejected. ++.Pp ++By default systems using MIT Kerberos 1.17 or later will not assign any ++indicators. SPAKE and PKINIT methods add authentication indicators ++to all successful authentications. The SPAKE pre-authentication method is ++preferred over an encrypted timestamp pre-authentication when passwords used to ++authenticate user principals. Kerberos KDCs built with Heimdal Kerberos ++(including Samba AD DC built with Heimdal) do not add authentication ++indicators. However, OpenSSH built against Heimdal Kerberos library is able to ++inquire authentication indicators and thus can be used to check for their presence. ++.Pp ++Indicator name is case-sensitive and depends on the configuration of a ++particular Kerberos deployment. Indicators available in MIT Kerberos and ++FreeIPA environments: ++.Pp ++.Bl -tag -width XXXX -offset indent -compact ++.It Cm hardened ++SPAKE or encrypted timestamp pre-authentication mechanisms in MIT Kerberos and FreeIPA ++.It Cm pkinit ++smartcard or PKCS11 token-based pre-authentication in MIT Kerberos and FreeIPA ++.It Cm radius ++pre-authentication based on a RADIUS server in MIT Kerberos and FreeIPA ++.It Cm otp ++TOTP/HOTP-based two-factor pre-authentication in FreeIPA ++.It Cm idp ++OAuth2-based pre-authentication in FreeIPA using an external identity provider ++and device authorization grant flow ++.It Cm passkey ++FIDO2-based pre-authentication in FreeIPA, using FIDO2 USB and NFC tokens ++.El ++.Pp ++The default is to not use GSSAPI authentication indicators for access decisions. + .It Cm HostbasedAcceptedAlgorithms + The default is handled system-wide by + .Xr crypto-policies 7 . +-- +2.49.0 + diff --git a/openssh.spec b/openssh.spec index 0b2b1bd..9412ac2 100644 --- a/openssh.spec +++ b/openssh.spec @@ -180,6 +180,8 @@ Patch0050: 0050-openssh-9.9p2-error_processing.patch Patch0051: 0051-Provide-better-error-for-non-supported-private-keys.patch # https://github.com/openssh/openssh-portable/pull/567 Patch0052: 0052-Ignore-bad-hostkeys-in-known_hosts-file.patch +# https://github.com/openssh/openssh-portable/pull/500 +Patch0053: 0053-support-authentication-indicators-in-GSSAPI.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 Patch1000: 1000-openssh-coverity.patch From 555ff68c37fbbd5e3e739a5144ee632e6e193be2 Mon Sep 17 00:00:00 2001 From: Allison Karlitskaya Date: Thu, 26 Jun 2025 13:52:50 +0200 Subject: [PATCH 72/80] Update sshd@.service to follow upstream In particular, this adds in the support for ephemeral ssh keys provided by credentials (passed from container managers or VM hypervisors). This was introduced upstream by 071155a1fbac ("ssh-generator: support ssh.ephemeral-key.all-users"). This change alone isn't enough to get this working. We now get this SELinux denial: type=AVC msg=audit(1750939616.931:111): avc: denied { read } for pid=1159 comm="sshd-session" name="ssh.ephemeral-authorized_keys-all" dev="tmpfs" ino=2 scontext=system_u:system_r:sshd_t:s0-s0:c0.c1023 tcontext=system_u:object_r:init_var_run_t:s0 tclass=file permissive=0 I have tested this with `setenforce 0`, however, and it works. Resolves: rhbz#2374928 --- sshd@.service | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sshd@.service b/sshd@.service index c077be2..4f12190 100644 --- a/sshd@.service +++ b/sshd@.service @@ -12,5 +12,6 @@ Wants=ssh-host-keys-migration.service # when the config file under /etc does not exist or is empty. Environment=OPTIONS= EnvironmentFile=-/etc/sysconfig/sshd -ExecStart=-/usr/sbin/sshd -i $OPTIONS +ExecStart=-/usr/sbin/sshd -i $OPTIONS -o "AuthorizedKeysFile ${CREDENTIALS_DIRECTORY}/ssh.ephemeral-authorized_keys-all .ssh/authorized_keys" StandardInput=socket +ImportCredential=ssh.ephemeral-authorized_keys-all From 8476fdfee5baaadaf7d913b2a81d4f4a24e25507 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 27 Jun 2025 10:39:00 +0200 Subject: [PATCH 73/80] OpenSSH part of support of ephemeral authorized keys Needs a SELinux counterpart --- openssh.spec | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/openssh.spec b/openssh.spec index 9412ac2..818d631 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 3%{?dist} +Release: 4%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -586,6 +586,12 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Fri Jun 27 2025 Dmitry Belyavskiy - 10.0p1-4 +- Update sshd@.service to follow upstream, mostly support ephemeral sshd keys + Submitted by Allison Karlitskaya (https://src.fedoraproject.org/rpms/openssh/pull-request/101) + Needs a SELinux counterpart. + Related: rhbz#2374928 + * Mon Jun 09 2025 Dmitry Belyavskiy - 10.0p1-3 - Apply patches forgot in previous respin From f6e9920c49b0edd039dc9b0e3de1b39a6650387e Mon Sep 17 00:00:00 2001 From: Fedora Release Engineering Date: Thu, 24 Jul 2025 23:40:26 +0000 Subject: [PATCH 74/80] Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild --- openssh.spec | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/openssh.spec b/openssh.spec index 818d631..4f98f19 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 4%{?dist} +Release: 5%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -586,6 +586,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Thu Jul 24 2025 Fedora Release Engineering - 10.0p1-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + * Fri Jun 27 2025 Dmitry Belyavskiy - 10.0p1-4 - Update sshd@.service to follow upstream, mostly support ephemeral sshd keys Submitted by Allison Karlitskaya (https://src.fedoraproject.org/rpms/openssh/pull-request/101) From 6fcc31aa4a562eaa4e5d357c8ea4f79f68cbd24d Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 28 Aug 2025 14:07:02 +0200 Subject: [PATCH 75/80] Enable GSS KEX in FIPS mode --- 0042-openssh-7.7p1-fips.patch | 178 ++++++++++++---------------------- openssh.spec | 5 +- 2 files changed, 68 insertions(+), 115 deletions(-) diff --git a/0042-openssh-7.7p1-fips.patch b/0042-openssh-7.7p1-fips.patch index f4729d7..9a81cc0 100644 --- a/0042-openssh-7.7p1-fips.patch +++ b/0042-openssh-7.7p1-fips.patch @@ -1,7 +1,7 @@ -From 6e0e7462959e8bc6a99f50dbf9a5b42ae74c2c87 Mon Sep 17 00:00:00 2001 +From 79f9b2763d85ec592cb7e54dcf1c695d8dd138b1 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy -Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 42/50] openssh-7.7p1-fips +Date: Thu, 28 Aug 2025 14:01:38 +0200 +Subject: [PATCH 42/54] openssh-7.7p1-fips --- dh.c | 41 ++++++++++++++++++++++ @@ -15,17 +15,18 @@ Subject: [PATCH 42/50] openssh-7.7p1-fips sandbox-seccomp-filter.c | 3 ++ servconf.c | 16 ++++++--- ssh-ed25519.c | 9 +++++ + ssh-gss.h | 5 +++ ssh-keygen.c | 22 ++++++++++-- ssh-rsa.c | 3 ++ ssh.c | 5 +++ - sshconnect2.c | 61 ++++++++++++++++++--------------- - sshd-auth.c | 13 ++++--- + sshconnect2.c | 9 ++++- + sshd-session.c | 1 + sshd.c | 13 +++++++ sshkey.c | 37 ++++++++++++++++++++ - 18 files changed, 301 insertions(+), 60 deletions(-) + 19 files changed, 272 insertions(+), 30 deletions(-) diff --git a/dh.c b/dh.c -index 168dea1d..8c9a29fa 100644 +index 168dea1dd..8c9a29fa7 100644 --- a/dh.c +++ b/dh.c @@ -36,6 +36,7 @@ @@ -89,7 +90,7 @@ index 168dea1d..8c9a29fa 100644 + #endif /* WITH_OPENSSL */ diff --git a/dh.h b/dh.h -index c6326a39..e51e292b 100644 +index c6326a39d..e51e292b8 100644 --- a/dh.h +++ b/dh.h @@ -45,6 +45,7 @@ DH *dh_new_group_fallback(int); @@ -101,7 +102,7 @@ index c6326a39..e51e292b 100644 u_int dh_estimate(int); void dh_set_moduli_file(const char *); diff --git a/kex-names.c b/kex-names.c -index 6c0b7c2b..cd3902ad 100644 +index 6c0b7c2b3..cd3902ad2 100644 --- a/kex-names.c +++ b/kex-names.c @@ -33,6 +33,7 @@ @@ -125,7 +126,7 @@ index 6c0b7c2b..cd3902ad 100644 return 0; } diff --git a/kex.c b/kex.c -index 62f607d6..71fbe5cb 100644 +index 62f607d6f..71fbe5cbe 100644 --- a/kex.c +++ b/kex.c @@ -40,6 +40,7 @@ @@ -146,7 +147,7 @@ index 62f607d6..71fbe5cb 100644 "ext-info-s,kex-strict-s-v00@openssh.com" : "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) diff --git a/kexgen.c b/kexgen.c -index 15df591c..eecdceba 100644 +index 15df591ca..eecdceba2 100644 --- a/kexgen.c +++ b/kexgen.c @@ -31,6 +31,7 @@ @@ -264,7 +265,7 @@ index 15df591c..eecdceba 100644 default: r = SSH_ERR_INVALID_ARGUMENT; diff --git a/kexgexc.c b/kexgexc.c -index e99e0cf2..4c3feae0 100644 +index e99e0cf21..4c3feae09 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -28,6 +28,7 @@ @@ -287,7 +288,7 @@ index e99e0cf2..4c3feae0 100644 /* generate and send 'e', client DH public key */ diff --git a/myproposal.h b/myproposal.h -index 8fe9276c..3e0ec682 100644 +index 8fe9276c2..3e0ec6826 100644 --- a/myproposal.h +++ b/myproposal.h @@ -58,6 +58,18 @@ @@ -338,7 +339,7 @@ index 8fe9276c..3e0ec682 100644 #define SSH_ALLOWED_CA_SIGALGS \ "ssh-ed25519," \ diff --git a/readconf.c b/readconf.c -index f340bf50..ea9d293c 100644 +index f340bf501..ea9d293c3 100644 --- a/readconf.c +++ b/readconf.c @@ -43,6 +43,7 @@ @@ -372,7 +373,7 @@ index f340bf50..ea9d293c 100644 do { \ if ((r = kex_assemble_names(&options->what, \ diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index 1fabf99d..ccb61586 100644 +index 1fabf99d0..ccb61586e 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c @@ -230,6 +230,9 @@ static const struct sock_filter preauth_insns[] = { @@ -386,7 +387,7 @@ index 1fabf99d..ccb61586 100644 SC_DENY(__NR_openat, EACCES), #endif diff --git a/servconf.c b/servconf.c -index 84891544..8b708cbf 100644 +index 84891544b..8b708cbf4 100644 --- a/servconf.c +++ b/servconf.c @@ -37,6 +37,7 @@ @@ -420,7 +421,7 @@ index 84891544..8b708cbf 100644 do { \ if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ diff --git a/ssh-ed25519.c b/ssh-ed25519.c -index 22d8db02..41942f4e 100644 +index 22d8db026..41942f4e5 100644 --- a/ssh-ed25519.c +++ b/ssh-ed25519.c @@ -24,6 +24,7 @@ @@ -453,8 +454,24 @@ index 22d8db02..41942f4e 100644 if ((b = sshbuf_from(sig, siglen)) == NULL) return SSH_ERR_ALLOC_FAIL; +diff --git a/ssh-gss.h b/ssh-gss.h +index a894e23c9..329dc9da0 100644 +--- a/ssh-gss.h ++++ b/ssh-gss.h +@@ -88,6 +88,11 @@ extern char **k5users_allowed_cmds; + KEX_GSS_GRP14_SHA1_ID "," \ + KEX_GSS_GEX_SHA1_ID + ++#define GSS_KEX_DEFAULT_KEX_FIPS \ ++ KEX_GSS_GRP14_SHA256_ID "," \ ++ KEX_GSS_GRP16_SHA512_ID "," \ ++ KEX_GSS_NISTP256_SHA256_ID ++ + #include "digest.h" /* SSH_DIGEST_MAX_LENGTH */ + + typedef struct { diff --git a/ssh-keygen.c b/ssh-keygen.c -index 16cff947..792aafde 100644 +index 16cff9473..792aafde0 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -20,6 +20,7 @@ @@ -524,7 +541,7 @@ index 16cff947..792aafde 100644 type = sshkey_type_from_shortname(key_type_name); type_bits_valid(type, key_type_name, &bits); diff --git a/ssh-rsa.c b/ssh-rsa.c -index 3ad1fddc..6c2f771a 100644 +index 3ad1fddc4..6c2f771a3 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c @@ -23,6 +23,7 @@ @@ -545,7 +562,7 @@ index 3ad1fddc..6c2f771a 100644 goto out; } diff --git a/ssh.c b/ssh.c -index 98b103c9..abc8b843 100644 +index 98b103c9e..abc8b8439 100644 --- a/ssh.c +++ b/ssh.c @@ -78,6 +78,7 @@ @@ -568,7 +585,7 @@ index 98b103c9..abc8b843 100644 if (options.sk_provider != NULL && *options.sk_provider == '$' && strlen(options.sk_provider) > 1) { diff --git a/sshconnect2.c b/sshconnect2.c -index 0af15bcc..14f7671a 100644 +index 0af15bcc1..3e02f485d 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -45,6 +45,8 @@ @@ -580,108 +597,41 @@ index 0af15bcc..14f7671a 100644 #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" -@@ -262,36 +264,41 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, +@@ -262,6 +264,9 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, #if defined(GSSAPI) && defined(WITH_OPENSSL) if (options.gss_keyex) { -- /* Add the GSSAPI mechanisms currently supported on this -- * client to the key exchange algorithm proposal */ -- orig = myproposal[PROPOSAL_KEX_ALGS]; -- -- if (options.gss_server_identity) { -- gss_host = xstrdup(options.gss_server_identity); -- } else if (options.gss_trust_dns) { -- gss_host = remote_hostname(ssh); -- /* Fall back to specified host if we are using proxy command -- * and can not use DNS on that socket */ -- if (strcmp(gss_host, "UNKNOWN") == 0) { -- free(gss_host); -+ if (FIPS_mode()) { -+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); -+ options.gss_keyex = 0; -+ } else { -+ /* Add the GSSAPI mechanisms currently supported on this -+ * client to the key exchange algorithm proposal */ -+ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ char * gss_kex_filtered = FIPS_mode() ? ++ match_filter_allowlist(options.gss_kex_algorithms, GSS_KEX_DEFAULT_KEX_FIPS) : xstrdup(options.gss_kex_algorithms); + -+ if (options.gss_server_identity) { -+ gss_host = xstrdup(options.gss_server_identity); -+ } else if (options.gss_trust_dns) { -+ gss_host = remote_hostname(ssh); -+ /* Fall back to specified host if we are using proxy command -+ * and can not use DNS on that socket */ -+ if (strcmp(gss_host, "UNKNOWN") == 0) { -+ free(gss_host); -+ gss_host = xstrdup(host); -+ } -+ } else { - gss_host = xstrdup(host); - } -- } else { -- gss_host = xstrdup(host); -- } - -- gss = ssh_gssapi_client_mechanisms(gss_host, -- options.gss_client_identity, options.gss_kex_algorithms); -- if (gss) { -- debug("Offering GSSAPI proposal: %s", gss); -- xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -- "%s,%s", gss, orig); -- -- /* If we've got GSSAPI algorithms, then we also support the -- * 'null' hostkey, as a last resort */ -- orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; -- xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], -- "%s,null", orig); -+ gss = ssh_gssapi_client_mechanisms(gss_host, -+ options.gss_client_identity, options.gss_kex_algorithms); -+ if (gss) { -+ debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -+ "%s,%s", gss, orig); -+ -+ /* If we've got GSSAPI algorithms, then we also support the -+ * 'null' hostkey, as a last resort */ -+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; -+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "%s,null", orig); -+ } + /* Add the GSSAPI mechanisms currently supported on this + * client to the key exchange algorithm proposal */ + orig = myproposal[PROPOSAL_KEX_ALGS]; +@@ -281,7 +286,9 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, } - } - #endif -diff --git a/sshd-auth.c b/sshd-auth.c -index 897db9b4..eaf32981 100644 ---- a/sshd-auth.c -+++ b/sshd-auth.c -@@ -58,6 +58,7 @@ - #ifdef WITH_OPENSSL + + gss = ssh_gssapi_client_mechanisms(gss_host, +- options.gss_client_identity, options.gss_kex_algorithms); ++ options.gss_client_identity, gss_kex_filtered); ++ free(gss_kex_filtered); ++ + if (gss) { + debug("Offering GSSAPI proposal: %s", gss); + xasprintf(&myproposal[PROPOSAL_KEX_ALGS], +diff --git a/sshd-session.c b/sshd-session.c +index a808ac9a6..a67a78391 100644 +--- a/sshd-session.c ++++ b/sshd-session.c +@@ -62,6 +62,7 @@ #include #include + #include +#include + #include "openbsd-compat/openssl-compat.h" #endif - #include "xmalloc.h" -@@ -859,10 +860,14 @@ do_ssh2_kex(struct ssh *ssh) - if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) - orig = NULL; - -- if (options.gss_keyex) -- gss = ssh_gssapi_server_mechanisms(); -- else -- gss = NULL; -+ if (options.gss_keyex) { -+ if (FIPS_mode()) { -+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode"); -+ options.gss_keyex = 0; -+ } else { -+ gss = ssh_gssapi_server_mechanisms(); -+ } -+ } - - if (gss && orig) - xasprintf(&newstr, "%s,%s", gss, orig); diff --git a/sshd.c b/sshd.c -index 8a99f0b2..5ff0b5ff 100644 +index 8a99f0b29..5ff0b5ff0 100644 --- a/sshd.c +++ b/sshd.c @@ -52,6 +52,7 @@ @@ -726,7 +676,7 @@ index 8a99f0b2..5ff0b5ff 100644 * Chdir to the root directory so that the current disk can be * unmounted if desired. diff --git a/sshkey.c b/sshkey.c -index 4e41a78c..ca1cdb64 100644 +index 4e41a78c7..ca1cdb642 100644 --- a/sshkey.c +++ b/sshkey.c @@ -35,6 +35,7 @@ @@ -809,5 +759,5 @@ index 4e41a78c..ca1cdb64 100644 return SSH_ERR_KEY_TYPE_UNKNOWN; return impl->funcs->verify(key, sig, siglen, data, dlen, -- -2.49.0 +2.51.0 diff --git a/openssh.spec b/openssh.spec index 4f98f19..b675ec5 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 5%{?dist} +Release: 6%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -586,6 +586,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Thu Aug 28 2025 Dmitry Belyavskiy - 10.0p1-6 +- Enable GSS KEX in FIPS mode + * Thu Jul 24 2025 Fedora Release Engineering - 10.0p1-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild From fa07fe987f4d605044898a79bd55c032ad1ae806 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 15 Sep 2025 15:45:42 +0200 Subject: [PATCH 76/80] Minor cleanup --- 0042-openssh-7.7p1-fips.patch | 13 ------------- openssh.spec | 5 ++++- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/0042-openssh-7.7p1-fips.patch b/0042-openssh-7.7p1-fips.patch index 9a81cc0..54997e3 100644 --- a/0042-openssh-7.7p1-fips.patch +++ b/0042-openssh-7.7p1-fips.patch @@ -20,7 +20,6 @@ Subject: [PATCH 42/54] openssh-7.7p1-fips ssh-rsa.c | 3 ++ ssh.c | 5 +++ sshconnect2.c | 9 ++++- - sshd-session.c | 1 + sshd.c | 13 +++++++ sshkey.c | 37 ++++++++++++++++++++ 19 files changed, 272 insertions(+), 30 deletions(-) @@ -618,18 +617,6 @@ index 0af15bcc1..3e02f485d 100644 if (gss) { debug("Offering GSSAPI proposal: %s", gss); xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -diff --git a/sshd-session.c b/sshd-session.c -index a808ac9a6..a67a78391 100644 ---- a/sshd-session.c -+++ b/sshd-session.c -@@ -62,6 +62,7 @@ - #include - #include - #include -+#include - #include "openbsd-compat/openssl-compat.h" - #endif - diff --git a/sshd.c b/sshd.c index 8a99f0b29..5ff0b5ff0 100644 --- a/sshd.c diff --git a/openssh.spec b/openssh.spec index b675ec5..7dcd46c 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 6%{?dist} +Release: 7%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -586,6 +586,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Mon Sep 15 2025 Dmitry Belyavskiy - 10.0p1-7 +- rebuilt + * Thu Aug 28 2025 Dmitry Belyavskiy - 10.0p1-6 - Enable GSS KEX in FIPS mode From ef51fad48251bc3a9da63b4aff0e2c3018ff7e81 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 3 Nov 2025 13:44:22 +0100 Subject: [PATCH 77/80] Implement mlkem768nistp256-sha256 and mlkem1024nistp384-sha384 KEX methods --- 0054-openssh-10.0-mlkem-nist.patch | 988 +++++++++++++++++++++++++++++ openssh.spec | 6 +- 2 files changed, 993 insertions(+), 1 deletion(-) create mode 100644 0054-openssh-10.0-mlkem-nist.patch diff --git a/0054-openssh-10.0-mlkem-nist.patch b/0054-openssh-10.0-mlkem-nist.patch new file mode 100644 index 0000000..9c3f105 --- /dev/null +++ b/0054-openssh-10.0-mlkem-nist.patch @@ -0,0 +1,988 @@ +diff --git a/crypto_api.h b/crypto_api.h +index 8bbc3a08a..6940bbf0e 100644 +--- a/crypto_api.h ++++ b/crypto_api.h +@@ -58,4 +58,8 @@ int crypto_kem_sntrup761_keypair(unsigned char *pk, unsigned char *sk); + #define crypto_kem_mlkem768_CIPHERTEXTBYTES 1088 + #define crypto_kem_mlkem768_BYTES 32 + ++#define crypto_kem_mlkem1024_PUBLICKEYBYTES 1568 ++#define crypto_kem_mlkem1024_SECRETKEYBYTES 3168 ++#define crypto_kem_mlkem1024_CIPHERTEXTBYTES 1568 ++ + #endif /* crypto_api_h */ +diff --git a/kex-names.c b/kex-names.c +index 36a953ab2..a728e0b38 100644 +--- a/kex-names.c ++++ b/kex-names.c +@@ -90,6 +90,10 @@ static const struct kexalg kexalgs[] = { + #ifdef USE_MLKEM768X25519 + { KEX_MLKEM768X25519_SHA256, KEX_KEM_MLKEM768X25519_SHA256, 0, + SSH_DIGEST_SHA256 }, ++ { KEX_MLKEM768NISTP256_SHA256, KEX_KEM_MLKEM768NISTP256_SHA256, 0, ++ SSH_DIGEST_SHA256 }, ++ { KEX_MLKEM1024NISTP384_SHA384, KEX_KEM_MLKEM1024NISTP384_SHA384, 0, ++ SSH_DIGEST_SHA384 }, + #endif + #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ + { NULL, 0, -1, -1}, +@@ -129,7 +133,9 @@ kex_alg_list_internal(char sep, const struct kexalg *algs) + const struct kexalg *k; + + for (k = algs; k->name != NULL; k++) { +- if (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0 ++ if ( (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0 ++ || strcmp(k->name, KEX_MLKEM768NISTP256_SHA256) == 0 ++ || strcmp(k->name, KEX_MLKEM1024NISTP384_SHA384) == 0) + && !is_mlkem768_available()) + continue; + if (ret != NULL) +@@ -163,7 +169,9 @@ kex_alg_by_name(const char *name) + { + const struct kexalg *k; + +- if (strcmp(name, KEX_MLKEM768X25519_SHA256) == 0 ++ if ( (strcmp(name, KEX_MLKEM768X25519_SHA256) == 0 ++ || strcmp(name, KEX_MLKEM768NISTP256_SHA256) == 0 ++ || strcmp(name, KEX_MLKEM1024NISTP384_SHA384) == 0) + && !is_mlkem768_available()) + return NULL; + +diff --git a/kex.c b/kex.c +index ce6a7b818..efaf5749c 100644 +--- a/kex.c ++++ b/kex.c +@@ -753,6 +753,7 @@ kex_free(struct kex *kex) + #ifdef OPENSSL_HAS_ECC + EC_KEY_free(kex->ec_client_key); + #endif /* OPENSSL_HAS_ECC */ ++ EVP_PKEY_free(kex->ec_hybrid_client_key); + #endif /* WITH_OPENSSL */ + for (mode = 0; mode < MODE_MAX; mode++) { + kex_free_newkeys(kex->newkeys[mode]); +diff --git a/kex.h b/kex.h +index 48f3bb875..50a461ddb 100644 +--- a/kex.h ++++ b/kex.h +@@ -72,6 +72,8 @@ + #define KEX_SNTRUP761X25519_SHA512 "sntrup761x25519-sha512" + #define KEX_SNTRUP761X25519_SHA512_OLD "sntrup761x25519-sha512@openssh.com" + #define KEX_MLKEM768X25519_SHA256 "mlkem768x25519-sha256" ++#define KEX_MLKEM768NISTP256_SHA256 "mlkem768nistp256-sha256" ++#define KEX_MLKEM1024NISTP384_SHA384 "mlkem1024nistp384-sha384" + + #define COMP_NONE 0 + #define COMP_DELAYED 2 +@@ -110,6 +112,8 @@ enum kex_exchange { + KEX_C25519_SHA256, + KEX_KEM_SNTRUP761X25519_SHA512, + KEX_KEM_MLKEM768X25519_SHA256, ++ KEX_KEM_MLKEM768NISTP256_SHA256, ++ KEX_KEM_MLKEM1024NISTP384_SHA384, + #ifdef GSSAPI + KEX_GSS_GRP1_SHA1, + KEX_GSS_GRP14_SHA1, +@@ -206,6 +210,9 @@ struct kex { + u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */ + u_char mlkem768_client_key[crypto_kem_mlkem768_SECRETKEYBYTES]; /* KEM */ + struct sshbuf *client_pub; ++ /* FIXME */ ++ EVP_PKEY *ec_hybrid_client_key; /* NIST hybrids */ ++ u_char mlkem1024_client_key[crypto_kem_mlkem1024_SECRETKEYBYTES]; /* ML-KEM 1024 + NIST */ + }; + + int kex_name_valid(const char *); +@@ -287,6 +294,18 @@ int kex_kem_mlkem768x25519_enc(struct kex *, const struct sshbuf *, + int kex_kem_mlkem768x25519_dec(struct kex *, const struct sshbuf *, + struct sshbuf **); + ++int kex_kem_mlkem768nistp256_keypair(struct kex *); ++int kex_kem_mlkem768nistp256_enc(struct kex *, const struct sshbuf *, ++ struct sshbuf **, struct sshbuf **); ++int kex_kem_mlkem768nistp256_dec(struct kex *, const struct sshbuf *, ++ struct sshbuf **); ++ ++int kex_kem_mlkem1024nistp384_keypair(struct kex *); ++int kex_kem_mlkem1024nistp384_enc(struct kex *, const struct sshbuf *, ++ struct sshbuf **, struct sshbuf **); ++int kex_kem_mlkem1024nistp384_dec(struct kex *, const struct sshbuf *, ++ struct sshbuf **); ++ + int kex_dh_keygen(struct kex *); + int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); + +diff --git a/kexgen.c b/kexgen.c +index eecdceba2..6e910f84f 100644 +--- a/kexgen.c ++++ b/kexgen.c +@@ -139,6 +139,22 @@ kex_gen_client(struct ssh *ssh) + r = kex_kem_mlkem768x25519_keypair(kex); + } + break; ++ case KEX_KEM_MLKEM768NISTP256_SHA256: ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768nistp256 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768nistp256_keypair(kex); ++ } ++ break; ++ case KEX_KEM_MLKEM1024NISTP384_SHA384: ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem1024nistp384 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem1024nistp384_keypair(kex); ++ } ++ break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; +@@ -230,6 +246,24 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) + &shared_secret); + } + break; ++ case KEX_KEM_MLKEM768NISTP256_SHA256: ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768nistp256 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768nistp256_dec(kex, server_blob, ++ &shared_secret); ++ } ++ break; ++ case KEX_KEM_MLKEM1024NISTP384_SHA384: ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem1024nistp384 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem1024nistp384_dec(kex, server_blob, ++ &shared_secret); ++ } ++ break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; +@@ -283,6 +317,8 @@ out: + sizeof(kex->sntrup761_client_key)); + explicit_bzero(kex->mlkem768_client_key, + sizeof(kex->mlkem768_client_key)); ++ explicit_bzero(kex->mlkem1024_client_key, ++ sizeof(kex->mlkem1024_client_key)); + sshbuf_free(server_host_key_blob); + free(signature); + sshbuf_free(tmp); +@@ -369,6 +405,24 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) + &server_pubkey, &shared_secret); + } + break; ++ case KEX_KEM_MLKEM768NISTP256_SHA256: ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem768nistp256 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem768nistp256_enc(kex, client_pubkey, ++ &server_pubkey, &shared_secret); ++ } ++ break; ++ case KEX_KEM_MLKEM1024NISTP384_SHA384: ++ if (FIPS_mode()) { ++ logit_f("Key exchange type mlkem1024nistp384 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ r = kex_kem_mlkem1024nistp384_enc(kex, client_pubkey, ++ &server_pubkey, &shared_secret); ++ } ++ break; + default: + r = SSH_ERR_INVALID_ARGUMENT; + break; +diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c +index 670049dcd..463d18771 100644 +--- a/kexmlkem768x25519.c ++++ b/kexmlkem768x25519.c +@@ -53,14 +53,15 @@ + #include + + static int +-mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) ++mlkem_keypair_gen(const char *algname, unsigned char *pubkeybuf, size_t pubkey_size, ++ unsigned char *privkeybuf, size_t privkey_size) + { + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; +- size_t pubkey_size = crypto_kem_mlkem768_PUBLICKEYBYTES, privkey_size = crypto_kem_mlkem768_SECRETKEYBYTES; ++ size_t got_pub_size = pubkey_size, got_priv_size = privkey_size; + +- ctx = EVP_PKEY_CTX_new_from_name(NULL, "mlkem768", NULL); ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, algname, NULL); + if (ctx == NULL) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto err; +@@ -72,17 +73,23 @@ mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) + goto err; + } + +- if (EVP_PKEY_get_raw_public_key(pkey, pubkeybuf, &pubkey_size) <= 0 +- || EVP_PKEY_get_raw_private_key(pkey, privkeybuf, &privkey_size) <= 0) { ++ if (EVP_PKEY_get_raw_public_key(pkey, NULL, &got_pub_size) <= 0 ++ || EVP_PKEY_get_raw_private_key(pkey, NULL, &got_priv_size) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } ++ ++ if (privkey_size != got_priv_size || pubkey_size != got_pub_size) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } + +- if (privkey_size != crypto_kem_mlkem768_SECRETKEYBYTES +- || pubkey_size != crypto_kem_mlkem768_PUBLICKEYBYTES) { ++ if (EVP_PKEY_get_raw_public_key(pkey, pubkeybuf, &got_pub_size) <= 0 ++ || EVP_PKEY_get_raw_private_key(pkey, privkeybuf, &got_priv_size) <= 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } ++ + ret = 0; + + err: +@@ -94,16 +101,40 @@ mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) + } + + static int +-mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) ++mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) ++{ ++ return mlkem_keypair_gen("mlkem768", pubkeybuf, crypto_kem_mlkem768_PUBLICKEYBYTES, ++ privkeybuf, crypto_kem_mlkem768_SECRETKEYBYTES); ++} ++ ++static int ++mlkem1024_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) ++{ ++ return mlkem_keypair_gen("mlkem1024", pubkeybuf, crypto_kem_mlkem1024_PUBLICKEYBYTES, ++ privkeybuf, crypto_kem_mlkem1024_SECRETKEYBYTES); ++} ++ ++static int ++mlkem_encap_secret(const char *mlkem_alg, const u_char *pubkeybuf, u_char *secret, u_char *out) + { + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + int r = SSH_ERR_INTERNAL_ERROR; +- size_t outlen = crypto_kem_mlkem768_CIPHERTEXTBYTES, +- secretlen = crypto_kem_mlkem768_BYTES; ++ size_t outlen, expected_outlen, publen, secretlen = crypto_kem_mlkem768_BYTES; ++ ++ if (strcmp(mlkem_alg, "mlkem768") == 0) { ++ outlen = crypto_kem_mlkem768_CIPHERTEXTBYTES; ++ publen = crypto_kem_mlkem768_PUBLICKEYBYTES; ++ } else if (strcmp(mlkem_alg, "mlkem1024") == 0) { ++ outlen = crypto_kem_mlkem1024_CIPHERTEXTBYTES; ++ publen = crypto_kem_mlkem1024_PUBLICKEYBYTES; ++ } else ++ return r; + +- pkey = EVP_PKEY_new_raw_public_key_ex(NULL, "mlkem768", NULL, +- pubkeybuf, crypto_kem_mlkem768_PUBLICKEYBYTES); ++ expected_outlen = outlen; ++ ++ pkey = EVP_PKEY_new_raw_public_key_ex(NULL, mlkem_alg, NULL, ++ pubkeybuf, publen); + if (pkey == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; +@@ -112,9 +143,9 @@ mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) + ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + if (ctx == NULL + || EVP_PKEY_encapsulate_init(ctx, NULL) <= 0 +- || EVP_PKEY_encapsulate(ctx, out, &outlen, secret, &secretlen) <= 0 ++ || EVP_PKEY_encapsulate(ctx, out, &expected_outlen, secret, &secretlen) <= 0 + || secretlen != crypto_kem_mlkem768_BYTES +- || outlen != crypto_kem_mlkem768_CIPHERTEXTBYTES) { ++ || outlen != expected_outlen) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; + } +@@ -130,16 +161,30 @@ mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) + } + + static int +-mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *secret) ++mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) ++{ ++ return mlkem_encap_secret("mlkem768", pubkeybuf, secret, out); ++} ++ ++static int ++mlkem1024_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) ++{ ++ return mlkem_encap_secret("mlkem1024", pubkeybuf, secret, out); ++} ++ ++static int ++mlkem_decap_secret(const char *algname, ++ const u_char *privkeybuf, size_t privkey_len, ++ const u_char *wrapped, size_t wrapped_len, ++ u_char *secret) + { + EVP_PKEY *pkey = NULL; + EVP_PKEY_CTX *ctx = NULL; + int r = SSH_ERR_INTERNAL_ERROR; +- size_t wrappedlen = crypto_kem_mlkem768_CIPHERTEXTBYTES, +- secretlen = crypto_kem_mlkem768_BYTES; ++ size_t secretlen = crypto_kem_mlkem768_BYTES; + +- pkey = EVP_PKEY_new_raw_private_key_ex(NULL, "mlkem768", NULL, +- privkeybuf, crypto_kem_mlkem768_SECRETKEYBYTES); ++ pkey = EVP_PKEY_new_raw_private_key_ex(NULL, algname, ++ NULL, privkeybuf, privkey_len); + if (pkey == NULL) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; +@@ -148,7 +193,7 @@ mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *s + ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + if (ctx == NULL + || EVP_PKEY_decapsulate_init(ctx, NULL) <= 0 +- || EVP_PKEY_decapsulate(ctx, secret, &secretlen, wrapped, wrappedlen) <= 0 ++ || EVP_PKEY_decapsulate(ctx, secret, &secretlen, wrapped, wrapped_len) <= 0 + || secretlen != crypto_kem_mlkem768_BYTES) { + r = SSH_ERR_LIBCRYPTO_ERROR; + goto err; +@@ -165,6 +210,20 @@ mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *s + return r; + } + ++static int ++mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *secret) ++{ ++ return mlkem_decap_secret("mlkem768", privkeybuf, crypto_kem_mlkem768_SECRETKEYBYTES, ++ wrapped, crypto_kem_mlkem768_CIPHERTEXTBYTES, secret); ++} ++ ++static int ++mlkem1024_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *secret) ++{ ++ return mlkem_decap_secret("mlkem1024", privkeybuf, crypto_kem_mlkem1024_SECRETKEYBYTES, ++ wrapped, crypto_kem_mlkem1024_CIPHERTEXTBYTES, secret); ++} ++ + int + kex_kem_mlkem768x25519_keypair(struct kex *kex) + { +@@ -341,7 +400,7 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t need; + int r = SSH_ERR_INTERNAL_ERROR; +- struct libcrux_mlkem768_enc_result enc; /* FIXME */ ++ struct libcrux_mlkem768_enc_result enc; + + *server_blobp = NULL; + *shared_secretp = NULL; +@@ -550,6 +609,468 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, + return r; + #endif + } ++ ++#define NIST_P256_COMPRESSED_LEN 33 ++#define NIST_P256_UNCOMPRESSED_LEN 65 ++#define NIST_P384_COMPRESSED_LEN 49 ++#define NIST_P384_UNCOMPRESSED_LEN 97 ++#define NIST_BUF_MAX_SIZE NIST_P384_UNCOMPRESSED_LEN ++ ++static const char ec256[] = "P-256"; ++static const char ec384[] = "P-384"; ++static const char *len2curve_name(size_t len) ++{ ++ switch (len) { ++ case NIST_P256_COMPRESSED_LEN: ++ case NIST_P256_UNCOMPRESSED_LEN: ++ return ec256; ++ break; ++ case NIST_P384_COMPRESSED_LEN: ++ case NIST_P384_UNCOMPRESSED_LEN: ++ return ec384; ++ break; ++ } ++ return NULL; ++} ++ ++static EVP_PKEY * ++buf2nist_key(const unsigned char *pub_key_buf, size_t pub_key_len) ++{ ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ OSSL_PARAM params[3]; ++ const char *curve_name = len2curve_name(pub_key_len); ++ ++ if (curve_name == NULL) ++ return NULL; ++ ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); ++ if (!ctx) ++ goto err; ++ ++ if (EVP_PKEY_fromdata_init(ctx) <= 0) ++ goto err; ++ ++ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, curve_name, 0); ++ params[1] = OSSL_PARAM_construct_octet_string( ++ OSSL_PKEY_PARAM_PUB_KEY, (void *)pub_key_buf, pub_key_len); ++ params[2] = OSSL_PARAM_construct_end(); ++ ++ if (EVP_PKEY_fromdata(ctx, &pkey, EVP_PKEY_PUBLIC_KEY, params) <= 0) ++ goto err; ++ ++ EVP_PKEY_CTX_free(ctx); ++ return pkey; ++ ++err: ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(pkey); ++ return NULL; ++} ++ ++static int ++kex_nist_shared_key_ext(EVP_PKEY *priv_key, ++ const u_char *pub_key_buf, size_t pub_key_len, struct sshbuf *out) ++{ ++ EVP_PKEY_CTX *ctx = NULL; ++ unsigned char *shared_secret = NULL; ++ size_t shared_secret_len = 0; ++ EVP_PKEY *peer_key = buf2nist_key(pub_key_buf, pub_key_len); ++ int r = SSH_ERR_INTERNAL_ERROR; ++ ++ if (peer_key == NULL) ++ return SSH_ERR_KEY_LENGTH; ++ ++ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, priv_key, NULL); ++ if (!ctx) ++ goto end; ++ ++ if ((EVP_PKEY_derive_init(ctx) <= 0) ++ || EVP_PKEY_derive_set_peer(ctx, peer_key) <= 0 ++ || EVP_PKEY_derive(ctx, NULL, &shared_secret_len) <= 0) ++ goto end; ++ ++ shared_secret = OPENSSL_malloc(shared_secret_len); ++ if (shared_secret == NULL) ++ goto end; ++ ++ if (EVP_PKEY_derive(ctx, shared_secret, &shared_secret_len) <= 0) ++ goto end; ++ ++ if ((r = sshbuf_put(out, shared_secret, shared_secret_len)) != 0) ++ goto end; ++ ++ r = 0; ++ ++end: ++ EVP_PKEY_free(peer_key); ++ if (shared_secret) ++ OPENSSL_clear_free(shared_secret, shared_secret_len); ++ EVP_PKEY_CTX_free(ctx); ++ ++ return r; ++} ++ ++static EVP_PKEY * ++nist_pkey_keygen(size_t pub_key_len) ++{ ++ const char *curve_name = len2curve_name(pub_key_len); ++ EVP_PKEY_CTX *pctx = NULL; ++ EVP_PKEY *pkey = NULL; ++ OSSL_PARAM params[2]; ++ ++ if (curve_name == NULL) ++ return NULL; ++ ++ pctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL); ++ if (!pctx) ++ return NULL; ++ ++ if (EVP_PKEY_keygen_init(pctx) <= 0) { ++ EVP_PKEY_CTX_free(pctx); ++ return NULL; ++ } ++ ++ params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, curve_name, 0); ++ params[1] = OSSL_PARAM_construct_end(); ++ ++ if (EVP_PKEY_CTX_set_params(pctx, params) <= 0 ++ || EVP_PKEY_keygen(pctx, &pkey) <= 0) { ++ EVP_PKEY_CTX_free(pctx); ++ return NULL; ++ } ++ ++ EVP_PKEY_CTX_free(pctx); ++ return pkey; ++} ++ ++static int ++get_uncompressed_ec_pubkey(EVP_PKEY *pkey, unsigned char *buf, size_t buf_len) ++{ ++ OSSL_PARAM params[2]; ++ size_t required_len = 0, out_len = 0; ++ ++ params[0] = OSSL_PARAM_construct_utf8_string( ++ OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT, ++ "uncompressed", 0); ++ params[1] = OSSL_PARAM_construct_end(); ++ ++ if (EVP_PKEY_set_params(pkey, params) <= 0 ++ || EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, ++ NULL, 0, &required_len) <= 0) { ++ return SSH_ERR_LIBCRYPTO_ERROR; ++ } ++ ++ if (required_len != buf_len) ++ return SSH_ERR_INTERNAL_ERROR; ++ ++ if (EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, ++ buf, required_len, &out_len) <= 0) { ++ return SSH_ERR_LIBCRYPTO_ERROR; ++ } ++ ++ return 0; ++} ++/* nist_bytes_len should always be uncompressed */ ++static int ++kex_kem_mlkem_nist_keypair(struct kex *kex, size_t mlkem_bytes_len, size_t nist_bytes_len) ++{ ++ struct sshbuf *buf = NULL; ++ u_char *cp = NULL; ++ size_t need; ++ int r = SSH_ERR_INTERNAL_ERROR; ++ u_char *client_key = NULL; ++ ++ if ((buf = sshbuf_new()) == NULL) ++ return SSH_ERR_ALLOC_FAIL; ++ need = mlkem_bytes_len + nist_bytes_len; ++ if ((r = sshbuf_reserve(buf, need, &cp)) != 0) ++ goto out; ++ ++ if (mlkem_bytes_len == crypto_kem_mlkem768_PUBLICKEYBYTES) { ++ client_key = kex->mlkem768_client_key; ++ r = mlkem768_keypair_gen(cp, client_key); ++ } ++ ++ if (mlkem_bytes_len == crypto_kem_mlkem1024_PUBLICKEYBYTES) { ++ client_key = kex->mlkem1024_client_key; ++ r = mlkem1024_keypair_gen(cp, client_key); ++ } ++ ++ if (client_key == NULL) ++ goto out; ++ ++ if (r != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("client public key mlkemXXX:", cp, mlkem_bytes_len); ++#endif ++ cp += mlkem_bytes_len; ++ if ((kex->ec_hybrid_client_key = nist_pkey_keygen(nist_bytes_len)) == NULL) ++ goto out; ++ ++ if ((r = get_uncompressed_ec_pubkey(kex->ec_hybrid_client_key, cp, nist_bytes_len)) != 0) ++ goto out; ++ ++#ifdef DEBUG_KEXECDH ++ dump_digest("client public key NIST:", cp, nist_bytes_len); ++#endif ++ /* success */ ++ r = 0; ++ kex->client_pub = buf; ++ buf = NULL; ++ out: ++ sshbuf_free(buf); ++ if (r == SSH_ERR_LIBCRYPTO_ERROR) ++ ERR_print_errors_fp(stderr); ++ ++ return r; ++} ++ ++static int ++kex_kem_mlkem_nist_enc(struct kex *kex, const char *nist_curve, ++ const struct sshbuf *client_blob, struct sshbuf **server_blobp, ++ struct sshbuf **shared_secretp) ++{ ++ struct sshbuf *server_blob = NULL; ++ struct sshbuf *buf = NULL; ++ const u_char *client_pub; ++ u_char server_pub[NIST_BUF_MAX_SIZE]; ++ u_char enc_out[crypto_kem_mlkem1024_CIPHERTEXTBYTES]; ++ u_char secret[crypto_kem_mlkem768_BYTES]; ++ EVP_PKEY *server_key = NULL; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t client_buf_len, mlkem_buf_len, ecdh_buf_len, server_key_len, enc_out_len; ++ int r = SSH_ERR_INTERNAL_ERROR; ++ ++ *server_blobp = NULL; ++ *shared_secretp = NULL; ++ ++ client_buf_len = sshbuf_len(client_blob); ++ /* client_blob contains both KEM and ECDH client pubkeys */ ++ if (strcmp(nist_curve, "P-256") == 0) { ++ if (crypto_kem_mlkem768_PUBLICKEYBYTES > client_buf_len) ++ return r; ++ ++ ecdh_buf_len = client_buf_len - crypto_kem_mlkem768_PUBLICKEYBYTES; ++ if (ecdh_buf_len != NIST_P256_COMPRESSED_LEN && ++ ecdh_buf_len != NIST_P256_UNCOMPRESSED_LEN) ++ return r; ++ mlkem_buf_len = crypto_kem_mlkem768_PUBLICKEYBYTES; ++ enc_out_len = crypto_kem_mlkem768_CIPHERTEXTBYTES; ++ server_key_len = NIST_P256_UNCOMPRESSED_LEN; ++ } else if (strcmp(nist_curve, "P-384") == 0) { ++ if (crypto_kem_mlkem1024_PUBLICKEYBYTES > client_buf_len) ++ return r; ++ ++ ecdh_buf_len = client_buf_len - crypto_kem_mlkem1024_PUBLICKEYBYTES; ++ if (ecdh_buf_len != NIST_P384_COMPRESSED_LEN && ++ ecdh_buf_len != NIST_P384_UNCOMPRESSED_LEN) ++ return r; ++ mlkem_buf_len = crypto_kem_mlkem1024_PUBLICKEYBYTES; ++ enc_out_len = crypto_kem_mlkem1024_CIPHERTEXTBYTES; ++ server_key_len = NIST_P384_UNCOMPRESSED_LEN; ++ } else ++ return r; ++ ++ client_pub = sshbuf_ptr(client_blob); ++#ifdef DEBUG_KEXECDH ++ dump_digest("client public key mlkem:", client_pub, mlkem_buf_len); ++ dump_digest("client public key NIST:", client_pub + mlkem_buf_len, ecdh_buf_len); ++#endif ++ ++ /* allocate buffer for concatenation of KEM key and ECDH shared key */ ++ /* the buffer will be hashed and the result is the shared secret */ ++ if ((buf = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ /* allocate space for encrypted KEM key and ECDH pub key */ ++ if ((server_blob = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ r = (mlkem_buf_len == crypto_kem_mlkem768_PUBLICKEYBYTES) ? ++ mlkem768_encap_secret(client_pub, secret, enc_out) : ++ mlkem1024_encap_secret(client_pub, secret, enc_out); ++ ++ if (r != 0) ++ goto out; ++ ++ /* generate ECDH key pair, store server pubkey after ciphertext */ ++ server_key = nist_pkey_keygen(server_key_len); ++ ++ if ((r = get_uncompressed_ec_pubkey(server_key, server_pub, server_key_len) != 0) || ++ (r = sshbuf_put(buf, secret, sizeof(secret))) != 0 || ++ (r = sshbuf_put(server_blob, enc_out, enc_out_len) != 0)|| ++ (r = sshbuf_put(server_blob, server_pub, server_key_len)) != 0) ++ goto out; ++ ++ /* append ECDH shared key */ ++ client_pub += mlkem_buf_len; ++ if ((r = kex_nist_shared_key_ext(server_key, client_pub, ecdh_buf_len, buf)) < 0) ++ goto out; ++ if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("server public NIST:", server_pub, server_key_len); ++ dump_digest("server cipher text:", enc_out, enc_out_len); ++ dump_digest("server kem key:", secret, sizeof(secret)); ++ dump_digest("concatenation of KEM key and ECDH shared key:", ++ sshbuf_ptr(buf), sshbuf_len(buf)); ++#endif ++ /* string-encoded hash is resulting shared secret */ ++ sshbuf_reset(buf); ++ if ((r = sshbuf_put_string(buf, hash, ++ ssh_digest_bytes(kex->hash_alg))) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); ++#endif ++ /* success */ ++ r = 0; ++ *server_blobp = server_blob; ++ *shared_secretp = buf; ++ server_blob = NULL; ++ buf = NULL; ++ out: ++ explicit_bzero(hash, sizeof(hash)); ++ EVP_PKEY_free(server_key); ++ explicit_bzero(enc_out, sizeof(enc_out)); ++ explicit_bzero(secret, sizeof(secret)); ++ sshbuf_free(server_blob); ++ sshbuf_free(buf); ++ return r; ++} ++ ++static int ++kex_kem_mlkem_nist_dec(struct kex *kex, ++ const struct sshbuf *server_blob, struct sshbuf **shared_secretp, ++ size_t mlkem_len) ++{ ++ struct sshbuf *buf = NULL; ++ const u_char *ciphertext, *server_pub; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ u_char decap[crypto_kem_mlkem768_BYTES]; ++ int r; ++ size_t nist_len; ++ ++ *shared_secretp = NULL; ++ ++ if (sshbuf_len(server_blob) < mlkem_len) { ++ r = SSH_ERR_SIGNATURE_INVALID; ++ goto out; ++ } ++ ++ nist_len = sshbuf_len(server_blob) - mlkem_len; ++ ++ switch (mlkem_len) { ++ case crypto_kem_mlkem768_CIPHERTEXTBYTES: ++ if (nist_len != NIST_P256_COMPRESSED_LEN ++ && nist_len != NIST_P256_UNCOMPRESSED_LEN) { ++ r = SSH_ERR_SIGNATURE_INVALID; ++ goto out; ++ } ++ break; ++ case crypto_kem_mlkem1024_CIPHERTEXTBYTES: ++ if (nist_len != NIST_P384_COMPRESSED_LEN ++ && nist_len != NIST_P384_UNCOMPRESSED_LEN) { ++ r = SSH_ERR_SIGNATURE_INVALID; ++ goto out; ++ } ++ break; ++ } ++ ++ ciphertext = sshbuf_ptr(server_blob); ++ server_pub = ciphertext + mlkem_len; ++ /* hash concatenation of KEM key and ECDH shared key */ ++ if ((buf = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++#ifdef DEBUG_KEXECDH ++ dump_digest("server cipher text:", ciphertext, mlkem_len); ++ dump_digest("server public key NIST:", server_pub, nist_len); ++#endif ++ r = (mlkem_len == crypto_kem_mlkem768_CIPHERTEXTBYTES) ? ++ mlkem768_decap_secret(kex->mlkem768_client_key, ciphertext, decap) : ++ mlkem1024_decap_secret(kex->mlkem1024_client_key, ciphertext, decap); ++ ++ if (r != 0) ++ goto out; ++ if ((r = sshbuf_put(buf, decap, sizeof(decap))) != 0) ++ goto out; ++ if ((r = kex_nist_shared_key_ext(kex->ec_hybrid_client_key, server_pub, ++ nist_len, buf)) < 0) ++ goto out; ++ if ((r = ssh_digest_buffer(kex->hash_alg, buf, ++ hash, sizeof(hash))) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("client kem key:", decap, sizeof(decap)); ++ dump_digest("concatenation of KEM key and ECDH shared key:", ++ sshbuf_ptr(buf), sshbuf_len(buf)); ++#endif ++ sshbuf_reset(buf); ++ if ((r = sshbuf_put_string(buf, hash, ++ ssh_digest_bytes(kex->hash_alg))) != 0) ++ goto out; ++#ifdef DEBUG_KEXECDH ++ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf)); ++#endif ++ /* success */ ++ r = 0; ++ *shared_secretp = buf; ++ buf = NULL; ++ out: ++ explicit_bzero(hash, sizeof(hash)); ++ explicit_bzero(decap, sizeof(decap)); ++ sshbuf_free(buf); ++ return r; ++} ++ ++int ++kex_kem_mlkem768nistp256_keypair(struct kex *kex) ++{ ++ return kex_kem_mlkem_nist_keypair(kex, crypto_kem_mlkem768_PUBLICKEYBYTES, NIST_P256_UNCOMPRESSED_LEN); ++} ++ ++int ++kex_kem_mlkem768nistp256_enc(struct kex *kex, const struct sshbuf *client_blob, ++ struct sshbuf **server_blobp, struct sshbuf **shared_secretp) ++{ ++ return kex_kem_mlkem_nist_enc(kex, "P-256", client_blob, server_blobp, shared_secretp); ++} ++ ++int ++kex_kem_mlkem768nistp256_dec(struct kex *kex, const struct sshbuf *server_blob, ++ struct sshbuf **shared_secretp) ++{ ++ return kex_kem_mlkem_nist_dec(kex, server_blob, shared_secretp, ++ crypto_kem_mlkem768_CIPHERTEXTBYTES); ++} ++ ++int ++kex_kem_mlkem1024nistp384_keypair(struct kex *kex) ++{ ++ return kex_kem_mlkem_nist_keypair(kex, crypto_kem_mlkem1024_PUBLICKEYBYTES, NIST_P384_UNCOMPRESSED_LEN); ++} ++ ++int ++kex_kem_mlkem1024nistp384_enc(struct kex *kex, const struct sshbuf *client_blob, ++ struct sshbuf **server_blobp, struct sshbuf **shared_secretp) ++{ ++ return kex_kem_mlkem_nist_enc(kex, "P-384", client_blob, server_blobp, shared_secretp); ++} ++ ++int ++kex_kem_mlkem1024nistp384_dec(struct kex *kex, const struct sshbuf *server_blob, ++ struct sshbuf **shared_secretp) ++{ ++ return kex_kem_mlkem_nist_dec(kex, server_blob, shared_secretp, ++ crypto_kem_mlkem1024_CIPHERTEXTBYTES); ++} ++ + #else /* USE_MLKEM768X25519 */ + int + kex_kem_mlkem768x25519_keypair(struct kex *kex) +@@ -571,4 +1092,39 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, + { + return SSH_ERR_SIGN_ALG_UNSUPPORTED; + } ++ ++int kex_kem_mlkem768nistp256_keypair(struct kex *) ++{ ++ return SSH_ERR_SIGN_ALG_UNSUPPORTED; ++} ++ ++int kex_kem_mlkem768nistp256_enc(struct kex *, const struct sshbuf *, ++ struct sshbuf **, struct sshbuf **) ++{ ++ return SSH_ERR_SIGN_ALG_UNSUPPORTED; ++} ++ ++int kex_kem_mlkem768nistp256_dec(struct kex *, const struct sshbuf *, ++ struct sshbuf **) ++{ ++ return SSH_ERR_SIGN_ALG_UNSUPPORTED; ++} ++ ++int kex_kem_mlkem1024nistp384_keypair(struct kex *) ++{ ++ return SSH_ERR_SIGN_ALG_UNSUPPORTED; ++} ++ ++int kex_kem_mlkem1024nistp384_enc(struct kex *, const struct sshbuf *, ++ struct sshbuf **, struct sshbuf **) ++{ ++ return SSH_ERR_SIGN_ALG_UNSUPPORTED; ++} ++ ++int kex_kem_mlkem1024nistp384_dec(struct kex *, const struct sshbuf *, ++ struct sshbuf **) ++{ ++ return SSH_ERR_SIGN_ALG_UNSUPPORTED; ++} ++ + #endif /* USE_MLKEM768X25519 */ +diff --git a/monitor.c b/monitor.c +index 58fbac9df..75413ce71 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -2009,6 +2009,8 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; + kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; ++ kex->kex[KEX_KEM_MLKEM768NISTP256_SHA256] = kex_gen_server; ++ kex->kex[KEX_KEM_MLKEM1024NISTP384_SHA384] = kex_gen_server; + kex->load_host_public_key=&get_hostkey_public_by_type; + kex->load_host_private_key=&get_hostkey_private_by_type; + kex->host_key_index=&get_hostkey_index; +diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c +index 09016aead..2baf9a7a0 100644 +--- a/regress/unittests/kex/test_kex.c ++++ b/regress/unittests/kex/test_kex.c +@@ -155,6 +155,8 @@ do_kex_with_key(char *kex, int keytype, int bits) + server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; + server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; + server2->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; ++ server2->kex->kex[KEX_KEM_MLKEM768NISTP256_SHA256] = kex_gen_server; ++ server2->kex->kex[KEX_KEM_MLKEM1024NISTP384_SHA384] = 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; + server2->kex->sign = server->kex->sign; +@@ -211,6 +213,8 @@ kex_tests(void) + do_kex("diffie-hellman-group1-sha1"); + # ifdef USE_MLKEM768X25519 + do_kex("mlkem768x25519-sha256"); ++ do_kex("mlkem768nistp256-sha256"); ++ do_kex("mlkem1024nistp384-sha384"); + # endif /* USE_MLKEM768X25519 */ + # ifdef USE_SNTRUP761X25519 + do_kex("sntrup761x25519-sha512@openssh.com"); +diff --git a/ssh-keyscan.c b/ssh-keyscan.c +index 9f76ad225..8660088b7 100644 +--- a/ssh-keyscan.c ++++ b/ssh-keyscan.c +@@ -304,6 +304,8 @@ keygrab_ssh2(con *c) + c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + c->c_ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; + c->c_ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_client; ++ c->c_ssh->kex->kex[KEX_KEM_MLKEM768NISTP256_SHA256] = kex_gen_client; ++ c->c_ssh->kex->kex[KEX_KEM_MLKEM1024NISTP384_SHA384] = kex_gen_client; + ssh_set_verify_host_key_callback(c->c_ssh, key_print_wrapper); + /* + * do the key-exchange until an error occurs or until +diff --git a/ssh_api.c b/ssh_api.c +index 7bdcee148..d20b03a00 100644 +--- a/ssh_api.c ++++ b/ssh_api.c +@@ -135,6 +135,8 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_server; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; + ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; ++ ssh->kex->kex[KEX_KEM_MLKEM768NISTP256_SHA256] = kex_gen_server; ++ ssh->kex->kex[KEX_KEM_MLKEM1024NISTP384_SHA384] = kex_gen_server; + ssh->kex->load_host_public_key=&_ssh_host_public_key; + ssh->kex->load_host_private_key=&_ssh_host_private_key; + ssh->kex->sign=&_ssh_host_key_sign; +@@ -154,6 +156,8 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params) + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_client; ++ ssh->kex->kex[KEX_KEM_MLKEM768NISTP256_SHA256] = kex_gen_client; ++ ssh->kex->kex[KEX_KEM_MLKEM1024NISTP384_SHA384] = kex_gen_client; + ssh->kex->verify_host_key =&_ssh_verify_host_key; + } + *sshp = ssh; +diff --git a/sshconnect2.c b/sshconnect2.c +index 5beae1c10..6d9f1238b 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -347,6 +347,8 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_client; ++ ssh->kex->kex[KEX_KEM_MLKEM768NISTP256_SHA256] = kex_gen_client; ++ ssh->kex->kex[KEX_KEM_MLKEM1024NISTP384_SHA384] = kex_gen_client; + ssh->kex->verify_host_key=&verify_host_key_callback; + + #if defined(GSSAPI) && defined(WITH_OPENSSL) +diff --git a/sshd-auth.c b/sshd-auth.c +index 897db9b43..a1b43ba5a 100644 +--- a/sshd-auth.c ++++ b/sshd-auth.c +@@ -918,6 +918,8 @@ do_ssh2_kex(struct ssh *ssh) + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; + kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; ++ kex->kex[KEX_KEM_MLKEM768NISTP256_SHA256] = kex_gen_server; ++ kex->kex[KEX_KEM_MLKEM1024NISTP384_SHA384] = kex_gen_server; + kex->load_host_public_key=&get_hostkey_public_by_type; + kex->load_host_private_key=&get_hostkey_private_by_type; + kex->host_key_index=&get_hostkey_index; diff --git a/openssh.spec b/openssh.spec index 7dcd46c..c9600a6 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 7%{?dist} +Release: 8%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -182,6 +182,7 @@ Patch0051: 0051-Provide-better-error-for-non-supported-private-keys.patch Patch0052: 0052-Ignore-bad-hostkeys-in-known_hosts-file.patch # https://github.com/openssh/openssh-portable/pull/500 Patch0053: 0053-support-authentication-indicators-in-GSSAPI.patch +Patch0054: 0054-openssh-10.0-mlkem-nist.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 Patch1000: 1000-openssh-coverity.patch @@ -586,6 +587,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Mon Nov 03 2025 Dmitry Belyavskiy - 10.0p1-8 +- Implement mlkem768nistp256-sha256 and mlkem1024nistp384-sha384 KEX methods + * Mon Sep 15 2025 Dmitry Belyavskiy - 10.0p1-7 - rebuilt From c3d6c51bfca1cf6a2d452186c241470e63e06851 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Tue, 2 Dec 2025 14:05:50 +0100 Subject: [PATCH 78/80] Remove redundant SELinux patches --- 0001-openssh-7.8p1-role-mls.patch | 42 ++--- ...t.patch => 0002-openssh-6.6p1-keycat.patch | 42 ++--- 0002-openssh-6.6p1-privsep-selinux.patch | 144 ----------------- ... => 0003-openssh-6.6p1-allow-ip-opts.patch | 8 +- ....patch => 0004-openssh-5.9p1-ipv6man.patch | 10 +- ....patch => 0005-openssh-5.8p2-sigpipe.patch | 8 +- ...-x11.patch => 0006-openssh-7.2p2-x11.patch | 8 +- ... 0007-openssh-5.1p1-askpass-progress.patch | 8 +- ...0008-openssh-4.3p2-askpass-grab-info.patch | 8 +- ...t.patch => 0009-openssh-8.7p1-redhat.patch | 20 +-- ...=> 0010-openssh-7.8p1-UsePAM-warning.patch | 10 +- ...h => 0011-openssh-9.6p1-gssapi-keyex.patch | 94 +++++------ ...atch => 0012-openssh-6.6p1-force_krb.patch | 14 +- ...0013-openssh-7.7p1-gssapi-new-unique.patch | 26 ++-- ...0014-openssh-7.2p2-k5login_directory.patch | 14 +- ....patch => 0015-openssh-6.6p1-kuserok.patch | 18 +-- ... => 0016-openssh-6.4p1-fromto-remote.patch | 8 +- ...> 0017-openssh-6.6.1p1-log-in-chroot.patch | 36 ++--- ...h-6.6.1p1-scp-non-existing-directory.patch | 8 +- 0018-openssh-6.6.1p1-selinux-contexts.patch | 147 ------------------ ...19-openssh-6.6p1-GSSAPIEnablek5users.patch | 16 +- ...h => 0020-openssh-6.8p1-sshdT-output.patch | 8 +- ...-openssh-6.7p1-sftp-force-permission.patch | 10 +- ...=> 0022-openssh-7.2p2-s390-closefrom.patch | 8 +- ... 0023-openssh-7.3p1-x11-max-displays.patch | 20 +-- ...> 0024-openssh-7.6p1-cleanup-selinux.patch | 57 +++---- ....patch => 0025-openssh-7.5p1-sandbox.patch | 8 +- ...tch => 0026-openssh-8.0p1-pkcs11-uri.patch | 38 ++--- ...patch => 0027-openssh-7.8p1-scp-ipv6.patch | 8 +- ...> 0028-openssh-8.0p1-crypto-policies.patch | 10 +- ...ch => 0029-openssh-8.0p1-openssl-kdf.patch | 10 +- ...tch => 0030-openssh-8.2p1-visibility.patch | 8 +- ... 0031-openssh-8.2p1-x11-without-ipv6.patch | 8 +- ...32-openssh-8.0p1-preserve-pam-errors.patch | 8 +- ...> 0033-openssh-8.7p1-scp-kill-switch.patch | 12 +- ... => 0034-openssh-8.7p1-recursive-scp.patch | 14 +- ...tch => 0035-openssh-8.7p1-minrsabits.patch | 10 +- ...ca.patch => 0036-openssh-8.7p1-ibmca.patch | 8 +- ...it.patch => 0037-openssh-7.6p1-audit.patch | 76 ++++----- ...8-openssh-7.1p2-audit-race-condition.patch | 16 +- ...atch => 0039-openssh-9.0p1-audit-log.patch | 14 +- ...ips.patch => 0040-openssh-7.7p1-fips.patch | 8 +- ...ch => 0041-openssh-8.7p1-ssh-manpage.patch | 8 +- ...enssh-8.7p1-negotiate-supported-algs.patch | 10 +- ...h => 0043-openssh-9.0p1-evp-fips-kex.patch | 16 +- ...> 0044-openssh-8.7p1-nohostsha1proof.patch | 28 ++-- ...atch => 0045-openssh-9.6p1-pam-rhost.patch | 8 +- ... 0046-openssh-9.9p1-separate-keysign.patch | 8 +- ... => 0047-openssh-9.9p1-openssl-mlkem.patch | 10 +- ... 0048-openssh-9.9p2-error_processing.patch | 8 +- ...error-for-non-supported-private-keys.patch | 6 +- ...ore-bad-hostkeys-in-known_hosts-file.patch | 6 +- ...-authentication-indicators-in-GSSAPI.patch | 14 +- ...IST-curves-hybrid-KEX-implementation.patch | 29 +++- ...patch => 1000-openssh-6.7p1-coverity.patch | 36 ++--- openssh.spec | 113 +++++++------- 56 files changed, 534 insertions(+), 814 deletions(-) rename 0003-openssh-6.6p1-keycat.patch => 0002-openssh-6.6p1-keycat.patch (93%) delete mode 100644 0002-openssh-6.6p1-privsep-selinux.patch rename 0004-openssh-6.6p1-allow-ip-opts.patch => 0003-openssh-6.6p1-allow-ip-opts.patch (90%) rename 0005-openssh-5.9p1-ipv6man.patch => 0004-openssh-5.9p1-ipv6man.patch (86%) rename 0006-openssh-5.8p2-sigpipe.patch => 0005-openssh-5.8p2-sigpipe.patch (77%) rename 0007-openssh-7.2p2-x11.patch => 0006-openssh-7.2p2-x11.patch (92%) rename 0008-openssh-5.1p1-askpass-progress.patch => 0007-openssh-5.1p1-askpass-progress.patch (94%) rename 0009-openssh-4.3p2-askpass-grab-info.patch => 0008-openssh-4.3p2-askpass-grab-info.patch (87%) rename 0010-openssh-8.7p1-redhat.patch => 0009-openssh-8.7p1-redhat.patch (93%) rename 0011-openssh-7.8p1-UsePAM-warning.patch => 0010-openssh-7.8p1-UsePAM-warning.patch (85%) rename 0012-openssh-9.6p1-gssapi-keyex.patch => 0011-openssh-9.6p1-gssapi-keyex.patch (98%) rename 0013-openssh-6.6p1-force_krb.patch => 0012-openssh-6.6p1-force_krb.patch (97%) rename 0014-openssh-7.7p1-gssapi-new-unique.patch => 0013-openssh-7.7p1-gssapi-new-unique.patch (97%) rename 0015-openssh-7.2p2-k5login_directory.patch => 0014-openssh-7.2p2-k5login_directory.patch (91%) rename 0016-openssh-6.6p1-kuserok.patch => 0015-openssh-6.6p1-kuserok.patch (97%) rename 0017-openssh-6.4p1-fromto-remote.patch => 0016-openssh-6.4p1-fromto-remote.patch (81%) rename 0019-openssh-6.6.1p1-log-in-chroot.patch => 0017-openssh-6.6.1p1-log-in-chroot.patch (90%) rename 0020-openssh-6.6.1p1-scp-non-existing-directory.patch => 0018-openssh-6.6.1p1-scp-non-existing-directory.patch (74%) delete mode 100644 0018-openssh-6.6.1p1-selinux-contexts.patch rename 0021-openssh-6.6p1-GSSAPIEnablek5users.patch => 0019-openssh-6.6p1-GSSAPIEnablek5users.patch (94%) rename 0022-openssh-6.8p1-sshdT-output.patch => 0020-openssh-6.8p1-sshdT-output.patch (81%) rename 0023-openssh-6.7p1-sftp-force-permission.patch => 0021-openssh-6.7p1-sftp-force-permission.patch (94%) rename 0024-openssh-7.2p2-s390-closefrom.patch => 0022-openssh-7.2p2-s390-closefrom.patch (89%) rename 0025-openssh-7.3p1-x11-max-displays.patch => 0023-openssh-7.3p1-x11-max-displays.patch (94%) rename 0026-openssh-7.6p1-cleanup-selinux.patch => 0024-openssh-7.6p1-cleanup-selinux.patch (87%) rename 0027-openssh-7.5p1-sandbox.patch => 0025-openssh-7.5p1-sandbox.patch (89%) rename 0028-openssh-8.0p1-pkcs11-uri.patch => 0026-openssh-8.0p1-pkcs11-uri.patch (99%) rename 0029-openssh-7.8p1-scp-ipv6.patch => 0027-openssh-7.8p1-scp-ipv6.patch (82%) rename 0030-openssh-8.0p1-crypto-policies.patch => 0028-openssh-8.0p1-crypto-policies.patch (99%) rename 0031-openssh-8.0p1-openssl-kdf.patch => 0029-openssh-8.0p1-openssl-kdf.patch (95%) rename 0032-openssh-8.2p1-visibility.patch => 0030-openssh-8.2p1-visibility.patch (90%) rename 0033-openssh-8.2p1-x11-without-ipv6.patch => 0031-openssh-8.2p1-x11-without-ipv6.patch (82%) rename 0034-openssh-8.0p1-preserve-pam-errors.patch => 0032-openssh-8.0p1-preserve-pam-errors.patch (90%) rename 0035-openssh-8.7p1-scp-kill-switch.patch => 0033-openssh-8.7p1-scp-kill-switch.patch (86%) rename 0036-openssh-8.7p1-recursive-scp.patch => 0034-openssh-8.7p1-recursive-scp.patch (96%) rename 0037-openssh-8.7p1-minrsabits.patch => 0035-openssh-8.7p1-minrsabits.patch (86%) rename 0038-openssh-8.7p1-ibmca.patch => 0036-openssh-8.7p1-ibmca.patch (79%) rename 0039-openssh-7.6p1-audit.patch => 0037-openssh-7.6p1-audit.patch (97%) rename 0040-openssh-7.1p2-audit-race-condition.patch => 0038-openssh-7.1p2-audit-race-condition.patch (94%) rename 0041-openssh-9.0p1-audit-log.patch => 0039-openssh-9.0p1-audit-log.patch (97%) rename 0042-openssh-7.7p1-fips.patch => 0040-openssh-7.7p1-fips.patch (99%) rename 0043-openssh-8.7p1-ssh-manpage.patch => 0041-openssh-8.7p1-ssh-manpage.patch (87%) rename 0044-openssh-8.7p1-negotiate-supported-algs.patch => 0042-openssh-8.7p1-negotiate-supported-algs.patch (95%) rename 0045-openssh-9.0p1-evp-fips-kex.patch => 0043-openssh-9.0p1-evp-fips-kex.patch (98%) rename 0046-openssh-8.7p1-nohostsha1proof.patch => 0044-openssh-8.7p1-nohostsha1proof.patch (95%) rename 0047-openssh-9.6p1-pam-rhost.patch => 0045-openssh-9.6p1-pam-rhost.patch (80%) rename 0048-openssh-9.9p1-separate-keysign.patch => 0046-openssh-9.9p1-separate-keysign.patch (76%) rename 0049-openssh-9.9p1-openssl-mlkem.patch => 0047-openssh-9.9p1-openssl-mlkem.patch (98%) rename 0050-openssh-9.9p2-error_processing.patch => 0048-openssh-9.9p2-error_processing.patch (77%) rename 0051-Provide-better-error-for-non-supported-private-keys.patch => 0049-Provide-better-error-for-non-supported-private-keys.patch (81%) rename 0052-Ignore-bad-hostkeys-in-known_hosts-file.patch => 0050-Ignore-bad-hostkeys-in-known_hosts-file.patch (94%) rename 0053-support-authentication-indicators-in-GSSAPI.patch => 0051-support-authentication-indicators-in-GSSAPI.patch (98%) rename 0054-openssh-10.0-mlkem-nist.patch => 0052-NIST-curves-hybrid-KEX-implementation.patch (97%) rename 1000-openssh-coverity.patch => 1000-openssh-6.7p1-coverity.patch (91%) diff --git a/0001-openssh-7.8p1-role-mls.patch b/0001-openssh-7.8p1-role-mls.patch index c08e414..be26347 100644 --- a/0001-openssh-7.8p1-role-mls.patch +++ b/0001-openssh-7.8p1-role-mls.patch @@ -1,7 +1,7 @@ -From 95f4e30195382c3df7104c2ad3e5e9953f8ad554 Mon Sep 17 00:00:00 2001 +From 03708ca29702203727ea0e4ca64425b7f1b6f755 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 01/50] openssh-7.8p1-role-mls +Subject: [PATCH 01/53] openssh-7.8p1-role-mls --- auth-pam.c | 2 +- @@ -26,7 +26,7 @@ Subject: [PATCH 01/50] openssh-7.8p1-role-mls create mode 100644 openbsd-compat/port-linux-sshd.c diff --git a/auth-pam.c b/auth-pam.c -index 13c0a792..b4100ea1 100644 +index 13c0a792e..b4100ea1c 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -1238,7 +1238,7 @@ is_pam_session_open(void) @@ -39,7 +39,7 @@ index 13c0a792..b4100ea1 100644 int ret = 1; char *compound; diff --git a/auth-pam.h b/auth-pam.h -index 8d801c68..9dd7ae07 100644 +index 8d801c689..9dd7ae078 100644 --- a/auth-pam.h +++ b/auth-pam.h @@ -33,7 +33,7 @@ u_int do_pam_account(void); @@ -52,7 +52,7 @@ index 8d801c68..9dd7ae07 100644 char ** fetch_pam_child_environment(void); void free_pam_environment(char **); diff --git a/auth.h b/auth.h -index 98bb23d4..83d07ae8 100644 +index 98bb23d4c..83d07ae8b 100644 --- a/auth.h +++ b/auth.h @@ -65,6 +65,9 @@ struct Authctxt { @@ -66,7 +66,7 @@ index 98bb23d4..83d07ae8 100644 /* Method lists for multiple authentication */ char **auth_methods; /* modified from server config */ diff --git a/auth2-gss.c b/auth2-gss.c -index 75eb4e3a..f7898ab3 100644 +index 75eb4e3a3..f7898ab3e 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -284,6 +284,7 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) @@ -102,7 +102,7 @@ index 75eb4e3a..f7898ab3 100644 authctxt->postponed = 0; diff --git a/auth2-hostbased.c b/auth2-hostbased.c -index eb21479a..a3be6e49 100644 +index eb21479a0..a3be6e497 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -129,7 +129,16 @@ userauth_hostbased(struct ssh *ssh, const char *method) @@ -123,7 +123,7 @@ index eb21479a..a3be6e49 100644 (r = sshbuf_put_cstring(b, method)) != 0 || (r = sshbuf_put_string(b, pkalg, alen)) != 0 || diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index aa24fda0..267a27d2 100644 +index aa24fda05..267a27d24 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -206,9 +206,16 @@ userauth_pubkey(struct ssh *ssh, const char *method) @@ -146,7 +146,7 @@ index aa24fda0..267a27d2 100644 (r = sshbuf_put_cstring(b, userstyle)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || diff --git a/auth2.c b/auth2.c -index 82f6e621..5ba45c12 100644 +index 82f6e6211..5ba45c12e 100644 --- a/auth2.c +++ b/auth2.c @@ -271,6 +271,9 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) @@ -186,7 +186,7 @@ index 82f6e621..5ba45c12 100644 if ((r = kex_server_update_ext_info(ssh)) != 0) fatal_fr(r, "kex_server_update_ext_info failed"); diff --git a/misc.c b/misc.c -index dd0bd032..c932f9bb 100644 +index dd0bd032a..c932f9bbb 100644 --- a/misc.c +++ b/misc.c @@ -806,6 +806,7 @@ char * @@ -212,7 +212,7 @@ index dd0bd032..c932f9bb 100644 return NULL; } diff --git a/monitor.c b/monitor.c -index 2179553d..02b3eaaa 100644 +index 2179553d3..02b3eaaa3 100644 --- a/monitor.c +++ b/monitor.c @@ -120,6 +120,9 @@ int mm_answer_sign(struct ssh *, int, struct sshbuf *); @@ -309,7 +309,7 @@ index 2179553d..02b3eaaa 100644 authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); diff --git a/monitor.h b/monitor.h -index 3f8a9bea..9dcd9c29 100644 +index 3f8a9bea3..9dcd9c293 100644 --- a/monitor.h +++ b/monitor.h @@ -56,6 +56,10 @@ enum monitor_reqtype { @@ -324,7 +324,7 @@ index 3f8a9bea..9dcd9c29 100644 MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105, diff --git a/monitor_wrap.c b/monitor_wrap.c -index bd900b2f..ef3ab1b1 100644 +index bd900b2f0..ef3ab1b18 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -442,6 +442,27 @@ mm_inform_authserv(char *service, char *style) @@ -356,7 +356,7 @@ index bd900b2f..ef3ab1b1 100644 int mm_auth_password(struct ssh *ssh, char *password) diff --git a/monitor_wrap.h b/monitor_wrap.h -index 7134afee..38a280c8 100644 +index 7134afeec..38a280c87 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -46,6 +46,9 @@ int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, @@ -370,7 +370,7 @@ index 7134afee..38a280c8 100644 char *mm_auth2_read_banner(void); int mm_auth_password(struct ssh *, char *); diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in -index 1d549954..78e6fa5b 100644 +index 1d549954f..78e6fa5b1 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in @@ -100,7 +100,8 @@ PORTS= port-aix.o \ @@ -385,7 +385,7 @@ index 1d549954..78e6fa5b 100644 $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c new file mode 100644 -index 00000000..b9fbe38b +index 000000000..b9fbe38b7 --- /dev/null +++ b/openbsd-compat/port-linux-sshd.c @@ -0,0 +1,420 @@ @@ -810,7 +810,7 @@ index 00000000..b9fbe38b +#endif + diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c -index c1d54f38..7426f6f7 100644 +index c1d54f38d..7426f6f79 100644 --- a/openbsd-compat/port-linux.c +++ b/openbsd-compat/port-linux.c @@ -109,37 +109,6 @@ ssh_selinux_getctxbyname(char *pwname) @@ -865,7 +865,7 @@ index c1d54f38..7426f6f7 100644 /* XXX: should these calls fatal() upon failure in enforcing mode? */ diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h -index 959430de..055c825e 100644 +index 959430de1..055c825e4 100644 --- a/openbsd-compat/port-linux.h +++ b/openbsd-compat/port-linux.h @@ -20,9 +20,10 @@ @@ -881,7 +881,7 @@ index 959430de..055c825e 100644 #ifdef LINUX_OOM_ADJUST diff --git a/platform.c b/platform.c -index 4c4fe57e..1bfb4bea 100644 +index 4c4fe57ea..1bfb4beae 100644 --- a/platform.c +++ b/platform.c @@ -140,7 +140,7 @@ platform_setusercontext_post_groups(struct passwd *pw) @@ -894,7 +894,7 @@ index 4c4fe57e..1bfb4bea 100644 } diff --git a/sshd-session.c b/sshd-session.c -index c64eb29f..74d2cbc7 100644 +index c64eb29fc..74d2cbc78 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -1328,6 +1328,9 @@ main(int ac, char **av) @@ -908,5 +908,5 @@ index c64eb29f..74d2cbc7 100644 if (options.use_pam) { do_pam_setcred(); -- -2.49.0 +2.52.0 diff --git a/0003-openssh-6.6p1-keycat.patch b/0002-openssh-6.6p1-keycat.patch similarity index 93% rename from 0003-openssh-6.6p1-keycat.patch rename to 0002-openssh-6.6p1-keycat.patch index b46b378..8664ab5 100644 --- a/0003-openssh-6.6p1-keycat.patch +++ b/0002-openssh-6.6p1-keycat.patch @@ -1,24 +1,24 @@ -From 5e35e18a419a5a66b6e1cb2b98beaaf4d9db0dc6 Mon Sep 17 00:00:00 2001 +From 29ac74175c56664e0d2c7bb9362cfa0b25bb0fb4 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 03/50] openssh-6.6p1-keycat +Subject: [PATCH 02/53] openssh-6.6p1-keycat --- HOWTO.ssh-keycat | 12 ++ Makefile.in | 8 +- configure.ac | 6 + misc.c | 7 + - openbsd-compat/port-linux-sshd.c | 44 +++++- - openbsd-compat/port-linux.h | 2 + + openbsd-compat/port-linux-sshd.c | 42 +++++- + openbsd-compat/port-linux.h | 1 + platform.c | 2 +- ssh-keycat.c | 241 +++++++++++++++++++++++++++++++ - 8 files changed, 314 insertions(+), 8 deletions(-) + 8 files changed, 312 insertions(+), 7 deletions(-) create mode 100644 HOWTO.ssh-keycat create mode 100644 ssh-keycat.c diff --git a/HOWTO.ssh-keycat b/HOWTO.ssh-keycat new file mode 100644 -index 00000000..630ec628 +index 000000000..630ec628c --- /dev/null +++ b/HOWTO.ssh-keycat @@ -0,0 +1,12 @@ @@ -35,7 +35,7 @@ index 00000000..630ec628 + + diff --git a/Makefile.in b/Makefile.in -index 4617cebc..438efc51 100644 +index 4617cebcd..438efc51e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -23,6 +23,7 @@ SSH_PROGRAM=@bindir@/ssh @@ -82,7 +82,7 @@ index 4617cebc..438efc51 100644 $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 diff --git a/configure.ac b/configure.ac -index ee77a048..d546788c 100644 +index ee77a0484..d546788cc 100644 --- a/configure.ac +++ b/configure.ac @@ -3566,6 +3566,7 @@ AC_ARG_WITH([pam], @@ -120,7 +120,7 @@ index ee77a048..d546788c 100644 echo "" diff --git a/misc.c b/misc.c -index c932f9bb..1e31acc9 100644 +index c932f9bbb..1e31acc95 100644 --- a/misc.c +++ b/misc.c @@ -2897,6 +2897,13 @@ subprocess(const char *tag, const char *command, @@ -138,7 +138,7 @@ index c932f9bb..1e31acc9 100644 execve(av[0], av, env); else diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c -index dfafc622..8c5fc1fe 100644 +index b9fbe38b7..4d56745f7 100644 --- a/openbsd-compat/port-linux-sshd.c +++ b/openbsd-compat/port-linux-sshd.c @@ -52,6 +52,20 @@ extern ServerOptions options; @@ -225,32 +225,20 @@ index dfafc622..8c5fc1fe 100644 return; if (options.use_pam) { -@@ -420,7 +452,7 @@ sshd_selinux_copy_context(void) - { - security_context_t *ctx; - -- if (!ssh_selinux_enabled()) -+ if (!sshd_selinux_enabled()) - return; - - if (getexeccon((security_context_t *)&ctx) != 0) { diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h -index 498d242a..1b745a76 100644 +index 055c825e4..c004071d1 100644 --- a/openbsd-compat/port-linux.h +++ b/openbsd-compat/port-linux.h -@@ -23,8 +23,10 @@ void ssh_selinux_setup_pty(char *, const char *); - void ssh_selinux_change_context(const char *); +@@ -24,6 +24,7 @@ void ssh_selinux_change_context(const char *); void ssh_selinux_setfscreatecon(const char *); -+int sshd_selinux_enabled(void); - void sshd_selinux_copy_context(void); void sshd_selinux_setup_exec_context(char *); +int sshd_selinux_setup_env_variables(void); #endif #ifdef LINUX_OOM_ADJUST diff --git a/platform.c b/platform.c -index 1bfb4bea..0d12f311 100644 +index 1bfb4beae..0d12f3111 100644 --- a/platform.c +++ b/platform.c @@ -55,7 +55,7 @@ platform_setusercontext(struct passwd *pw) @@ -264,7 +252,7 @@ index 1bfb4bea..0d12f311 100644 #ifdef USE_SOLARIS_PROJECTS diff --git a/ssh-keycat.c b/ssh-keycat.c new file mode 100644 -index 00000000..5678be07 +index 000000000..5678be079 --- /dev/null +++ b/ssh-keycat.c @@ -0,0 +1,241 @@ @@ -510,5 +498,5 @@ index 00000000..5678be07 + return ev; +} -- -2.49.0 +2.52.0 diff --git a/0002-openssh-6.6p1-privsep-selinux.patch b/0002-openssh-6.6p1-privsep-selinux.patch deleted file mode 100644 index 32d3c64..0000000 --- a/0002-openssh-6.6p1-privsep-selinux.patch +++ /dev/null @@ -1,144 +0,0 @@ -From 99d8e250514023d3b88a1c9eb724c4898aba9827 Mon Sep 17 00:00:00 2001 -From: Dmitry Belyavskiy -Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 02/50] openssh-6.6p1-privsep-selinux - ---- - openbsd-compat/port-linux-sshd.c | 22 ++++++++++++++++++++++ - openbsd-compat/port-linux.h | 1 + - session.c | 16 +++++++++------- - sshd-auth.c | 4 ++++ - sshd-session.c | 2 +- - 5 files changed, 37 insertions(+), 8 deletions(-) - -diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c -index b9fbe38b..dfafc622 100644 ---- a/openbsd-compat/port-linux-sshd.c -+++ b/openbsd-compat/port-linux-sshd.c -@@ -415,6 +415,28 @@ sshd_selinux_setup_exec_context(char *pwname) - debug3_f("done"); - } - -+void -+sshd_selinux_copy_context(void) -+{ -+ security_context_t *ctx; -+ -+ if (!ssh_selinux_enabled()) -+ return; -+ -+ if (getexeccon((security_context_t *)&ctx) != 0) { -+ logit_f("getexeccon failed with %s", strerror(errno)); -+ return; -+ } -+ if (ctx != NULL) { -+ /* unset exec context before we will lose this capabililty */ -+ if (setexeccon(NULL) != 0) -+ fatal_f("setexeccon failed with %s", strerror(errno)); -+ if (setcon(ctx) != 0) -+ fatal_f("setcon failed with %s", strerror(errno)); -+ freecon(ctx); -+ } -+} -+ - #endif - #endif - -diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h -index 055c825e..498d242a 100644 ---- a/openbsd-compat/port-linux.h -+++ b/openbsd-compat/port-linux.h -@@ -23,6 +23,7 @@ void ssh_selinux_setup_pty(char *, const char *); - void ssh_selinux_change_context(const char *); - void ssh_selinux_setfscreatecon(const char *); - -+void sshd_selinux_copy_context(void); - void sshd_selinux_setup_exec_context(char *); - #endif - -diff --git a/session.c b/session.c -index 6444c77f..e4657cef 100644 ---- a/session.c -+++ b/session.c -@@ -1350,7 +1350,7 @@ do_setusercontext(struct passwd *pw) - - platform_setusercontext(pw); - -- if (platform_privileged_uidswap()) { -+ if (platform_privileged_uidswap() && !is_child) { - #ifdef HAVE_LOGIN_CAP - if (setusercontext(lc, pw, pw->pw_uid, - (LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) { -@@ -1382,6 +1382,9 @@ do_setusercontext(struct passwd *pw) - (unsigned long long)pw->pw_uid); - chroot_path = percent_expand(tmp, "h", pw->pw_dir, - "u", pw->pw_name, "U", uidstr, (char *)NULL); -+#ifdef WITH_SELINUX -+ sshd_selinux_copy_context(); -+#endif - safely_chroot(chroot_path, pw->pw_uid); - free(tmp); - free(chroot_path); -@@ -1417,6 +1420,11 @@ do_setusercontext(struct passwd *pw) - /* Permanently switch to the desired uid. */ - permanently_set_uid(pw); - #endif -+ -+#ifdef WITH_SELINUX -+ if (in_chroot == 0) -+ sshd_selinux_copy_context(); -+#endif - } else if (options.chroot_directory != NULL && - strcasecmp(options.chroot_directory, "none") != 0) { - fatal("server lacks privileges to chroot to ChrootDirectory"); -@@ -1434,9 +1442,6 @@ do_pwchange(Session *s) - if (s->ttyfd != -1) { - fprintf(stderr, - "You must change your password now and log in again!\n"); --#ifdef WITH_SELINUX -- setexeccon(NULL); --#endif - #ifdef PASSWD_NEEDS_USERNAME - execl(_PATH_PASSWD_PROG, "passwd", s->pw->pw_name, - (char *)NULL); -@@ -1649,9 +1654,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) - argv[i] = NULL; - optind = optreset = 1; - __progname = argv[0]; --#ifdef WITH_SELINUX -- ssh_selinux_change_context("sftpd_t"); --#endif - exit(sftp_server_main(i, argv, s->pw)); - } - -diff --git a/sshd-auth.c b/sshd-auth.c -index 30eecd8a..f957dc22 100644 ---- a/sshd-auth.c -+++ b/sshd-auth.c -@@ -187,6 +187,10 @@ privsep_child_demote(void) - if ((box = ssh_sandbox_init(pmonitor)) == NULL) - fatal_f("ssh_sandbox_init failed"); - #endif -+#ifdef WITH_SELINUX -+ ssh_selinux_change_context("sshd_net_t"); -+#endif -+ - /* Demote the child */ - if (privsep_chroot) { - /* Change our root directory */ -diff --git a/sshd-session.c b/sshd-session.c -index 74d2cbc7..4a148db4 100644 ---- a/sshd-session.c -+++ b/sshd-session.c -@@ -432,7 +432,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) - * fd passing, as AFAIK PTY allocation on this platform doesn't require - * special privileges to begin with. - */ --#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) -+#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) && !defined(WITH_SELINUX) - skip_privdrop = 1; - #endif - --- -2.49.0 - diff --git a/0004-openssh-6.6p1-allow-ip-opts.patch b/0003-openssh-6.6p1-allow-ip-opts.patch similarity index 90% rename from 0004-openssh-6.6p1-allow-ip-opts.patch rename to 0003-openssh-6.6p1-allow-ip-opts.patch index ef15fbf..ec85893 100644 --- a/0004-openssh-6.6p1-allow-ip-opts.patch +++ b/0003-openssh-6.6p1-allow-ip-opts.patch @@ -1,14 +1,14 @@ -From 28333f1dfe68b0ffc80c2a4799759587b4c32d3e Mon Sep 17 00:00:00 2001 +From 22410e0a4b292f9a27b4d17eb923ed9809e8c0ae Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 04/50] openssh-6.6p1-allow-ip-opts +Subject: [PATCH 03/53] openssh-6.6p1-allow-ip-opts --- sshd-session.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/sshd-session.c b/sshd-session.c -index 4a148db4..a365f26f 100644 +index 74d2cbc78..316e2970e 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -778,12 +778,32 @@ check_ip_options(struct ssh *ssh) @@ -51,5 +51,5 @@ index 4a148db4..a365f26f 100644 #endif /* IP_OPTIONS */ } -- -2.49.0 +2.52.0 diff --git a/0005-openssh-5.9p1-ipv6man.patch b/0004-openssh-5.9p1-ipv6man.patch similarity index 86% rename from 0005-openssh-5.9p1-ipv6man.patch rename to 0004-openssh-5.9p1-ipv6man.patch index 909b988..e43c447 100644 --- a/0005-openssh-5.9p1-ipv6man.patch +++ b/0004-openssh-5.9p1-ipv6man.patch @@ -1,7 +1,7 @@ -From 388be633842a9f3e4b0a76fe40cf7035912a913a Mon Sep 17 00:00:00 2001 +From 9f7414f535da29a79d3312b3c3c1ed5fcedf912b Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 05/50] openssh-5.9p1-ipv6man +Subject: [PATCH 04/53] openssh-5.9p1-ipv6man --- ssh.1 | 2 ++ @@ -9,7 +9,7 @@ Subject: [PATCH 05/50] openssh-5.9p1-ipv6man 2 files changed, 4 insertions(+) diff --git a/ssh.1 b/ssh.1 -index 697f4e42..db92ac9a 100644 +index 697f4e42a..db92ac9af 100644 --- a/ssh.1 +++ b/ssh.1 @@ -1663,6 +1663,8 @@ manual page for more information. @@ -22,7 +22,7 @@ index 697f4e42..db92ac9a 100644 .Xr scp 1 , .Xr sftp 1 , diff --git a/sshd.8 b/sshd.8 -index 08ebf53a..2aa73271 100644 +index 08ebf53a1..2aa732717 100644 --- a/sshd.8 +++ b/sshd.8 @@ -1018,6 +1018,8 @@ concurrently for different ports, this contains the process ID of the one @@ -35,5 +35,5 @@ index 08ebf53a..2aa73271 100644 .Xr scp 1 , .Xr sftp 1 , -- -2.49.0 +2.52.0 diff --git a/0006-openssh-5.8p2-sigpipe.patch b/0005-openssh-5.8p2-sigpipe.patch similarity index 77% rename from 0006-openssh-5.8p2-sigpipe.patch rename to 0005-openssh-5.8p2-sigpipe.patch index 5bf31bc..e8f5fc5 100644 --- a/0006-openssh-5.8p2-sigpipe.patch +++ b/0005-openssh-5.8p2-sigpipe.patch @@ -1,14 +1,14 @@ -From 80359feb76fd8061b5ce18f73451d7b9db0c2477 Mon Sep 17 00:00:00 2001 +From 030764b5f9c86e3f585c1acc8bec7b4b7af4614e Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 06/50] openssh-5.8p2-sigpipe +Subject: [PATCH 05/53] openssh-5.8p2-sigpipe --- ssh-keyscan.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ssh-keyscan.c b/ssh-keyscan.c -index 3436c0b5..9f76ad22 100644 +index 3436c0b5c..9f76ad225 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c @@ -798,6 +798,9 @@ main(int argc, char **argv) @@ -22,5 +22,5 @@ index 3436c0b5..9f76ad22 100644 for (j = 0; j < maxfd; j++) read_wait[j].fd = -1; -- -2.49.0 +2.52.0 diff --git a/0007-openssh-7.2p2-x11.patch b/0006-openssh-7.2p2-x11.patch similarity index 92% rename from 0007-openssh-7.2p2-x11.patch rename to 0006-openssh-7.2p2-x11.patch index 2f72f9a..1dfeb14 100644 --- a/0007-openssh-7.2p2-x11.patch +++ b/0006-openssh-7.2p2-x11.patch @@ -1,14 +1,14 @@ -From cf6d48305cf6601448ea7a0d96ae825cbbbf0a2c Mon Sep 17 00:00:00 2001 +From 7fd98c9696df1e7f5feae99762bdde002b98eebe Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 07/50] openssh-7.2p2-x11 +Subject: [PATCH 06/53] openssh-7.2p2-x11 --- channels.c | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/channels.c b/channels.c -index bfe2e3b2..d46531ce 100644 +index bfe2e3b2d..d46531ce0 100644 --- a/channels.c +++ b/channels.c @@ -5098,11 +5098,13 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, @@ -64,5 +64,5 @@ index bfe2e3b2..d46531ce 100644 #ifdef __APPLE__ -- -2.49.0 +2.52.0 diff --git a/0008-openssh-5.1p1-askpass-progress.patch b/0007-openssh-5.1p1-askpass-progress.patch similarity index 94% rename from 0008-openssh-5.1p1-askpass-progress.patch rename to 0007-openssh-5.1p1-askpass-progress.patch index f7ca382..63b77d8 100644 --- a/0008-openssh-5.1p1-askpass-progress.patch +++ b/0007-openssh-5.1p1-askpass-progress.patch @@ -1,14 +1,14 @@ -From 6b2a33044583e892badb9ac86cd2c6252b1a532f Mon Sep 17 00:00:00 2001 +From 8e3dd528906915d8b82a65b9a56e0c9201d32ece Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 08/50] openssh-5.1p1-askpass-progress +Subject: [PATCH 07/53] openssh-5.1p1-askpass-progress --- contrib/gnome-ssh-askpass2.c | 39 +++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c -index a62f9815..cb7152dc 100644 +index a62f98152..cb7152dc8 100644 --- a/contrib/gnome-ssh-askpass2.c +++ b/contrib/gnome-ssh-askpass2.c @@ -58,6 +58,7 @@ @@ -92,5 +92,5 @@ index a62f9815..cb7152dc 100644 /* Grab focus */ -- -2.49.0 +2.52.0 diff --git a/0009-openssh-4.3p2-askpass-grab-info.patch b/0008-openssh-4.3p2-askpass-grab-info.patch similarity index 87% rename from 0009-openssh-4.3p2-askpass-grab-info.patch rename to 0008-openssh-4.3p2-askpass-grab-info.patch index 8a7cf9e..b781c76 100644 --- a/0009-openssh-4.3p2-askpass-grab-info.patch +++ b/0008-openssh-4.3p2-askpass-grab-info.patch @@ -1,14 +1,14 @@ -From 710ce53fdf1d32a0629fce2e42fb49d407e2b06c Mon Sep 17 00:00:00 2001 +From 02f18438ad18ae5fc1015b9122f98c16e42f8389 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 09/50] openssh-4.3p2-askpass-grab-info +Subject: [PATCH 08/53] openssh-4.3p2-askpass-grab-info --- contrib/gnome-ssh-askpass2.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/contrib/gnome-ssh-askpass2.c b/contrib/gnome-ssh-askpass2.c -index cb7152dc..bbe93d83 100644 +index cb7152dc8..bbe93d838 100644 --- a/contrib/gnome-ssh-askpass2.c +++ b/contrib/gnome-ssh-askpass2.c @@ -70,8 +70,12 @@ report_failed_grab (GtkWidget *parent_window, const char *what) @@ -27,5 +27,5 @@ index cb7152dc..bbe93d83 100644 gtk_dialog_run(GTK_DIALOG(err)); -- -2.49.0 +2.52.0 diff --git a/0010-openssh-8.7p1-redhat.patch b/0009-openssh-8.7p1-redhat.patch similarity index 93% rename from 0010-openssh-8.7p1-redhat.patch rename to 0009-openssh-8.7p1-redhat.patch index cb3d140..e0844c6 100644 --- a/0010-openssh-8.7p1-redhat.patch +++ b/0009-openssh-8.7p1-redhat.patch @@ -1,7 +1,7 @@ -From 5f21983f6472b26693babea4d6ca6b95a7dc7b05 Mon Sep 17 00:00:00 2001 +From 73e8653026dc5b08ff9a194be7f1a3f5374ff4da Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 10/50] openssh-8.7p1-redhat +Subject: [PATCH 09/53] openssh-8.7p1-redhat --- ssh_config | 7 +++++++ @@ -17,7 +17,7 @@ Subject: [PATCH 10/50] openssh-8.7p1-redhat create mode 100644 sshd_config_redhat_cp diff --git a/ssh_config b/ssh_config -index cc566356..18169187 100644 +index cc5663562..181691873 100644 --- a/ssh_config +++ b/ssh_config @@ -44,3 +44,10 @@ @@ -33,7 +33,7 @@ index cc566356..18169187 100644 +Include /etc/ssh/ssh_config.d/*.conf diff --git a/ssh_config_redhat b/ssh_config_redhat new file mode 100644 -index 00000000..8b1b5902 +index 000000000..8b1b59021 --- /dev/null +++ b/ssh_config_redhat @@ -0,0 +1,18 @@ @@ -56,7 +56,7 @@ index 00000000..8b1b5902 +# Uncomment this if you want to use .local domain +# Host *.local diff --git a/sshd_config b/sshd_config -index 0f4a3a72..608203e4 100644 +index 0f4a3a724..608203e4b 100644 --- a/sshd_config +++ b/sshd_config @@ -10,6 +10,14 @@ @@ -75,7 +75,7 @@ index 0f4a3a72..608203e4 100644 #AddressFamily any #ListenAddress 0.0.0.0 diff --git a/sshd_config.0 b/sshd_config.0 -index 2f77b4f4..49349bb3 100644 +index 2f77b4f4c..49349bb30 100644 --- a/sshd_config.0 +++ b/sshd_config.0 @@ -1219,9 +1219,9 @@ DESCRIPTION @@ -92,7 +92,7 @@ index 2f77b4f4..49349bb3 100644 TCPKeepAlive Specifies whether the system should send TCP keepalive messages diff --git a/sshd_config.5 b/sshd_config.5 -index c0771737..035a50c8 100644 +index c07717375..035a50c8c 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -1942,7 +1942,7 @@ By default no subsystems are defined. @@ -106,7 +106,7 @@ index c0771737..035a50c8 100644 .It Cm TCPKeepAlive diff --git a/sshd_config_redhat b/sshd_config_redhat new file mode 100644 -index 00000000..993a28d5 +index 000000000..993a28d52 --- /dev/null +++ b/sshd_config_redhat @@ -0,0 +1,18 @@ @@ -130,7 +130,7 @@ index 00000000..993a28d5 + diff --git a/sshd_config_redhat_cp b/sshd_config_redhat_cp new file mode 100644 -index 00000000..1d592d13 +index 000000000..1d592d13f --- /dev/null +++ b/sshd_config_redhat_cp @@ -0,0 +1,7 @@ @@ -142,5 +142,5 @@ index 00000000..1d592d13 +Include /etc/crypto-policies/back-ends/opensshserver.config + -- -2.49.0 +2.52.0 diff --git a/0011-openssh-7.8p1-UsePAM-warning.patch b/0010-openssh-7.8p1-UsePAM-warning.patch similarity index 85% rename from 0011-openssh-7.8p1-UsePAM-warning.patch rename to 0010-openssh-7.8p1-UsePAM-warning.patch index 76ee115..183f1ba 100644 --- a/0011-openssh-7.8p1-UsePAM-warning.patch +++ b/0010-openssh-7.8p1-UsePAM-warning.patch @@ -1,7 +1,7 @@ -From 56b8d082bc9e25a77b5227d576f27088446c6fb9 Mon Sep 17 00:00:00 2001 +From 9c047ae43abfe2bddb8abbe1bd7d97a301d36afa Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 11/50] openssh-7.8p1-UsePAM-warning +Subject: [PATCH 10/53] openssh-7.8p1-UsePAM-warning --- sshd-session.c | 4 ++++ @@ -9,7 +9,7 @@ Subject: [PATCH 11/50] openssh-7.8p1-UsePAM-warning 2 files changed, 6 insertions(+) diff --git a/sshd-session.c b/sshd-session.c -index a365f26f..a70b36c9 100644 +index 316e2970e..c759f95a4 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -1127,6 +1127,10 @@ main(int ac, char **av) @@ -24,7 +24,7 @@ index a365f26f..a70b36c9 100644 if (options.moduli_file != NULL) dh_set_moduli_file(options.moduli_file); diff --git a/sshd_config b/sshd_config -index 608203e4..48af6321 100644 +index 608203e4b..48af6321b 100644 --- a/sshd_config +++ b/sshd_config @@ -89,6 +89,8 @@ AuthorizedKeysFile .ssh/authorized_keys @@ -37,5 +37,5 @@ index 608203e4..48af6321 100644 #AllowAgentForwarding yes -- -2.49.0 +2.52.0 diff --git a/0012-openssh-9.6p1-gssapi-keyex.patch b/0011-openssh-9.6p1-gssapi-keyex.patch similarity index 98% rename from 0012-openssh-9.6p1-gssapi-keyex.patch rename to 0011-openssh-9.6p1-gssapi-keyex.patch index f5f54f7..c8ac581 100644 --- a/0012-openssh-9.6p1-gssapi-keyex.patch +++ b/0011-openssh-9.6p1-gssapi-keyex.patch @@ -1,7 +1,7 @@ -From 754b023b92aa68742258c55243a6ae8f30ed5a17 Mon Sep 17 00:00:00 2001 +From f4b968d4fd79a47ad3796fc489dd9e5f7fc9d4f2 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 12/50] openssh-9.6p1-gssapi-keyex +Subject: [PATCH 11/53] openssh-9.6p1-gssapi-keyex --- Makefile.in | 7 +- @@ -50,7 +50,7 @@ Subject: [PATCH 12/50] openssh-9.6p1-gssapi-keyex create mode 100644 kexgsss.c diff --git a/Makefile.in b/Makefile.in -index 438efc51..78f65948 100644 +index 438efc51e..78f659487 100644 --- a/Makefile.in +++ b/Makefile.in @@ -117,6 +117,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ @@ -89,7 +89,7 @@ index 438efc51..78f65948 100644 regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ diff --git a/auth.c b/auth.c -index 9a6e5a31..e4578169 100644 +index 9a6e5a319..e4578169b 100644 --- a/auth.c +++ b/auth.c @@ -356,7 +356,8 @@ auth_root_allowed(struct ssh *ssh, const char *method) @@ -103,7 +103,7 @@ index 9a6e5a31..e4578169 100644 break; case PERMIT_FORCED_ONLY: diff --git a/auth2-gss.c b/auth2-gss.c -index f7898ab3..5b1b9cde 100644 +index f7898ab3e..5b1b9cde3 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -51,6 +51,7 @@ @@ -194,7 +194,7 @@ index f7898ab3..5b1b9cde 100644 &methodcfg_gssapi, userauth_gssapi, diff --git a/auth2-methods.c b/auth2-methods.c -index 99637a89..a05908cf 100644 +index 99637a89b..a05908cf3 100644 --- a/auth2-methods.c +++ b/auth2-methods.c @@ -50,6 +50,11 @@ struct authmethod_cfg methodcfg_pubkey = { @@ -218,7 +218,7 @@ index 99637a89..a05908cf 100644 #endif &methodcfg_passwd, diff --git a/auth2.c b/auth2.c -index 5ba45c12..8ec41de2 100644 +index 5ba45c12e..8ec41de23 100644 --- a/auth2.c +++ b/auth2.c @@ -71,6 +71,7 @@ extern Authmethod method_passwd; @@ -238,7 +238,7 @@ index 5ba45c12..8ec41de2 100644 #endif &method_passwd, diff --git a/canohost.c b/canohost.c -index 28f086e5..875805c9 100644 +index 28f086e5a..875805c99 100644 --- a/canohost.c +++ b/canohost.c @@ -35,6 +35,99 @@ @@ -342,7 +342,7 @@ index 28f086e5..875805c9 100644 ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) { diff --git a/canohost.h b/canohost.h -index 26d62855..0cadc9f1 100644 +index 26d62855a..0cadc9f18 100644 --- a/canohost.h +++ b/canohost.h @@ -15,6 +15,9 @@ @@ -356,7 +356,7 @@ index 26d62855..0cadc9f1 100644 int get_peer_port(int); char *get_local_ipaddr(int); diff --git a/clientloop.c b/clientloop.c -index 916fc077..4655f91f 100644 +index 916fc077b..4655f91fe 100644 --- a/clientloop.c +++ b/clientloop.c @@ -115,6 +115,10 @@ @@ -386,7 +386,7 @@ index 916fc077..4655f91f 100644 if (conn_in_ready) client_process_net_input(ssh); diff --git a/configure.ac b/configure.ac -index d546788c..13c70a98 100644 +index d546788cc..13c70a983 100644 --- a/configure.ac +++ b/configure.ac @@ -786,6 +786,30 @@ int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) @@ -421,7 +421,7 @@ index d546788c..13c70a98 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 aa34b71c..3034370c 100644 +index aa34b71c5..3034370c7 100644 --- a/gss-genr.c +++ b/gss-genr.c @@ -42,9 +42,33 @@ @@ -810,7 +810,7 @@ index aa34b71c..3034370c 100644 + #endif /* GSSAPI */ diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index a151bc1e..8d2b677f 100644 +index a151bc1e4..8d2b677f7 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c @@ -1,7 +1,7 @@ @@ -950,7 +950,7 @@ index a151bc1e..8d2b677f 100644 #endif /* KRB5 */ diff --git a/gss-serv.c b/gss-serv.c -index 025a118f..a5cca797 100644 +index 025a118f8..a5cca7973 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -1,7 +1,7 @@ @@ -1245,7 +1245,7 @@ index 025a118f..a5cca797 100644 /* Privileged */ diff --git a/kex-names.c b/kex-names.c -index ec840c1f..6c0b7c2b 100644 +index ec840c1f9..6c0b7c2b3 100644 --- a/kex-names.c +++ b/kex-names.c @@ -45,6 +45,10 @@ @@ -1349,7 +1349,7 @@ index ec840c1f..6c0b7c2b 100644 + return 1; +} diff --git a/kex.c b/kex.c -index 6b957e5e..19a56e8e 100644 +index 6b957e5e1..19a56e8e9 100644 --- a/kex.c +++ b/kex.c @@ -297,17 +297,37 @@ static int @@ -1407,7 +1407,7 @@ index 6b957e5e..19a56e8e 100644 sshkey_free(kex->initial_hostkey); free(kex->failed_choice); diff --git a/kex.h b/kex.h -index d08988b3..0e080ea3 100644 +index d08988b3e..0e080ea38 100644 --- a/kex.h +++ b/kex.h @@ -29,6 +29,10 @@ @@ -1489,7 +1489,7 @@ index d08988b3..0e080ea3 100644 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); diff --git a/kexdh.c b/kexdh.c -index c1084f21..0faab21b 100644 +index c1084f214..0faab21b0 100644 --- a/kexdh.c +++ b/kexdh.c @@ -49,13 +49,23 @@ kex_dh_keygen(struct kex *kex) @@ -1517,7 +1517,7 @@ index c1084f21..0faab21b 100644 break; case KEX_DH_GRP18_SHA512: diff --git a/kexgen.c b/kexgen.c -index 40d688d6..15df591c 100644 +index 40d688d62..15df591ca 100644 --- a/kexgen.c +++ b/kexgen.c @@ -44,7 +44,7 @@ @@ -1531,7 +1531,7 @@ index 40d688d6..15df591c 100644 const struct sshbuf *client_version, diff --git a/kexgssc.c b/kexgssc.c new file mode 100644 -index 00000000..96f7b6f5 +index 000000000..96f7b6f58 --- /dev/null +++ b/kexgssc.c @@ -0,0 +1,706 @@ @@ -2243,7 +2243,7 @@ index 00000000..96f7b6f5 +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --git a/kexgsss.c b/kexgsss.c new file mode 100644 -index 00000000..8362081e +index 000000000..8362081ea --- /dev/null +++ b/kexgsss.c @@ -0,0 +1,601 @@ @@ -2849,7 +2849,7 @@ index 00000000..8362081e + +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --git a/monitor.c b/monitor.c -index 02b3eaaa..2ef16cc8 100644 +index 02b3eaaa3..2ef16cc8e 100644 --- a/monitor.c +++ b/monitor.c @@ -147,6 +147,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); @@ -3099,7 +3099,7 @@ index 02b3eaaa..2ef16cc8 100644 #endif /* GSSAPI */ diff --git a/monitor.h b/monitor.h -index 9dcd9c29..dbc7e003 100644 +index 9dcd9c293..dbc7e0037 100644 --- a/monitor.h +++ b/monitor.h @@ -68,6 +68,8 @@ enum monitor_reqtype { @@ -3112,7 +3112,7 @@ index 9dcd9c29..dbc7e003 100644 struct ssh; diff --git a/monitor_wrap.c b/monitor_wrap.c -index ef3ab1b1..b6e3b3f3 100644 +index ef3ab1b18..b6e3b3f39 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1131,13 +1131,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) @@ -3193,7 +3193,7 @@ index ef3ab1b1..b6e3b3f3 100644 /* diff --git a/monitor_wrap.h b/monitor_wrap.h -index 38a280c8..672dce52 100644 +index 38a280c87..672dce525 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -67,8 +67,10 @@ void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); @@ -3209,7 +3209,7 @@ index 38a280c8..672dce52 100644 #ifdef USE_PAM diff --git a/readconf.c b/readconf.c -index 7cbe7d2c..6c04ed43 100644 +index 7cbe7d2c2..6c04ed43c 100644 --- a/readconf.c +++ b/readconf.c @@ -71,6 +71,7 @@ @@ -3344,7 +3344,7 @@ index 7cbe7d2c..6c04ed43 100644 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); diff --git a/readconf.h b/readconf.h -index cd49139b..368523dd 100644 +index cd49139b1..368523dd7 100644 --- a/readconf.h +++ b/readconf.h @@ -39,7 +39,13 @@ typedef struct { @@ -3362,7 +3362,7 @@ index cd49139b..368523dd 100644 * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ diff --git a/servconf.c b/servconf.c -index f7bc9237..d4f7fd66 100644 +index f7bc92377..d4f7fd66f 100644 --- a/servconf.c +++ b/servconf.c @@ -69,6 +69,7 @@ @@ -3481,7 +3481,7 @@ index f7bc9237..d4f7fd66 100644 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, diff --git a/servconf.h b/servconf.h -index 9beb90fa..c3f50140 100644 +index 9beb90fae..c3f501400 100644 --- a/servconf.h +++ b/servconf.h @@ -150,8 +150,11 @@ typedef struct { @@ -3497,10 +3497,10 @@ index 9beb90fa..c3f50140 100644 * authentication. */ int kbd_interactive_authentication; /* If true, permit */ diff --git a/session.c b/session.c -index e4657cef..cbfbcee8 100644 +index 6444c77f3..b3833e44c 100644 --- a/session.c +++ b/session.c -@@ -2670,13 +2670,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +@@ -2668,13 +2668,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) #ifdef KRB5 if (options.kerberos_ticket_cleanup && @@ -3523,7 +3523,7 @@ index e4657cef..cbfbcee8 100644 /* remove agent socket */ diff --git a/ssh-gss.h b/ssh-gss.h -index 7b14e74a..8ec45192 100644 +index 7b14e74a8..8ec451926 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -61,10 +61,36 @@ @@ -3651,7 +3651,7 @@ index 7b14e74a..8ec45192 100644 #endif /* _SSH_GSS_H */ diff --git a/ssh.1 b/ssh.1 -index db92ac9a..6a9fbdc5 100644 +index db92ac9af..6a9fbdc5b 100644 --- a/ssh.1 +++ b/ssh.1 @@ -539,9 +539,15 @@ For full details of the options listed below, and their possible values, see @@ -3680,7 +3680,7 @@ index db92ac9a..6a9fbdc5 100644 (key types), .Ar key-ca-sign diff --git a/ssh.c b/ssh.c -index dc4886d0..c23d3b9e 100644 +index dc4886d0e..c23d3b9e3 100644 --- a/ssh.c +++ b/ssh.c @@ -835,6 +835,8 @@ main(int ac, char **av) @@ -3704,7 +3704,7 @@ index dc4886d0..c23d3b9e 100644 if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); diff --git a/ssh_config b/ssh_config -index 18169187..209248d6 100644 +index 181691873..209248d69 100644 --- a/ssh_config +++ b/ssh_config @@ -24,6 +24,8 @@ @@ -3717,7 +3717,7 @@ index 18169187..209248d6 100644 # CheckHostIP no # AddressFamily any diff --git a/ssh_config.5 b/ssh_config.5 -index 894d7383..3a8e246c 100644 +index 894d73831..3a8e246c4 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -976,10 +976,68 @@ The default is @@ -3790,7 +3790,7 @@ index 894d7383..3a8e246c 100644 Indicates that .Xr ssh 1 diff --git a/sshconnect2.c b/sshconnect2.c -index 1ee6000a..0af15bcc 100644 +index 1ee6000ab..0af15bcc1 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -222,6 +222,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, @@ -4023,10 +4023,10 @@ index 1ee6000a..0af15bcc 100644 static int diff --git a/sshd-auth.c b/sshd-auth.c -index f957dc22..d51e4636 100644 +index 30eecd8a4..62f1dc808 100644 --- a/sshd-auth.c +++ b/sshd-auth.c -@@ -844,6 +844,48 @@ do_ssh2_kex(struct ssh *ssh) +@@ -840,6 +840,48 @@ do_ssh2_kex(struct ssh *ssh) free(hkalgs); @@ -4075,7 +4075,7 @@ index f957dc22..d51e4636 100644 /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); -@@ -861,6 +903,17 @@ do_ssh2_kex(struct ssh *ssh) +@@ -857,6 +899,17 @@ do_ssh2_kex(struct ssh *ssh) # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif /* OPENSSL_HAS_ECC */ @@ -4094,7 +4094,7 @@ index f957dc22..d51e4636 100644 kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; diff --git a/sshd-session.c b/sshd-session.c -index a70b36c9..f8c8a797 100644 +index c759f95a4..3cfe71806 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -616,8 +616,8 @@ notify_hostkeys(struct ssh *ssh) @@ -4121,7 +4121,7 @@ index a70b36c9..f8c8a797 100644 /* Ensure that umask disallows at least group and world write */ new_umask = umask(0077) | 0022; diff --git a/sshd.c b/sshd.c -index 4a93e29e..c9ea8e38 100644 +index 4a93e29e4..c9ea8e385 100644 --- a/sshd.c +++ b/sshd.c @@ -1676,7 +1676,8 @@ main(int ac, char **av) @@ -4135,7 +4135,7 @@ index 4a93e29e..c9ea8e38 100644 exit(1); } diff --git a/sshd_config b/sshd_config -index 48af6321..8db9f0fb 100644 +index 48af6321b..8db9f0fb1 100644 --- a/sshd_config +++ b/sshd_config @@ -79,6 +79,8 @@ AuthorizedKeysFile .ssh/authorized_keys @@ -4148,7 +4148,7 @@ index 48af6321..8db9f0fb 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 035a50c8..8bc6586e 100644 +index 035a50c8c..8bc6586e6 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -739,6 +739,11 @@ Specifies whether to automatically destroy the user's credentials cache @@ -4197,7 +4197,7 @@ index 035a50c8..8bc6586e 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 ab80752b..4e41a78c 100644 +index ab80752b8..4e41a78c7 100644 --- a/sshkey.c +++ b/sshkey.c @@ -129,6 +129,75 @@ extern const struct sshkey_impl sshkey_xmss_impl; @@ -4294,7 +4294,7 @@ index ab80752b..4e41a78c 100644 if (!include_sigonly && impl->sigonly) continue; diff --git a/sshkey.h b/sshkey.h -index 19bbbac7..4a318d05 100644 +index 19bbbac7d..4a318d05b 100644 --- a/sshkey.h +++ b/sshkey.h @@ -75,6 +75,7 @@ enum sshkey_types { @@ -4306,5 +4306,5 @@ index 19bbbac7..4a318d05 100644 }; -- -2.49.0 +2.52.0 diff --git a/0013-openssh-6.6p1-force_krb.patch b/0012-openssh-6.6p1-force_krb.patch similarity index 97% rename from 0013-openssh-6.6p1-force_krb.patch rename to 0012-openssh-6.6p1-force_krb.patch index 74643b5..861112c 100644 --- a/0013-openssh-6.6p1-force_krb.patch +++ b/0012-openssh-6.6p1-force_krb.patch @@ -1,7 +1,7 @@ -From f5e5ee321def2a3674600714ad98fd1ca9b2cff1 Mon Sep 17 00:00:00 2001 +From 41d42d41834ed9b60a627fe6025cfe99be72e82c Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 13/50] openssh-6.6p1-force_krb +Subject: [PATCH 12/53] openssh-6.6p1-force_krb --- gss-serv-krb5.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++- @@ -11,7 +11,7 @@ Subject: [PATCH 13/50] openssh-6.6p1-force_krb 4 files changed, 189 insertions(+), 1 deletion(-) diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index 8d2b677f..14502c5a 100644 +index 8d2b677f7..14502c5a6 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c @@ -32,7 +32,9 @@ @@ -217,7 +217,7 @@ index 8d2b677f..14502c5a 100644 /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ diff --git a/session.c b/session.c -index cbfbcee8..89b3a9cf 100644 +index b3833e44c..40f36af17 100644 --- a/session.c +++ b/session.c @@ -680,6 +680,29 @@ do_exec(struct ssh *ssh, Session *s, const char *command) @@ -251,7 +251,7 @@ index cbfbcee8..89b3a9cf 100644 if (forced != NULL) { s->forced = 1; diff --git a/ssh-gss.h b/ssh-gss.h -index 8ec45192..db34d77f 100644 +index 8ec451926..db34d77f4 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -49,6 +49,10 @@ @@ -266,7 +266,7 @@ index 8ec45192..db34d77f 100644 /* draft-ietf-secsh-gsskeyex-06 */ diff --git a/sshd.8 b/sshd.8 -index 2aa73271..049d0a94 100644 +index 2aa732717..049d0a945 100644 --- a/sshd.8 +++ b/sshd.8 @@ -286,6 +286,7 @@ Finally, the server and the client enter an authentication dialog. @@ -291,5 +291,5 @@ index 2aa73271..049d0a94 100644 This directory is the default location for all user-specific configuration and authentication information. -- -2.49.0 +2.52.0 diff --git a/0014-openssh-7.7p1-gssapi-new-unique.patch b/0013-openssh-7.7p1-gssapi-new-unique.patch similarity index 97% rename from 0014-openssh-7.7p1-gssapi-new-unique.patch rename to 0013-openssh-7.7p1-gssapi-new-unique.patch index 1d21839..cd10771 100644 --- a/0014-openssh-7.7p1-gssapi-new-unique.patch +++ b/0013-openssh-7.7p1-gssapi-new-unique.patch @@ -1,7 +1,7 @@ -From 5fca5946aa97dce23c6824c52b070a92532752a9 Mon Sep 17 00:00:00 2001 +From ecc21a6a6d63b033a649f2446e2d2d38c19ae129 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 14/50] openssh-7.7p1-gssapi-new-unique +Subject: [PATCH 13/53] openssh-7.7p1-gssapi-new-unique --- auth-krb5.c | 262 ++++++++++++++++++++++++++++++++++++++++++------ @@ -17,7 +17,7 @@ Subject: [PATCH 14/50] openssh-7.7p1-gssapi-new-unique 10 files changed, 279 insertions(+), 71 deletions(-) diff --git a/auth-krb5.c b/auth-krb5.c -index c99e4e43..77714e3d 100644 +index c99e4e430..77714e3de 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -51,6 +51,7 @@ @@ -339,7 +339,7 @@ index c99e4e43..77714e3d 100644 #endif /* !HEIMDAL */ #endif /* KRB5 */ diff --git a/auth.h b/auth.h -index 83d07ae8..10e88e11 100644 +index 83d07ae8b..10e88e11f 100644 --- a/auth.h +++ b/auth.h @@ -85,6 +85,7 @@ struct Authctxt { @@ -360,7 +360,7 @@ index 83d07ae8..10e88e11 100644 #endif /* AUTH_H */ diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index 14502c5a..df55512d 100644 +index 14502c5a6..df55512d3 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c @@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, @@ -475,7 +475,7 @@ index 14502c5a..df55512d 100644 int diff --git a/gss-serv.c b/gss-serv.c -index a5cca797..9d5435ed 100644 +index a5cca7973..9d5435eda 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -414,13 +414,15 @@ ssh_gssapi_cleanup_creds(void) @@ -508,7 +508,7 @@ index a5cca797..9d5435ed 100644 ok = mm_ssh_gssapi_update_creds(&gssapi_client.store); diff --git a/servconf.c b/servconf.c -index d4f7fd66..55aa5bf0 100644 +index d4f7fd66f..55aa5bf02 100644 --- a/servconf.c +++ b/servconf.c @@ -138,6 +138,7 @@ initialize_server_options(ServerOptions *options) @@ -571,7 +571,7 @@ index d4f7fd66..55aa5bf0 100644 #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); diff --git a/servconf.h b/servconf.h -index c3f50140..a4a38d6d 100644 +index c3f501400..a4a38d6d7 100644 --- a/servconf.h +++ b/servconf.h @@ -149,6 +149,8 @@ typedef struct { @@ -584,7 +584,7 @@ index c3f50140..a4a38d6d 100644 int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ diff --git a/session.c b/session.c -index 89b3a9cf..2620dd11 100644 +index 40f36af17..c095a483a 100644 --- a/session.c +++ b/session.c @@ -1025,7 +1025,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) @@ -607,7 +607,7 @@ index 89b3a9cf..2620dd11 100644 s->authctxt->krb5_ccname); #endif diff --git a/ssh-gss.h b/ssh-gss.h -index db34d77f..a894e23c 100644 +index db34d77f4..a894e23c9 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -116,7 +116,7 @@ typedef struct ssh_gssapi_mech_struct { @@ -629,7 +629,7 @@ index db34d77f..a894e23c 100644 char *ssh_gssapi_server_mechanisms(void); diff --git a/sshd-session.c b/sshd-session.c -index f8c8a797..478381db 100644 +index 3cfe71806..1e15d4f0a 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -1349,7 +1349,7 @@ main(int ac, char **av) @@ -642,7 +642,7 @@ index f8c8a797..478381db 100644 } #endif diff --git a/sshd_config.5 b/sshd_config.5 -index 8bc6586e..1251d4d5 100644 +index 8bc6586e6..1251d4d54 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -1033,6 +1033,14 @@ Specifies whether to automatically destroy the user's ticket cache @@ -661,5 +661,5 @@ index 8bc6586e..1251d4d5 100644 Specifies the permitted KEX (Key Exchange) algorithms that the server will offer to clients. -- -2.49.0 +2.52.0 diff --git a/0015-openssh-7.2p2-k5login_directory.patch b/0014-openssh-7.2p2-k5login_directory.patch similarity index 91% rename from 0015-openssh-7.2p2-k5login_directory.patch rename to 0014-openssh-7.2p2-k5login_directory.patch index 5e980c8..6984887 100644 --- a/0015-openssh-7.2p2-k5login_directory.patch +++ b/0014-openssh-7.2p2-k5login_directory.patch @@ -1,7 +1,7 @@ -From 25540939422660b024b8832f67eab82267aa8df6 Mon Sep 17 00:00:00 2001 +From 30824076a227458d225a8b0e3c64771e8ac8fb75 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 15/50] openssh-7.2p2-k5login_directory +Subject: [PATCH 14/53] openssh-7.2p2-k5login_directory --- auth-krb5.c | 16 ++++++++++++++++ @@ -11,7 +11,7 @@ Subject: [PATCH 15/50] openssh-7.2p2-k5login_directory 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/auth-krb5.c b/auth-krb5.c -index 77714e3d..74f56d47 100644 +index 77714e3de..74f56d47f 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -465,5 +465,21 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm @@ -37,7 +37,7 @@ index 77714e3d..74f56d47 100644 #endif /* !HEIMDAL */ #endif /* KRB5 */ diff --git a/auth.h b/auth.h -index 10e88e11..39163035 100644 +index 10e88e11f..391630350 100644 --- a/auth.h +++ b/auth.h @@ -247,6 +247,8 @@ int sys_auth_passwd(struct ssh *, const char *); @@ -50,7 +50,7 @@ index 10e88e11..39163035 100644 #endif /* AUTH_H */ diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index df55512d..820f794c 100644 +index df55512d3..820f794cf 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c @@ -144,8 +144,27 @@ ssh_gssapi_k5login_exists() @@ -83,7 +83,7 @@ index df55512d..820f794c 100644 } diff --git a/sshd.8 b/sshd.8 -index 049d0a94..6784286d 100644 +index 049d0a945..6784286dc 100644 --- a/sshd.8 +++ b/sshd.8 @@ -880,6 +880,10 @@ rlogin/rsh. @@ -98,5 +98,5 @@ index 049d0a94..6784286d 100644 .It Pa ~/.ssh/ This directory is the default location for all user-specific configuration -- -2.49.0 +2.52.0 diff --git a/0016-openssh-6.6p1-kuserok.patch b/0015-openssh-6.6p1-kuserok.patch similarity index 97% rename from 0016-openssh-6.6p1-kuserok.patch rename to 0015-openssh-6.6p1-kuserok.patch index 3724b8d..5ddd72b 100644 --- a/0016-openssh-6.6p1-kuserok.patch +++ b/0015-openssh-6.6p1-kuserok.patch @@ -1,7 +1,7 @@ -From bac7a9d1a654c8c2e0c71f979195e300b25d6232 Mon Sep 17 00:00:00 2001 +From 44a1791e7f1ae1791e14e0974314d6016bec004a Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 16/50] openssh-6.6p1-kuserok +Subject: [PATCH 15/53] openssh-6.6p1-kuserok --- auth-krb5.c | 20 ++++++++- @@ -13,7 +13,7 @@ Subject: [PATCH 16/50] openssh-6.6p1-kuserok 6 files changed, 139 insertions(+), 7 deletions(-) diff --git a/auth-krb5.c b/auth-krb5.c -index 74f56d47..bae153c9 100644 +index 74f56d47f..bae153c93 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -55,6 +55,21 @@ @@ -51,7 +51,7 @@ index 74f56d47..bae153c9 100644 goto out; } diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index 820f794c..187faf92 100644 +index 820f794cf..187faf929 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c @@ -66,6 +66,7 @@ static int ssh_gssapi_krb5_cmdok(krb5_principal, const char *, const char *, @@ -189,7 +189,7 @@ index 820f794c..187faf92 100644 if ((fp = fopen(file, "r")) == NULL) { int saved_errno = errno; diff --git a/servconf.c b/servconf.c -index 55aa5bf0..5dd5ca21 100644 +index 55aa5bf02..5dd5ca213 100644 --- a/servconf.c +++ b/servconf.c @@ -145,6 +145,7 @@ initialize_server_options(ServerOptions *options) @@ -261,7 +261,7 @@ index 55aa5bf0..5dd5ca21 100644 #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); diff --git a/servconf.h b/servconf.h -index a4a38d6d..11de36a2 100644 +index a4a38d6d7..11de36a23 100644 --- a/servconf.h +++ b/servconf.h @@ -151,6 +151,7 @@ typedef struct { @@ -273,7 +273,7 @@ index a4a38d6d..11de36a2 100644 int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ diff --git a/sshd_config b/sshd_config -index 8db9f0fb..ea5a878e 100644 +index 8db9f0fb1..ea5a878e6 100644 --- a/sshd_config +++ b/sshd_config @@ -75,6 +75,7 @@ AuthorizedKeysFile .ssh/authorized_keys @@ -285,7 +285,7 @@ index 8db9f0fb..ea5a878e 100644 # GSSAPI options #GSSAPIAuthentication no diff --git a/sshd_config.5 b/sshd_config.5 -index 1251d4d5..0fcb409a 100644 +index 1251d4d54..0fcb409a6 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -1041,6 +1041,10 @@ The default value @@ -308,5 +308,5 @@ index 1251d4d5..0fcb409a 100644 .Cm MaxAuthTries , .Cm MaxSessions , -- -2.49.0 +2.52.0 diff --git a/0017-openssh-6.4p1-fromto-remote.patch b/0016-openssh-6.4p1-fromto-remote.patch similarity index 81% rename from 0017-openssh-6.4p1-fromto-remote.patch rename to 0016-openssh-6.4p1-fromto-remote.patch index 5e8309d..903b03f 100644 --- a/0017-openssh-6.4p1-fromto-remote.patch +++ b/0016-openssh-6.4p1-fromto-remote.patch @@ -1,14 +1,14 @@ -From 20aabb2c445e29d211266ce7434bb0273edf88b9 Mon Sep 17 00:00:00 2001 +From 5ade3deb755112e2062bd9ca136b6faee48cfee0 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 17/50] openssh-6.4p1-fromto-remote +Subject: [PATCH 16/53] openssh-6.4p1-fromto-remote --- scp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scp.c b/scp.c -index 57c242ff..716ae386 100644 +index 57c242ffc..716ae386b 100644 --- a/scp.c +++ b/scp.c @@ -1162,7 +1162,10 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) @@ -24,5 +24,5 @@ index 57c242ff..716ae386 100644 addargs(&alist, "%s", remote_remote_args.list[j]); -- -2.49.0 +2.52.0 diff --git a/0019-openssh-6.6.1p1-log-in-chroot.patch b/0017-openssh-6.6.1p1-log-in-chroot.patch similarity index 90% rename from 0019-openssh-6.6.1p1-log-in-chroot.patch rename to 0017-openssh-6.6.1p1-log-in-chroot.patch index 3b30f98..de5a784 100644 --- a/0019-openssh-6.6.1p1-log-in-chroot.patch +++ b/0017-openssh-6.6.1p1-log-in-chroot.patch @@ -1,7 +1,7 @@ -From 825018f5f2d892655f3d63167a0d1f3391cec678 Mon Sep 17 00:00:00 2001 +From a1509d4351de8bd1f8d85cdb9a7958000c10a4e2 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 19/50] openssh-6.6.1p1-log-in-chroot +Subject: [PATCH 17/53] openssh-6.6.1p1-log-in-chroot --- log.c | 11 +++++++++-- @@ -16,7 +16,7 @@ Subject: [PATCH 19/50] openssh-6.6.1p1-log-in-chroot 9 files changed, 52 insertions(+), 22 deletions(-) diff --git a/log.c b/log.c -index 6617f267..9782cfb0 100644 +index 6617f2672..9782cfb06 100644 --- a/log.c +++ b/log.c @@ -196,6 +196,11 @@ void @@ -45,7 +45,7 @@ index 6617f267..9782cfb0 100644 log_on_stderr = on_stderr; if (on_stderr) diff --git a/log.h b/log.h -index 8e8dfc23..70048a8a 100644 +index 8e8dfc23f..70048a8af 100644 --- a/log.h +++ b/log.h @@ -52,6 +52,7 @@ typedef enum { @@ -57,7 +57,7 @@ index 8e8dfc23..70048a8a 100644 int log_change_level(LogLevel); int log_is_on_stderr(void); diff --git a/monitor.c b/monitor.c -index 2ef16cc8..43c10a4e 100644 +index 2ef16cc8e..43c10a4ec 100644 --- a/monitor.c +++ b/monitor.c @@ -2001,9 +2001,22 @@ monitor_init(void) @@ -86,7 +86,7 @@ index 2ef16cc8..43c10a4e 100644 #ifdef GSSAPI diff --git a/monitor.h b/monitor.h -index dbc7e003..d4d631dd 100644 +index dbc7e0037..d4d631ddc 100644 --- a/monitor.h +++ b/monitor.h @@ -85,7 +85,7 @@ struct monitor { @@ -99,7 +99,7 @@ index dbc7e003..d4d631dd 100644 struct Authctxt; void monitor_child_preauth(struct ssh *, struct monitor *); diff --git a/session.c b/session.c -index 2620dd11..54da09d5 100644 +index c095a483a..dab771d3f 100644 --- a/session.c +++ b/session.c @@ -169,6 +169,7 @@ login_cap_t *lc; @@ -129,7 +129,7 @@ index 2620dd11..54da09d5 100644 verbose("Starting session: %s%s%s for %s from %.200s port %d id %d", session_type, tty == NULL ? "" : " on ", -@@ -1512,14 +1518,6 @@ child_close_fds(struct ssh *ssh) +@@ -1507,14 +1513,6 @@ child_close_fds(struct ssh *ssh) /* Stop directing logs to a high-numbered fd before we close it */ log_redirect_stderr_to(NULL); @@ -144,7 +144,7 @@ index 2620dd11..54da09d5 100644 } /* -@@ -1652,8 +1650,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) +@@ -1647,8 +1645,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) exit(1); } @@ -153,10 +153,10 @@ index 2620dd11..54da09d5 100644 do_rc_files(ssh, s, shell); /* restore SIGPIPE for child */ -@@ -1678,9 +1674,17 @@ do_child(struct ssh *ssh, Session *s, const char *command) - argv[i] = NULL; - optind = optreset = 1; - __progname = argv[0]; +@@ -1676,9 +1672,17 @@ do_child(struct ssh *ssh, Session *s, const char *command) + #ifdef WITH_SELINUX + ssh_selinux_change_context("sftpd_t"); + #endif - exit(sftp_server_main(i, argv, s->pw)); + exit(sftp_server_main(i, argv, s->pw, have_dev_log)); } @@ -173,7 +173,7 @@ index 2620dd11..54da09d5 100644 /* Get the last component of the shell name. */ diff --git a/sftp-server-main.c b/sftp-server-main.c -index 2c70f89b..bbb79f27 100644 +index 2c70f89bc..bbb79f278 100644 --- a/sftp-server-main.c +++ b/sftp-server-main.c @@ -48,5 +48,5 @@ main(int argc, char **argv) @@ -184,7 +184,7 @@ index 2c70f89b..bbb79f27 100644 + return (sftp_server_main(argc, argv, user_pw, 0)); } diff --git a/sftp-server.c b/sftp-server.c -index a4abb9f7..4985da38 100644 +index a4abb9f7c..4985da38f 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -1901,7 +1901,7 @@ sftp_server_usage(void) @@ -215,7 +215,7 @@ index a4abb9f7..4985da38 100644 /* * On platforms where we can, avoid making /proc/self/{mem,maps} diff --git a/sftp.h b/sftp.h -index 2bde8bb7..ddf1a396 100644 +index 2bde8bb7f..ddf1a3968 100644 --- a/sftp.h +++ b/sftp.h @@ -97,5 +97,5 @@ @@ -226,7 +226,7 @@ index 2bde8bb7..ddf1a396 100644 +int sftp_server_main(int, char **, struct passwd *, int); void sftp_server_cleanup_exit(int) __attribute__((noreturn)); diff --git a/sshd-session.c b/sshd-session.c -index 478381db..9342e416 100644 +index 1e15d4f0a..87b6122b0 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -437,7 +437,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) @@ -251,5 +251,5 @@ index 478381db..9342e416 100644 /* Demote the private keys to public keys. */ demote_sensitive_data(); -- -2.49.0 +2.52.0 diff --git a/0020-openssh-6.6.1p1-scp-non-existing-directory.patch b/0018-openssh-6.6.1p1-scp-non-existing-directory.patch similarity index 74% rename from 0020-openssh-6.6.1p1-scp-non-existing-directory.patch rename to 0018-openssh-6.6.1p1-scp-non-existing-directory.patch index 94c43ef..1c4f2c1 100644 --- a/0020-openssh-6.6.1p1-scp-non-existing-directory.patch +++ b/0018-openssh-6.6.1p1-scp-non-existing-directory.patch @@ -1,14 +1,14 @@ -From 007ee98fa9100f7241985ac2a7eed71e17d89a9f Mon Sep 17 00:00:00 2001 +From 4cf88a3767f326788a795fde687f80b97e4a0964 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 20/50] openssh-6.6.1p1-scp-non-existing-directory +Subject: [PATCH 18/53] openssh-6.6.1p1-scp-non-existing-directory --- scp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scp.c b/scp.c -index 716ae386..9554b188 100644 +index 716ae386b..9554b188b 100644 --- a/scp.c +++ b/scp.c @@ -1876,6 +1876,10 @@ sink(int argc, char **argv, const char *src) @@ -23,5 +23,5 @@ index 716ae386..9554b188 100644 mode |= S_IWUSR; if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { -- -2.49.0 +2.52.0 diff --git a/0018-openssh-6.6.1p1-selinux-contexts.patch b/0018-openssh-6.6.1p1-selinux-contexts.patch deleted file mode 100644 index 49f2119..0000000 --- a/0018-openssh-6.6.1p1-selinux-contexts.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 6481ac7fbd0027a7038560e0f51dd0af056cc229 Mon Sep 17 00:00:00 2001 -From: Dmitry Belyavskiy -Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 18/50] openssh-6.6.1p1-selinux-contexts - ---- - openbsd-compat/port-linux-sshd.c | 69 +++++++++++++++++++++++++++++++- - openbsd-compat/port-linux.c | 2 +- - openbsd-compat/port-linux.h | 1 + - sshd-auth.c | 2 +- - 4 files changed, 71 insertions(+), 3 deletions(-) - -diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c -index 8c5fc1fe..646f0887 100644 ---- a/openbsd-compat/port-linux-sshd.c -+++ b/openbsd-compat/port-linux-sshd.c -@@ -33,6 +33,7 @@ - #include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */ - #include "servconf.h" - #include "port-linux.h" -+#include "misc.h" - #include "sshkey.h" - #include "hostfile.h" - #include "auth.h" -@@ -450,7 +451,7 @@ sshd_selinux_setup_exec_context(char *pwname) - void - sshd_selinux_copy_context(void) - { -- security_context_t *ctx; -+ char *ctx; - - if (!sshd_selinux_enabled()) - return; -@@ -469,6 +470,72 @@ sshd_selinux_copy_context(void) - } - } - -+void -+sshd_selinux_change_privsep_preauth_context(void) -+{ -+ int len; -+ char line[1024], *preauth_context = NULL, *cp, *arg; -+ const char *contexts_path; -+ FILE *contexts_file; -+ struct stat sb; -+ -+ contexts_path = selinux_openssh_contexts_path(); -+ if (contexts_path == NULL) { -+ debug3_f("Failed to get the path to SELinux context"); -+ return; -+ } -+ -+ if ((contexts_file = fopen(contexts_path, "r")) == NULL) { -+ debug_f("Failed to open SELinux context file"); -+ return; -+ } -+ -+ if (fstat(fileno(contexts_file), &sb) != 0 || -+ sb.st_uid != 0 || (sb.st_mode & 022) != 0) { -+ logit_f("SELinux context file needs to be owned by root" -+ " and not writable by anyone else"); -+ fclose(contexts_file); -+ return; -+ } -+ -+ while (fgets(line, sizeof(line), contexts_file)) { -+ /* Strip trailing whitespace */ -+ for (len = strlen(line) - 1; len > 0; len--) { -+ if (strchr(" \t\r\n", line[len]) == NULL) -+ break; -+ line[len] = '\0'; -+ } -+ -+ if (line[0] == '\0') -+ continue; -+ -+ cp = line; -+ arg = strdelim(&cp); -+ if (arg && *arg == '\0') -+ arg = strdelim(&cp); -+ -+ if (arg && strcmp(arg, "privsep_preauth") == 0) { -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') { -+ debug_f("privsep_preauth is empty"); -+ fclose(contexts_file); -+ return; -+ } -+ preauth_context = xstrdup(arg); -+ } -+ } -+ fclose(contexts_file); -+ -+ if (preauth_context == NULL) { -+ debug_f("Unable to find 'privsep_preauth' option in" -+ " SELinux context file"); -+ return; -+ } -+ -+ ssh_selinux_change_context(preauth_context); -+ free(preauth_context); -+} -+ - #endif - #endif - -diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c -index 7426f6f7..9a6b1d6e 100644 ---- a/openbsd-compat/port-linux.c -+++ b/openbsd-compat/port-linux.c -@@ -188,7 +188,7 @@ ssh_selinux_change_context(const char *newname) - xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx, - newname, cx2 == NULL ? "" : cx2); - -- debug3_f("setting context from '%s' to '%s'", oldctx, newctx); -+ debug_f("setting context from '%s' to '%s'", oldctx, newctx); - if (setcon(newctx) < 0) - do_log2_f(log_level, "setcon %s from %s failed with %s", - newctx, oldctx, strerror(errno)); -diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h -index 1b745a76..7f8ba200 100644 ---- a/openbsd-compat/port-linux.h -+++ b/openbsd-compat/port-linux.h -@@ -27,6 +27,7 @@ int sshd_selinux_enabled(void); - void sshd_selinux_copy_context(void); - void sshd_selinux_setup_exec_context(char *); - int sshd_selinux_setup_env_variables(void); -+void sshd_selinux_change_privsep_preauth_context(void); - #endif - - #ifdef LINUX_OOM_ADJUST -diff --git a/sshd-auth.c b/sshd-auth.c -index d51e4636..e4a8edfd 100644 ---- a/sshd-auth.c -+++ b/sshd-auth.c -@@ -188,7 +188,7 @@ privsep_child_demote(void) - fatal_f("ssh_sandbox_init failed"); - #endif - #ifdef WITH_SELINUX -- ssh_selinux_change_context("sshd_net_t"); -+ sshd_selinux_change_privsep_preauth_context(); - #endif - - /* Demote the child */ --- -2.49.0 - diff --git a/0021-openssh-6.6p1-GSSAPIEnablek5users.patch b/0019-openssh-6.6p1-GSSAPIEnablek5users.patch similarity index 94% rename from 0021-openssh-6.6p1-GSSAPIEnablek5users.patch rename to 0019-openssh-6.6p1-GSSAPIEnablek5users.patch index eeff02a..4f500e0 100644 --- a/0021-openssh-6.6p1-GSSAPIEnablek5users.patch +++ b/0019-openssh-6.6p1-GSSAPIEnablek5users.patch @@ -1,7 +1,7 @@ -From 9c75c175e3555377328fc5fc9b06e94f129b7cd7 Mon Sep 17 00:00:00 2001 +From b14be52d0033c535732efa76f4b416e8a0d97b74 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 21/50] openssh-6.6p1-GSSAPIEnablek5users +Subject: [PATCH 19/53] openssh-6.6p1-GSSAPIEnablek5users --- gss-serv-krb5.c | 3 +-- @@ -12,7 +12,7 @@ Subject: [PATCH 21/50] openssh-6.6p1-GSSAPIEnablek5users 5 files changed, 21 insertions(+), 3 deletions(-) diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index 187faf92..03188d9b 100644 +index 187faf929..03188d9b3 100644 --- a/gss-serv-krb5.c +++ b/gss-serv-krb5.c @@ -278,7 +278,6 @@ ssh_gssapi_krb5_cmdok(krb5_principal principal, const char *name, @@ -33,7 +33,7 @@ index 187faf92..03188d9b 100644 k5login_exists); } diff --git a/servconf.c b/servconf.c -index 5dd5ca21..c0de7110 100644 +index 5dd5ca213..c0de71108 100644 --- a/servconf.c +++ b/servconf.c @@ -146,6 +146,7 @@ initialize_server_options(ServerOptions *options) @@ -106,7 +106,7 @@ index 5dd5ca21..c0de7110 100644 #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); diff --git a/servconf.h b/servconf.h -index 11de36a2..c08cf6a7 100644 +index 11de36a23..c08cf6a7a 100644 --- a/servconf.h +++ b/servconf.h @@ -152,6 +152,7 @@ typedef struct { @@ -118,7 +118,7 @@ index 11de36a2..c08cf6a7 100644 int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ diff --git a/sshd_config b/sshd_config -index ea5a878e..33713c88 100644 +index ea5a878e6..33713c886 100644 --- a/sshd_config +++ b/sshd_config @@ -82,6 +82,7 @@ AuthorizedKeysFile .ssh/authorized_keys @@ -130,7 +130,7 @@ index ea5a878e..33713c88 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 0fcb409a..fe246fc2 100644 +index 0fcb409a6..fe246fc21 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -739,6 +739,12 @@ Specifies whether to automatically destroy the user's credentials cache @@ -147,5 +147,5 @@ index 0fcb409a..fe246fc2 100644 Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange doesn't rely on ssh keys to verify host identity. -- -2.49.0 +2.52.0 diff --git a/0022-openssh-6.8p1-sshdT-output.patch b/0020-openssh-6.8p1-sshdT-output.patch similarity index 81% rename from 0022-openssh-6.8p1-sshdT-output.patch rename to 0020-openssh-6.8p1-sshdT-output.patch index 4e4766e..86b77ed 100644 --- a/0022-openssh-6.8p1-sshdT-output.patch +++ b/0020-openssh-6.8p1-sshdT-output.patch @@ -1,14 +1,14 @@ -From 05b09904f431333e19cd24528ef66d1fd15e9efe Mon Sep 17 00:00:00 2001 +From 18402a4f528d772e71d01cbd5d2a0dffb048fd89 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 22/50] openssh-6.8p1-sshdT-output +Subject: [PATCH 20/53] openssh-6.8p1-sshdT-output --- servconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servconf.c b/servconf.c -index c0de7110..105e301d 100644 +index c0de71108..105e301d9 100644 --- a/servconf.c +++ b/servconf.c @@ -3366,7 +3366,7 @@ dump_config(ServerOptions *o) @@ -21,5 +21,5 @@ index c0de7110..105e301d 100644 dump_cfg_string(sChrootDirectory, o->chroot_directory); dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); -- -2.49.0 +2.52.0 diff --git a/0023-openssh-6.7p1-sftp-force-permission.patch b/0021-openssh-6.7p1-sftp-force-permission.patch similarity index 94% rename from 0023-openssh-6.7p1-sftp-force-permission.patch rename to 0021-openssh-6.7p1-sftp-force-permission.patch index 1cdc0df..0cb6915 100644 --- a/0023-openssh-6.7p1-sftp-force-permission.patch +++ b/0021-openssh-6.7p1-sftp-force-permission.patch @@ -1,7 +1,7 @@ -From 34b196198018059bed294fa7a08e70606b4cbc36 Mon Sep 17 00:00:00 2001 +From 2ea1fc3bf0996b06bb0fa6c41b2e1d49d4f203be Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 23/50] openssh-6.7p1-sftp-force-permission +Subject: [PATCH 21/53] openssh-6.7p1-sftp-force-permission --- sftp-server.8 | 7 +++++++ @@ -9,7 +9,7 @@ Subject: [PATCH 23/50] openssh-6.7p1-sftp-force-permission 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/sftp-server.8 b/sftp-server.8 -index 5311bf92..5e6e3aa4 100644 +index 5311bf929..5e6e3aa44 100644 --- a/sftp-server.8 +++ b/sftp-server.8 @@ -38,6 +38,7 @@ @@ -34,7 +34,7 @@ index 5311bf92..5e6e3aa4 100644 .Pp On some systems, diff --git a/sftp-server.c b/sftp-server.c -index 4985da38..6ed1c27f 100644 +index 4985da38f..6ed1c27fa 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -76,6 +76,10 @@ struct sshbuf *oqueue; @@ -111,5 +111,5 @@ index 4985da38..6ed1c27f 100644 default: sftp_server_usage(); -- -2.49.0 +2.52.0 diff --git a/0024-openssh-7.2p2-s390-closefrom.patch b/0022-openssh-7.2p2-s390-closefrom.patch similarity index 89% rename from 0024-openssh-7.2p2-s390-closefrom.patch rename to 0022-openssh-7.2p2-s390-closefrom.patch index 0214781..cd939d7 100644 --- a/0024-openssh-7.2p2-s390-closefrom.patch +++ b/0022-openssh-7.2p2-s390-closefrom.patch @@ -1,14 +1,14 @@ -From 9bb31b63142adaaf949e20c2d86c97f9b787217b Mon Sep 17 00:00:00 2001 +From dea189d1c1ed7d206db52cd6dcf72388c0ff5778 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 24/50] openssh-7.2p2-s390-closefrom +Subject: [PATCH 22/53] openssh-7.2p2-s390-closefrom --- openbsd-compat/bsd-closefrom.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c -index 49a4f35f..f6112458 100644 +index 49a4f35ff..f61124585 100644 --- a/openbsd-compat/bsd-closefrom.c +++ b/openbsd-compat/bsd-closefrom.c @@ -140,7 +140,33 @@ closefrom(int lowfd) @@ -46,5 +46,5 @@ index 49a4f35f..f6112458 100644 (void) closedir(dirp); return; -- -2.49.0 +2.52.0 diff --git a/0025-openssh-7.3p1-x11-max-displays.patch b/0023-openssh-7.3p1-x11-max-displays.patch similarity index 94% rename from 0025-openssh-7.3p1-x11-max-displays.patch rename to 0023-openssh-7.3p1-x11-max-displays.patch index 68d679c..09aa917 100644 --- a/0025-openssh-7.3p1-x11-max-displays.patch +++ b/0023-openssh-7.3p1-x11-max-displays.patch @@ -1,7 +1,7 @@ -From 36e3430d1f81397d5f40600e075272a81f7effce Mon Sep 17 00:00:00 2001 +From f727dd5c28358d7dcd132fca006a8cebce054d40 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 25/50] openssh-7.3p1-x11-max-displays +Subject: [PATCH 23/53] openssh-7.3p1-x11-max-displays --- channels.c | 9 ++++++--- @@ -13,7 +13,7 @@ Subject: [PATCH 25/50] openssh-7.3p1-x11-max-displays 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/channels.c b/channels.c -index d46531ce..7438c1a5 100644 +index d46531ce0..7438c1a58 100644 --- a/channels.c +++ b/channels.c @@ -4996,7 +4996,7 @@ rdynamic_connect_finish(struct ssh *ssh, Channel *c) @@ -48,7 +48,7 @@ index d46531ce..7438c1a5 100644 return -1; } diff --git a/channels.h b/channels.h -index 134528d5..8a09a820 100644 +index 134528d59..8a09a8202 100644 --- a/channels.h +++ b/channels.h @@ -379,7 +379,7 @@ int permitopen_port(const char *); @@ -61,7 +61,7 @@ index 134528d5..8a09a820 100644 const char *, const char *, const char *, int); int x11_channel_used_recently(struct ssh *ssh); diff --git a/servconf.c b/servconf.c -index 105e301d..15c99b30 100644 +index 105e301d9..15c99b303 100644 --- a/servconf.c +++ b/servconf.c @@ -117,6 +117,7 @@ initialize_server_options(ServerOptions *options) @@ -126,7 +126,7 @@ index 105e301d..15c99b30 100644 dump_cfg_int(sMaxSessions, o->max_sessions); dump_cfg_int(sClientAliveInterval, o->client_alive_interval); diff --git a/servconf.h b/servconf.h -index c08cf6a7..7c7e5d43 100644 +index c08cf6a7a..7c7e5d434 100644 --- a/servconf.h +++ b/servconf.h @@ -38,6 +38,7 @@ @@ -146,10 +146,10 @@ index c08cf6a7..7c7e5d43 100644 char *xauth_location; /* Location of xauth program */ int permit_tty; /* If false, deny pty allocation */ diff --git a/session.c b/session.c -index 54da09d5..28bbb8a7 100644 +index dab771d3f..d7f05848e 100644 --- a/session.c +++ b/session.c -@@ -2611,8 +2611,9 @@ session_setup_x11fwd(struct ssh *ssh, Session *s) +@@ -2609,8 +2609,9 @@ session_setup_x11fwd(struct ssh *ssh, Session *s) return 0; } if (x11_create_display_inet(ssh, options.x11_display_offset, @@ -162,7 +162,7 @@ index 54da09d5..28bbb8a7 100644 return 0; } diff --git a/sshd_config.5 b/sshd_config.5 -index fe246fc2..26fcdc84 100644 +index fe246fc21..26fcdc840 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -1391,6 +1391,7 @@ Available keywords are @@ -187,5 +187,5 @@ index fe246fc2..26fcdc84 100644 Specifies whether X11 forwarding is permitted. The argument must be -- -2.49.0 +2.52.0 diff --git a/0026-openssh-7.6p1-cleanup-selinux.patch b/0024-openssh-7.6p1-cleanup-selinux.patch similarity index 87% rename from 0026-openssh-7.6p1-cleanup-selinux.patch rename to 0024-openssh-7.6p1-cleanup-selinux.patch index c4f2d15..a618fd1 100644 --- a/0026-openssh-7.6p1-cleanup-selinux.patch +++ b/0024-openssh-7.6p1-cleanup-selinux.patch @@ -1,22 +1,22 @@ -From 43320351b6f150167190aacc84f2f87030fef3d2 Mon Sep 17 00:00:00 2001 +From 41acb1470333db97ed767b3459c6b34ccb84ec73 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 26/50] openssh-7.6p1-cleanup-selinux +Subject: [PATCH 24/53] openssh-7.6p1-cleanup-selinux --- auth2-pubkey.c | 8 ++++-- misc.c | 5 ++-- misc.h | 2 +- openbsd-compat/port-linux-sshd.c | 42 +++++++++++++++++--------------- - openbsd-compat/port-linux.h | 4 +-- + openbsd-compat/port-linux.h | 5 ++-- platform.c | 6 ++++- sshconnect.c | 2 +- sshd-auth.c | 2 +- sshd-session.c | 6 +++-- - 9 files changed, 45 insertions(+), 32 deletions(-) + 9 files changed, 46 insertions(+), 32 deletions(-) diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index 267a27d2..0d5ae0df 100644 +index 267a27d24..0d5ae0df7 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -77,6 +77,8 @@ @@ -49,7 +49,7 @@ index 267a27d2..0d5ae0df 100644 uid_swapped = 1; diff --git a/misc.c b/misc.c -index 1e31acc9..09722962 100644 +index 1e31acc95..097229620 100644 --- a/misc.c +++ b/misc.c @@ -2764,7 +2764,8 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) @@ -72,7 +72,7 @@ index 1e31acc9..09722962 100644 strerror(errno)); _exit(127); diff --git a/misc.h b/misc.h -index efecdf1a..9efa9cf4 100644 +index efecdf1ad..9efa9cf47 100644 --- a/misc.h +++ b/misc.h @@ -122,7 +122,7 @@ typedef void privrestore_fn(void); @@ -85,10 +85,10 @@ index efecdf1a..9efa9cf4 100644 typedef struct arglist arglist; struct arglist { diff --git a/openbsd-compat/port-linux-sshd.c b/openbsd-compat/port-linux-sshd.c -index 646f0887..291b569a 100644 +index 4d56745f7..ab083a637 100644 --- a/openbsd-compat/port-linux-sshd.c +++ b/openbsd-compat/port-linux-sshd.c -@@ -49,10 +49,6 @@ +@@ -48,10 +48,6 @@ #include #endif @@ -99,7 +99,7 @@ index 646f0887..291b569a 100644 /* Wrapper around is_selinux_enabled() to log its return value once only */ int sshd_selinux_enabled(void) -@@ -222,7 +218,8 @@ get_user_context(const char *sename, const char *role, const char *lvl, +@@ -221,7 +217,8 @@ get_user_context(const char *sename, const char *role, const char *lvl, } static void @@ -109,7 +109,7 @@ index 646f0887..291b569a 100644 { *role = NULL; *level = NULL; -@@ -240,8 +237,8 @@ ssh_selinux_get_role_level(char **role, const char **level) +@@ -239,8 +236,8 @@ ssh_selinux_get_role_level(char **role, const char **level) /* Return the default security context for the given username */ static int @@ -120,7 +120,7 @@ index 646f0887..291b569a 100644 { char *sename, *lvl; char *role; -@@ -249,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -248,7 +245,7 @@ sshd_selinux_getctxbyname(char *pwname, int r = 0; context_t con = NULL; @@ -129,7 +129,7 @@ index 646f0887..291b569a 100644 #ifdef HAVE_GETSEUSERBYNAME if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { -@@ -271,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -270,7 +267,7 @@ sshd_selinux_getctxbyname(char *pwname, if (r == 0) { /* If launched from xinetd, we must use current level */ @@ -138,7 +138,7 @@ index 646f0887..291b569a 100644 security_context_t sshdsc=NULL; if (getcon_raw(&sshdsc) < 0) -@@ -332,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -331,7 +328,8 @@ sshd_selinux_getctxbyname(char *pwname, /* Setup environment variables for pam_selinux */ static int @@ -148,7 +148,7 @@ index 646f0887..291b569a 100644 { const char *reqlvl; char *role; -@@ -341,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) +@@ -340,11 +338,11 @@ sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) debug3_f("setting execution context"); @@ -162,7 +162,7 @@ index 646f0887..291b569a 100644 use_current = "1"; } else { use_current = ""; -@@ -361,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) +@@ -360,9 +358,10 @@ sshd_selinux_setup_variables(int(*set_it)(char *, const char *)) } static int @@ -175,7 +175,7 @@ index 646f0887..291b569a 100644 } static int -@@ -373,25 +372,28 @@ do_setenv(char *name, const char *value) +@@ -372,25 +371,28 @@ do_setenv(char *name, const char *value) } int @@ -209,7 +209,7 @@ index 646f0887..291b569a 100644 switch (security_getenforce()) { case -1: fatal_f("security_getenforce() failed"); -@@ -407,7 +409,7 @@ sshd_selinux_setup_exec_context(char *pwname) +@@ -406,7 +408,7 @@ sshd_selinux_setup_exec_context(char *pwname) debug3_f("setting execution context"); @@ -219,22 +219,23 @@ index 646f0887..291b569a 100644 r = setexeccon(user_ctx); if (r < 0) { diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h -index 7f8ba200..3cd7da6a 100644 +index c004071d1..26c5f773b 100644 --- a/openbsd-compat/port-linux.h +++ b/openbsd-compat/port-linux.h -@@ -25,8 +25,8 @@ void ssh_selinux_setfscreatecon(const char *); +@@ -23,8 +23,9 @@ void ssh_selinux_setup_pty(char *, const char *); + void ssh_selinux_change_context(const char *); + void ssh_selinux_setfscreatecon(const char *); - int sshd_selinux_enabled(void); - void sshd_selinux_copy_context(void); -void sshd_selinux_setup_exec_context(char *); -int sshd_selinux_setup_env_variables(void); ++int sshd_selinux_enabled(void); +void sshd_selinux_setup_exec_context(char *, int, int(char *, const char *), void *, int); +int sshd_selinux_setup_env_variables(int inetd, void *); - void sshd_selinux_change_privsep_preauth_context(void); #endif + #ifdef LINUX_OOM_ADJUST diff --git a/platform.c b/platform.c -index 0d12f311..f0800b1f 100644 +index 0d12f3111..f0800b1fc 100644 --- a/platform.c +++ b/platform.c @@ -33,6 +33,8 @@ @@ -258,7 +259,7 @@ index 0d12f311..f0800b1f 100644 } diff --git a/sshconnect.c b/sshconnect.c -index c86182d1..04084810 100644 +index c86182d13..040848105 100644 --- a/sshconnect.c +++ b/sshconnect.c @@ -925,7 +925,7 @@ load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template, @@ -271,7 +272,7 @@ index c86182d1..04084810 100644 load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); diff --git a/sshd-auth.c b/sshd-auth.c -index e4a8edfd..897db9b4 100644 +index 62f1dc808..de61be5ac 100644 --- a/sshd-auth.c +++ b/sshd-auth.c @@ -122,7 +122,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; @@ -284,7 +285,7 @@ index e4a8edfd..897db9b4 100644 /* Saved arguments to main(). */ static char **saved_argv; diff --git a/sshd-session.c b/sshd-session.c -index 9342e416..81d30152 100644 +index 87b6122b0..e86acf704 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -136,7 +136,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; @@ -308,5 +309,5 @@ index 9342e416..81d30152 100644 #ifdef USE_PAM if (options.use_pam) { -- -2.49.0 +2.52.0 diff --git a/0027-openssh-7.5p1-sandbox.patch b/0025-openssh-7.5p1-sandbox.patch similarity index 89% rename from 0027-openssh-7.5p1-sandbox.patch rename to 0025-openssh-7.5p1-sandbox.patch index 435d029..82fda78 100644 --- a/0027-openssh-7.5p1-sandbox.patch +++ b/0025-openssh-7.5p1-sandbox.patch @@ -1,14 +1,14 @@ -From 35205319dd71d8e61c1596b8f9479df91aff7756 Mon Sep 17 00:00:00 2001 +From 5cb527355936245bfb90aef0fddd23146b134772 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 27/50] openssh-7.5p1-sandbox +Subject: [PATCH 25/53] openssh-7.5p1-sandbox --- sandbox-seccomp-filter.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index b31062c2..1fabf99d 100644 +index b31062c2b..1fabf99d0 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c @@ -277,6 +277,9 @@ static const struct sock_filter preauth_insns[] = { @@ -54,5 +54,5 @@ index b31062c2..1fabf99d 100644 SC_ALLOW(__NR_getuid), #endif -- -2.49.0 +2.52.0 diff --git a/0028-openssh-8.0p1-pkcs11-uri.patch b/0026-openssh-8.0p1-pkcs11-uri.patch similarity index 99% rename from 0028-openssh-8.0p1-pkcs11-uri.patch rename to 0026-openssh-8.0p1-pkcs11-uri.patch index 73e890b..3a7a603 100644 --- a/0028-openssh-8.0p1-pkcs11-uri.patch +++ b/0026-openssh-8.0p1-pkcs11-uri.patch @@ -1,7 +1,7 @@ -From 5d6ec35c1a0e06452a2c087decb0baf6e8063e21 Mon Sep 17 00:00:00 2001 +From 14abcc0887a8435549154137a43e68359f9d64eb Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 28/50] openssh-8.0p1-pkcs11-uri +Subject: [PATCH 26/53] openssh-8.0p1-pkcs11-uri --- Makefile.in | 20 +- @@ -27,7 +27,7 @@ Subject: [PATCH 28/50] openssh-8.0p1-pkcs11-uri create mode 100644 ssh-pkcs11-uri.h diff --git a/Makefile.in b/Makefile.in -index 78f65948..6c417ef7 100644 +index 78f659487..6c417ef7c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -110,7 +110,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ @@ -93,7 +93,7 @@ index 78f65948..6c417ef7 100644 tests: file-tests t-exec interop-tests extra-tests unit echo all tests passed diff --git a/configure.ac b/configure.ac -index 13c70a98..d9bd2f51 100644 +index 13c70a983..d9bd2f516 100644 --- a/configure.ac +++ b/configure.ac @@ -2172,12 +2172,14 @@ AC_LINK_IFELSE( @@ -161,7 +161,7 @@ index 13c70a98..d9bd2f51 100644 echo "" diff --git a/regress/Makefile b/regress/Makefile -index 7e7f95b5..f36de51e 100644 +index 7e7f95b58..f36de51e8 100644 --- a/regress/Makefile +++ b/regress/Makefile @@ -137,7 +137,8 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ @@ -188,7 +188,7 @@ index 7e7f95b5..f36de51e 100644 -d ${.CURDIR}/unittests/sshsig/testdata ; \ diff --git a/regress/pkcs11.sh b/regress/pkcs11.sh new file mode 100644 -index 00000000..a91aee94 +index 000000000..a91aee94f --- /dev/null +++ b/regress/pkcs11.sh @@ -0,0 +1,349 @@ @@ -542,7 +542,7 @@ index 00000000..a91aee94 + ${SSHAGENT} -k > /dev/null +fi diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile -index e370900e..d6c89c12 100644 +index e370900e4..d6c89c129 100644 --- a/regress/unittests/Makefile +++ b/regress/unittests/Makefile @@ -1,6 +1,6 @@ @@ -555,7 +555,7 @@ index e370900e..d6c89c12 100644 .include diff --git a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c new file mode 100644 -index 00000000..7d4fa499 +index 000000000..7d4fa4992 --- /dev/null +++ b/regress/unittests/pkcs11/tests.c @@ -0,0 +1,346 @@ @@ -906,7 +906,7 @@ index 00000000..7d4fa499 + test_generate_valid(); +} diff --git a/ssh-add.c b/ssh-add.c -index 0035cb84..b0f47f4d 100644 +index 0035cb84a..b0f47f4de 100644 --- a/ssh-add.c +++ b/ssh-add.c @@ -69,6 +69,7 @@ @@ -999,7 +999,7 @@ index 0035cb84..b0f47f4d 100644 goto done; } diff --git a/ssh-agent.c b/ssh-agent.c -index c27c5a95..798bf9b6 100644 +index c27c5a956..798bf9b60 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1569,10 +1569,74 @@ add_p11_identity(struct sshkey *key, char *comment, const char *provider, @@ -1180,7 +1180,7 @@ index c27c5a95..798bf9b6 100644 } #endif /* ENABLE_PKCS11 */ diff --git a/ssh-keygen.c b/ssh-keygen.c -index 89c3ed28..16cff947 100644 +index 89c3ed287..16cff9473 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -906,8 +906,11 @@ do_download(struct passwd *pw) @@ -1198,7 +1198,7 @@ index 89c3ed28..16cff947 100644 free(comments[i]); sshkey_free(keys[i]); diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c -index b8d1700f..64df695e 100644 +index b8d1700f0..64df695e1 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c @@ -635,6 +635,8 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, @@ -1220,7 +1220,7 @@ index b8d1700f..64df695e 100644 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 00000000..8bd97e9e +index 000000000..8bd97e9e2 --- /dev/null +++ b/ssh-pkcs11-uri.c @@ -0,0 +1,437 @@ @@ -1663,7 +1663,7 @@ index 00000000..8bd97e9e +#endif /* ENABLE_PKCS11 */ diff --git a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h new file mode 100644 -index 00000000..29e9f732 +index 000000000..29e9f7327 --- /dev/null +++ b/ssh-pkcs11-uri.h @@ -0,0 +1,43 @@ @@ -1711,7 +1711,7 @@ index 00000000..29e9f732 +char *pkcs11_uri_get(struct pkcs11_uri *uri); + diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c -index 31b9360f..b96f5b89 100644 +index 31b9360f0..b96f5b890 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c @@ -38,6 +38,7 @@ @@ -2982,7 +2982,7 @@ index 31b9360f..b96f5b89 100644 return (nkeys); } diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h -index 52602231..9ce20c1f 100644 +index 526022319..9ce20c1f9 100644 --- a/ssh-pkcs11.h +++ b/ssh-pkcs11.h @@ -22,10 +22,14 @@ @@ -3001,7 +3001,7 @@ index 52602231..9ce20c1f 100644 struct sshkey * pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, diff --git a/ssh.c b/ssh.c -index c23d3b9e..98b103c9 100644 +index c23d3b9e3..98b103c9e 100644 --- a/ssh.c +++ b/ssh.c @@ -890,6 +890,14 @@ main(int ac, char **av) @@ -3152,7 +3152,7 @@ index c23d3b9e..98b103c9 100644 free(cp); check_load(sshkey_load_public(filename, &public, NULL), diff --git a/ssh_config.5 b/ssh_config.5 -index 3a8e246c..8d5d0722 100644 +index 3a8e246c4..8d5d07222 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -1263,6 +1263,21 @@ may also be used in conjunction with @@ -3178,5 +3178,5 @@ index 3a8e246c..8d5d0722 100644 Specifies a pattern-list of unknown options to be ignored if they are encountered in configuration parsing. -- -2.49.0 +2.52.0 diff --git a/0029-openssh-7.8p1-scp-ipv6.patch b/0027-openssh-7.8p1-scp-ipv6.patch similarity index 82% rename from 0029-openssh-7.8p1-scp-ipv6.patch rename to 0027-openssh-7.8p1-scp-ipv6.patch index dbd69aa..3070ed2 100644 --- a/0029-openssh-7.8p1-scp-ipv6.patch +++ b/0027-openssh-7.8p1-scp-ipv6.patch @@ -1,14 +1,14 @@ -From 507e6f245557ae7261806f7ecbd40697cb0dd389 Mon Sep 17 00:00:00 2001 +From e364c7688e94903c894533d4c09f6441f8ddd482 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 29/50] openssh-7.8p1-scp-ipv6 +Subject: [PATCH 27/53] openssh-7.8p1-scp-ipv6 --- scp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scp.c b/scp.c -index 9554b188..7f9795a5 100644 +index 9554b188b..7f9795a57 100644 --- a/scp.c +++ b/scp.c @@ -1183,7 +1183,9 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) @@ -23,5 +23,5 @@ index 9554b188..7f9795a5 100644 thost, targ); if (do_local_cmd(&alist) != 0) -- -2.49.0 +2.52.0 diff --git a/0030-openssh-8.0p1-crypto-policies.patch b/0028-openssh-8.0p1-crypto-policies.patch similarity index 99% rename from 0030-openssh-8.0p1-crypto-policies.patch rename to 0028-openssh-8.0p1-crypto-policies.patch index 498e3f5..35f4b24 100644 --- a/0030-openssh-8.0p1-crypto-policies.patch +++ b/0028-openssh-8.0p1-crypto-policies.patch @@ -1,7 +1,7 @@ -From b436140fe3abd9f97f01f9af9f5da5cf6c5d7725 Mon Sep 17 00:00:00 2001 +From 3b68d7133cd457b36929735c5cc1b8c6483d930e Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 30/50] openssh-8.0p1-crypto-policies +Subject: [PATCH 28/53] openssh-8.0p1-crypto-policies --- ssh_config.5 | 164 ++++++++++++++++++++------------------------- @@ -9,7 +9,7 @@ Subject: [PATCH 30/50] openssh-8.0p1-crypto-policies 2 files changed, 140 insertions(+), 203 deletions(-) diff --git a/ssh_config.5 b/ssh_config.5 -index 8d5d0722..a43b2a27 100644 +index 8d5d07222..a43b2a276 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -438,17 +438,13 @@ A single argument of @@ -323,7 +323,7 @@ index 8d5d0722..a43b2a27 100644 .An -nosplit OpenSSH is a derivative of the original and free diff --git a/sshd_config.5 b/sshd_config.5 -index 26fcdc84..583a01cd 100644 +index 26fcdc840..583a01cdb 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -379,17 +379,13 @@ If the argument is @@ -650,5 +650,5 @@ index 26fcdc84..583a01cd 100644 .An -nosplit OpenSSH is a derivative of the original and free -- -2.49.0 +2.52.0 diff --git a/0031-openssh-8.0p1-openssl-kdf.patch b/0029-openssh-8.0p1-openssl-kdf.patch similarity index 95% rename from 0031-openssh-8.0p1-openssl-kdf.patch rename to 0029-openssh-8.0p1-openssl-kdf.patch index 529940f..9c7c06b 100644 --- a/0031-openssh-8.0p1-openssl-kdf.patch +++ b/0029-openssh-8.0p1-openssl-kdf.patch @@ -1,7 +1,7 @@ -From 430bd33963725beb8ec01a1e581529ae6bf6bec0 Mon Sep 17 00:00:00 2001 +From e3fe562a76da5fed5dd7eaacd5645fd3afe972d3 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 31/50] openssh-8.0p1-openssl-kdf +Subject: [PATCH 29/53] openssh-8.0p1-openssl-kdf --- configure.ac | 1 + @@ -9,7 +9,7 @@ Subject: [PATCH 31/50] openssh-8.0p1-openssl-kdf 2 files changed, 108 insertions(+) diff --git a/configure.ac b/configure.ac -index d9bd2f51..d92a8580 100644 +index d9bd2f516..d92a85809 100644 --- a/configure.ac +++ b/configure.ac @@ -3137,6 +3137,7 @@ if test "x$openssl" = "xyes" ; then @@ -21,7 +21,7 @@ index d9bd2f51..d92a8580 100644 # OpenSSL_add_all_algorithms may be a macro. diff --git a/kex.c b/kex.c -index 19a56e8e..8b200ff4 100644 +index 19a56e8e9..8b200ff4a 100644 --- a/kex.c +++ b/kex.c @@ -40,6 +40,11 @@ @@ -153,5 +153,5 @@ index 19a56e8e..8b200ff4 100644 #define NKEYS 6 int -- -2.49.0 +2.52.0 diff --git a/0032-openssh-8.2p1-visibility.patch b/0030-openssh-8.2p1-visibility.patch similarity index 90% rename from 0032-openssh-8.2p1-visibility.patch rename to 0030-openssh-8.2p1-visibility.patch index c67373c..0bd9496 100644 --- a/0032-openssh-8.2p1-visibility.patch +++ b/0030-openssh-8.2p1-visibility.patch @@ -1,14 +1,14 @@ -From 6aa231d9acfeca870ee87e3bf9c4a1239518706d Mon Sep 17 00:00:00 2001 +From 4fddbc429e679944b5f3bf93d5ba46d198bc868f Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 32/50] openssh-8.2p1-visibility +Subject: [PATCH 30/53] openssh-8.2p1-visibility --- regress/misc/sk-dummy/sk-dummy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c -index 347b2122..344f8a8a 100644 +index 347b21227..344f8a8aa 100644 --- a/regress/misc/sk-dummy/sk-dummy.c +++ b/regress/misc/sk-dummy/sk-dummy.c @@ -81,7 +81,7 @@ skdebug(const char *func, const char *fmt, ...) @@ -48,5 +48,5 @@ index 347b2122..344f8a8a 100644 struct sk_resident_key ***rks, size_t *nrks) { -- -2.49.0 +2.52.0 diff --git a/0033-openssh-8.2p1-x11-without-ipv6.patch b/0031-openssh-8.2p1-x11-without-ipv6.patch similarity index 82% rename from 0033-openssh-8.2p1-x11-without-ipv6.patch rename to 0031-openssh-8.2p1-x11-without-ipv6.patch index 32a9056..1f2d8b7 100644 --- a/0033-openssh-8.2p1-x11-without-ipv6.patch +++ b/0031-openssh-8.2p1-x11-without-ipv6.patch @@ -1,14 +1,14 @@ -From cfe5a99d335eb57b8c08b4eb6b4535dd042d96e3 Mon Sep 17 00:00:00 2001 +From ee828e7c70d4bc7e3414703937317f208833ff0e Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 33/50] openssh-8.2p1-x11-without-ipv6 +Subject: [PATCH 31/53] openssh-8.2p1-x11-without-ipv6 --- channels.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/channels.c b/channels.c -index 7438c1a5..95836d50 100644 +index 7438c1a58..95836d508 100644 --- a/channels.c +++ b/channels.c @@ -5055,6 +5055,16 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, @@ -29,5 +29,5 @@ index 7438c1a5..95836d50 100644 close(socks[n]); num_socks = 0; -- -2.49.0 +2.52.0 diff --git a/0034-openssh-8.0p1-preserve-pam-errors.patch b/0032-openssh-8.0p1-preserve-pam-errors.patch similarity index 90% rename from 0034-openssh-8.0p1-preserve-pam-errors.patch rename to 0032-openssh-8.0p1-preserve-pam-errors.patch index 15e59c2..92777ce 100644 --- a/0034-openssh-8.0p1-preserve-pam-errors.patch +++ b/0032-openssh-8.0p1-preserve-pam-errors.patch @@ -1,14 +1,14 @@ -From 8de0391e3b3eb75e23ee9f173f04a9c78f2b96c9 Mon Sep 17 00:00:00 2001 +From 1aa49503ccce2e6390d9e7effacbaf695fa17e00 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 34/50] openssh-8.0p1-preserve-pam-errors +Subject: [PATCH 32/53] openssh-8.0p1-preserve-pam-errors --- auth-pam.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/auth-pam.c b/auth-pam.c -index b4100ea1..a042c3c8 100644 +index b4100ea1c..a042c3c8e 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -523,7 +523,11 @@ sshpam_thread(void *ctxtp) @@ -52,5 +52,5 @@ index b4100ea1..a042c3c8 100644 sshpam_set_maxtries_reached(1); /* FALLTHROUGH */ -- -2.49.0 +2.52.0 diff --git a/0035-openssh-8.7p1-scp-kill-switch.patch b/0033-openssh-8.7p1-scp-kill-switch.patch similarity index 86% rename from 0035-openssh-8.7p1-scp-kill-switch.patch rename to 0033-openssh-8.7p1-scp-kill-switch.patch index 58a5036..440eb3e 100644 --- a/0035-openssh-8.7p1-scp-kill-switch.patch +++ b/0033-openssh-8.7p1-scp-kill-switch.patch @@ -1,7 +1,7 @@ -From a68f3741fdc01bf6823a69d2442caba7de9835f9 Mon Sep 17 00:00:00 2001 +From 687b69ae7e5a503afa0dd4341ff4fb954daf7ccd Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 35/50] openssh-8.7p1-scp-kill-switch +Subject: [PATCH 33/53] openssh-8.7p1-scp-kill-switch --- pathnames.h | 1 + @@ -10,7 +10,7 @@ Subject: [PATCH 35/50] openssh-8.7p1-scp-kill-switch 3 files changed, 16 insertions(+) diff --git a/pathnames.h b/pathnames.h -index 1158bec9..43f0c570 100644 +index 1158bec96..43f0c5708 100644 --- a/pathnames.h +++ b/pathnames.h @@ -42,6 +42,7 @@ @@ -22,7 +22,7 @@ index 1158bec9..43f0c570 100644 #ifndef _PATH_SSH_PROGRAM #define _PATH_SSH_PROGRAM "/usr/bin/ssh" diff --git a/scp.1 b/scp.1 -index aa2e2d8b..373d7237 100644 +index aa2e2d8b5..373d72379 100644 --- a/scp.1 +++ b/scp.1 @@ -331,6 +331,13 @@ during download or upload. @@ -40,7 +40,7 @@ index aa2e2d8b..373d7237 100644 .Ex -std scp .Sh SEE ALSO diff --git a/scp.c b/scp.c -index 7f9795a5..7ed1a54c 100644 +index 7f9795a57..7ed1a54c9 100644 --- a/scp.c +++ b/scp.c @@ -649,6 +649,14 @@ main(int argc, char **argv) @@ -59,5 +59,5 @@ index 7f9795a5..7ed1a54c 100644 fatal("unknown user %u", (u_int) userid); -- -2.49.0 +2.52.0 diff --git a/0036-openssh-8.7p1-recursive-scp.patch b/0034-openssh-8.7p1-recursive-scp.patch similarity index 96% rename from 0036-openssh-8.7p1-recursive-scp.patch rename to 0034-openssh-8.7p1-recursive-scp.patch index 929b408..4ca409a 100644 --- a/0036-openssh-8.7p1-recursive-scp.patch +++ b/0034-openssh-8.7p1-recursive-scp.patch @@ -1,7 +1,7 @@ -From 99e1e3af524376788e591ca73387f1ca37e6f5ef Mon Sep 17 00:00:00 2001 +From fa0cc1c401f634af14cd46eb376bd4a59e8f00f7 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 36/50] openssh-8.7p1-recursive-scp +Subject: [PATCH 34/53] openssh-8.7p1-recursive-scp --- scp.c | 2 +- @@ -11,7 +11,7 @@ Subject: [PATCH 36/50] openssh-8.7p1-recursive-scp 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/scp.c b/scp.c -index 7ed1a54c..0c87dd0e 100644 +index 7ed1a54c9..0c87dd0e1 100644 --- a/scp.c +++ b/scp.c @@ -1388,7 +1388,7 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) @@ -24,7 +24,7 @@ index 7ed1a54c..0c87dd0e 100644 errs = 1; } diff --git a/sftp-client.c b/sftp-client.c -index 9f8ab4af..873dec04 100644 +index 9f8ab4afa..873dec04f 100644 --- a/sftp-client.c +++ b/sftp-client.c @@ -1003,7 +1003,7 @@ sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, @@ -143,7 +143,7 @@ index 9f8ab4af..873dec04 100644 from_path); return -1; diff --git a/sftp-client.h b/sftp-client.h -index 74cdae7d..00ed6630 100644 +index 74cdae7dc..00ed6630c 100644 --- a/sftp-client.h +++ b/sftp-client.h @@ -111,7 +111,7 @@ int sftp_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); @@ -165,7 +165,7 @@ index 74cdae7d..00ed6630 100644 /* * Download a 'from_path' from the 'from' connection and upload it to diff --git a/sftp.c b/sftp.c -index bdedd141..322e6d1f 100644 +index bdedd1416..322e6d1f4 100644 --- a/sftp.c +++ b/sftp.c @@ -809,7 +809,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, @@ -196,5 +196,5 @@ index bdedd141..322e6d1f 100644 startdir = xstrdup(remote_path); -- -2.49.0 +2.52.0 diff --git a/0037-openssh-8.7p1-minrsabits.patch b/0035-openssh-8.7p1-minrsabits.patch similarity index 86% rename from 0037-openssh-8.7p1-minrsabits.patch rename to 0035-openssh-8.7p1-minrsabits.patch index 59e530b..264be9e 100644 --- a/0037-openssh-8.7p1-minrsabits.patch +++ b/0035-openssh-8.7p1-minrsabits.patch @@ -1,7 +1,7 @@ -From 286bc4a302b5130f732c857095ae665f7bea01dd Mon Sep 17 00:00:00 2001 +From abf2f2c00cb708920e87f1a4f63490f812d00cf9 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 37/50] openssh-8.7p1-minrsabits +Subject: [PATCH 35/53] openssh-8.7p1-minrsabits --- readconf.c | 1 + @@ -9,7 +9,7 @@ Subject: [PATCH 37/50] openssh-8.7p1-minrsabits 2 files changed, 2 insertions(+) diff --git a/readconf.c b/readconf.c -index 6c04ed43..f340bf50 100644 +index 6c04ed43c..f340bf501 100644 --- a/readconf.c +++ b/readconf.c @@ -343,6 +343,7 @@ static struct { @@ -21,7 +21,7 @@ index 6c04ed43..f340bf50 100644 { "obscurekeystroketiming", oObscureKeystrokeTiming }, { "channeltimeout", oChannelTimeout }, diff --git a/servconf.c b/servconf.c -index 15c99b30..84891544 100644 +index 15c99b303..84891544b 100644 --- a/servconf.c +++ b/servconf.c @@ -788,6 +788,7 @@ static struct { @@ -33,5 +33,5 @@ index 15c99b30..84891544 100644 { "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL }, { "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL }, -- -2.49.0 +2.52.0 diff --git a/0038-openssh-8.7p1-ibmca.patch b/0036-openssh-8.7p1-ibmca.patch similarity index 79% rename from 0038-openssh-8.7p1-ibmca.patch rename to 0036-openssh-8.7p1-ibmca.patch index 74dd5b5..42e1bdd 100644 --- a/0038-openssh-8.7p1-ibmca.patch +++ b/0036-openssh-8.7p1-ibmca.patch @@ -1,14 +1,14 @@ -From 26af04432f6404eb03780265a5cce948ecfec8dc Mon Sep 17 00:00:00 2001 +From fd2a2cae9a672b8a255566a19e0be6c8d21f363b Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 38/50] openssh-8.7p1-ibmca +Subject: [PATCH 36/53] openssh-8.7p1-ibmca --- openbsd-compat/bsd-closefrom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c -index f6112458..417c2048 100644 +index f61124585..417c20484 100644 --- a/openbsd-compat/bsd-closefrom.c +++ b/openbsd-compat/bsd-closefrom.c @@ -16,7 +16,7 @@ @@ -21,5 +21,5 @@ index f6112458..417c2048 100644 #include #include -- -2.49.0 +2.52.0 diff --git a/0039-openssh-7.6p1-audit.patch b/0037-openssh-7.6p1-audit.patch similarity index 97% rename from 0039-openssh-7.6p1-audit.patch rename to 0037-openssh-7.6p1-audit.patch index e4f89c7..308a200 100644 --- a/0039-openssh-7.6p1-audit.patch +++ b/0037-openssh-7.6p1-audit.patch @@ -1,7 +1,7 @@ -From b0505837bfa2dcdf07800634fa80c5cdb78799dc Mon Sep 17 00:00:00 2001 +From 0a1cf7de02296d921d1ef32b0b0af0534f3b4306 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 39/50] openssh-7.6p1-audit +Subject: [PATCH 37/53] openssh-7.6p1-audit --- Makefile.in | 2 +- @@ -35,7 +35,7 @@ Subject: [PATCH 39/50] openssh-7.6p1-audit create mode 100644 auditstub.c diff --git a/Makefile.in b/Makefile.in -index 6c417ef7..a2942392 100644 +index 6c417ef7c..a2942392e 100644 --- a/Makefile.in +++ b/Makefile.in @@ -119,7 +119,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ @@ -48,7 +48,7 @@ index 6c417ef7..a2942392 100644 SKOBJS= ssh-sk-client.o diff --git a/audit-bsm.c b/audit-bsm.c -index ccfcf6f7..a49abb92 100644 +index ccfcf6f7f..a49abb929 100644 --- a/audit-bsm.c +++ b/audit-bsm.c @@ -373,12 +373,25 @@ audit_connection_from(const char *host, int port) @@ -121,7 +121,7 @@ index ccfcf6f7..a49abb92 100644 +} #endif /* BSM */ diff --git a/audit-linux.c b/audit-linux.c -index 3fcbe5c5..d484b82b 100644 +index 3fcbe5c53..d484b82b4 100644 --- a/audit-linux.c +++ b/audit-linux.c @@ -33,27 +33,40 @@ @@ -495,7 +495,7 @@ index 3fcbe5c5..d484b82b 100644 +} #endif /* USE_LINUX_AUDIT */ diff --git a/audit.c b/audit.c -index dd2f0355..d0433c3a 100644 +index dd2f03558..d0433c3a0 100644 --- a/audit.c +++ b/audit.c @@ -34,6 +34,12 @@ @@ -676,7 +676,7 @@ index dd2f0355..d0433c3a 100644 # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ #endif /* SSH_AUDIT_EVENTS */ diff --git a/audit.h b/audit.h -index 38cb5ad3..45d66ccf 100644 +index 38cb5ad31..45d66ccff 100644 --- a/audit.h +++ b/audit.h @@ -26,6 +26,7 @@ @@ -723,7 +723,7 @@ index 38cb5ad3..45d66ccf 100644 #endif /* _SSH_AUDIT_H */ diff --git a/auditstub.c b/auditstub.c new file mode 100644 -index 00000000..639a798d +index 000000000..639a798df --- /dev/null +++ b/auditstub.c @@ -0,0 +1,52 @@ @@ -780,7 +780,7 @@ index 00000000..639a798d +{ +} diff --git a/auth.c b/auth.c -index e4578169..e10e804f 100644 +index e4578169b..e10e804f3 100644 --- a/auth.c +++ b/auth.c @@ -501,9 +501,6 @@ getpwnamallow(struct ssh *ssh, const char *user) @@ -794,7 +794,7 @@ index e4578169..e10e804f 100644 } if (!allowed_user(ssh, pw)) diff --git a/auth.h b/auth.h -index 39163035..6be52d70 100644 +index 391630350..6be52d70b 100644 --- a/auth.h +++ b/auth.h @@ -215,6 +215,8 @@ struct sshkey *get_hostkey_private_by_type(int, int, struct ssh *); @@ -816,7 +816,7 @@ index 39163035..6be52d70 100644 FILE *auth_openprincipals(const char *, struct passwd *, int); diff --git a/auth2-hostbased.c b/auth2-hostbased.c -index a3be6e49..8cebaffd 100644 +index a3be6e497..8cebaffd9 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -157,7 +157,7 @@ userauth_hostbased(struct ssh *ssh, const char *method) @@ -850,7 +850,7 @@ index a3be6e49..8cebaffd 100644 int hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index 0d5ae0df..99cb810f 100644 +index 0d5ae0df7..99cb810f4 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c @@ -235,7 +235,7 @@ userauth_pubkey(struct ssh *ssh, const char *method) @@ -884,7 +884,7 @@ index 0d5ae0df..99cb810f 100644 match_principals_file(struct passwd *pw, char *file, struct sshkey_cert *cert, struct sshauthopt **authoptsp) diff --git a/auth2.c b/auth2.c -index 8ec41de2..4a8515ea 100644 +index 8ec41de23..4a8515eaf 100644 --- a/auth2.c +++ b/auth2.c @@ -310,9 +310,6 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) @@ -898,7 +898,7 @@ index 8ec41de2..4a8515ea 100644 #ifdef USE_PAM if (options.use_pam) diff --git a/cipher.c b/cipher.c -index 8a18da2d..57d55325 100644 +index 8a18da2df..57d553255 100644 --- a/cipher.c +++ b/cipher.c @@ -64,25 +64,6 @@ struct sshcipher_ctx { @@ -937,7 +937,7 @@ index 8a18da2d..57d55325 100644 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { chachapoly_free(cc->cp_ctx); diff --git a/cipher.h b/cipher.h -index 6533ff2b..2e05a021 100644 +index 6533ff2bb..2e05a0210 100644 --- a/cipher.h +++ b/cipher.h @@ -47,7 +47,25 @@ @@ -968,7 +968,7 @@ index 6533ff2b..2e05a021 100644 const struct sshcipher *cipher_by_name(const char *); diff --git a/kex.c b/kex.c -index 8b200ff4..62f607d6 100644 +index 8b200ff4a..62f607d6f 100644 --- a/kex.c +++ b/kex.c @@ -68,6 +68,7 @@ @@ -1098,7 +1098,7 @@ index 8b200ff4..62f607d6 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 0e080ea3..6a55aadf 100644 +index 0e080ea38..6a55aadf4 100644 --- a/kex.h +++ b/kex.h @@ -255,6 +255,8 @@ int kexgss_client(struct ssh *); @@ -1111,7 +1111,7 @@ index 0e080ea3..6a55aadf 100644 int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); diff --git a/mac.c b/mac.c -index f3dda669..bf051baa 100644 +index f3dda6692..bf051baa1 100644 --- a/mac.c +++ b/mac.c @@ -239,6 +239,20 @@ mac_clear(struct sshmac *mac) @@ -1136,7 +1136,7 @@ index f3dda669..bf051baa 100644 #define MAC_SEP "," int diff --git a/mac.h b/mac.h -index 0b119d7a..5fb593b9 100644 +index 0b119d7a1..5fb593b9e 100644 --- a/mac.h +++ b/mac.h @@ -49,5 +49,6 @@ int mac_compute(struct sshmac *, u_int32_t, const u_char *, int, @@ -1147,7 +1147,7 @@ index 0b119d7a..5fb593b9 100644 #endif /* SSHMAC_H */ diff --git a/monitor.c b/monitor.c -index 43c10a4e..fbc35782 100644 +index 43c10a4ec..fbc357825 100644 --- a/monitor.c +++ b/monitor.c @@ -93,6 +93,7 @@ @@ -1481,7 +1481,7 @@ index 43c10a4e..fbc35782 100644 +} +#endif /* SSH_AUDIT_EVENTS */ diff --git a/monitor.h b/monitor.h -index d4d631dd..2c64f07d 100644 +index d4d631ddc..2c64f07dc 100644 --- a/monitor.h +++ b/monitor.h @@ -66,7 +66,13 @@ enum monitor_reqtype { @@ -1500,7 +1500,7 @@ index d4d631dd..2c64f07d 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 b6e3b3f3..1a079c15 100644 +index b6e3b3f39..1a079c15d 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -567,7 +567,7 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, @@ -1676,7 +1676,7 @@ index b6e3b3f3..1a079c15 100644 +} +#endif /* SSH_AUDIT_EVENTS */ diff --git a/monitor_wrap.h b/monitor_wrap.h -index 672dce52..661ed63b 100644 +index 672dce525..661ed63be 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -58,7 +58,9 @@ int mm_user_key_allowed(struct ssh *ssh, struct passwd *, struct sshkey *, int, @@ -1705,7 +1705,7 @@ index 672dce52..661ed63b 100644 struct Session; diff --git a/packet.c b/packet.c -index 9dea2cfc..344b5f54 100644 +index 9dea2cfc5..344b5f54e 100644 --- a/packet.c +++ b/packet.c @@ -81,6 +81,7 @@ @@ -1859,7 +1859,7 @@ index 9dea2cfc..344b5f54 100644 static int ssh_packet_set_postauth(struct ssh *ssh) diff --git a/packet.h b/packet.h -index 49bb87f0..44a39a9e 100644 +index 49bb87f07..44a39a9e9 100644 --- a/packet.h +++ b/packet.h @@ -223,4 +223,5 @@ const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); @@ -1869,7 +1869,7 @@ index 49bb87f0..44a39a9e 100644 +void packet_destroy_all(struct ssh *, int, int); #endif /* PACKET_H */ diff --git a/session.c b/session.c -index 28bbb8a7..83fc9418 100644 +index d7f05848e..e204a06dd 100644 --- a/session.c +++ b/session.c @@ -145,7 +145,7 @@ extern char *__progname; @@ -1918,7 +1918,7 @@ index 28bbb8a7..83fc9418 100644 #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); -@@ -1538,7 +1550,11 @@ do_child(struct ssh *ssh, Session *s, const char *command) +@@ -1533,7 +1545,11 @@ do_child(struct ssh *ssh, Session *s, const char *command) sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); /* remove keys from memory */ @@ -1930,7 +1930,7 @@ index 28bbb8a7..83fc9418 100644 /* Force a password change */ if (s->authctxt->force_pwchange) { -@@ -1750,6 +1766,9 @@ session_unused(int id) +@@ -1748,6 +1764,9 @@ session_unused(int id) sessions[id].ttyfd = -1; sessions[id].ptymaster = -1; sessions[id].x11_chanids = NULL; @@ -1940,7 +1940,7 @@ index 28bbb8a7..83fc9418 100644 sessions[id].next_unused = sessions_first_unused; sessions_first_unused = id; } -@@ -1828,6 +1847,19 @@ session_open(Authctxt *authctxt, int chanid) +@@ -1826,6 +1845,19 @@ session_open(Authctxt *authctxt, int chanid) return 1; } @@ -1960,7 +1960,7 @@ index 28bbb8a7..83fc9418 100644 Session * session_by_tty(char *tty) { -@@ -2445,6 +2477,32 @@ session_exit_message(struct ssh *ssh, Session *s, int status) +@@ -2443,6 +2475,32 @@ session_exit_message(struct ssh *ssh, Session *s, int status) chan_write_failed(ssh, c); } @@ -1993,7 +1993,7 @@ index 28bbb8a7..83fc9418 100644 void session_close(struct ssh *ssh, Session *s) { -@@ -2458,6 +2516,10 @@ session_close(struct ssh *ssh, Session *s) +@@ -2456,6 +2514,10 @@ session_close(struct ssh *ssh, Session *s) if (s->ttyfd != -1) session_pty_cleanup(s); @@ -2004,7 +2004,7 @@ index 28bbb8a7..83fc9418 100644 free(s->term); free(s->display); free(s->x11_chanids); -@@ -2534,14 +2596,14 @@ session_close_by_channel(struct ssh *ssh, int id, int force, void *arg) +@@ -2532,14 +2594,14 @@ session_close_by_channel(struct ssh *ssh, int id, int force, void *arg) } void @@ -2021,7 +2021,7 @@ index 28bbb8a7..83fc9418 100644 else session_close(ssh, s); } -@@ -2668,6 +2730,15 @@ do_authenticated2(struct ssh *ssh, Authctxt *authctxt) +@@ -2666,6 +2728,15 @@ do_authenticated2(struct ssh *ssh, Authctxt *authctxt) server_loop2(ssh, authctxt); } @@ -2037,7 +2037,7 @@ index 28bbb8a7..83fc9418 100644 void do_cleanup(struct ssh *ssh, Authctxt *authctxt) { -@@ -2731,7 +2802,7 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +@@ -2729,7 +2800,7 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) * or if running in monitor. */ if (mm_is_monitor()) @@ -2047,7 +2047,7 @@ index 28bbb8a7..83fc9418 100644 /* Return a name for the remote host that fits inside utmp_size */ diff --git a/session.h b/session.h -index 344a1ddf..a41c6efc 100644 +index 344a1ddf9..a41c6efcd 100644 --- a/session.h +++ b/session.h @@ -61,6 +61,12 @@ struct Session { @@ -2078,7 +2078,7 @@ index 344a1ddf..a41c6efc 100644 void session_close(struct ssh *, Session *); void do_setusercontext(struct passwd *); diff --git a/sshd-session.c b/sshd-session.c -index 81d30152..a808ac9a 100644 +index e86acf704..5eae9aed7 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -194,8 +194,8 @@ struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); @@ -2264,7 +2264,7 @@ index 81d30152..a808ac9a 100644 #endif /* Override default fatal exit value when auth was attempted */ diff --git a/sshd.c b/sshd.c -index c9ea8e38..8a99f0b2 100644 +index c9ea8e385..8a99f0b29 100644 --- a/sshd.c +++ b/sshd.c @@ -217,6 +217,15 @@ close_listen_socks(void) @@ -2292,5 +2292,5 @@ index c9ea8e38..8a99f0b2 100644 if (options.pid_file != NULL) unlink(options.pid_file); -- -2.49.0 +2.52.0 diff --git a/0040-openssh-7.1p2-audit-race-condition.patch b/0038-openssh-7.1p2-audit-race-condition.patch similarity index 94% rename from 0040-openssh-7.1p2-audit-race-condition.patch rename to 0038-openssh-7.1p2-audit-race-condition.patch index fe732a6..f7d64ba 100644 --- a/0040-openssh-7.1p2-audit-race-condition.patch +++ b/0038-openssh-7.1p2-audit-race-condition.patch @@ -1,7 +1,7 @@ -From c288d4a26ad44dc481c9d18d2920c9d70474833c Mon Sep 17 00:00:00 2001 +From 4c8dfc9481ad2ed6dced8fd91b939de64e0b539b Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 40/50] openssh-7.1p2-audit-race-condition +Subject: [PATCH 38/53] openssh-7.1p2-audit-race-condition --- monitor_wrap.c | 46 +++++++++++++++++++++++++++++++++++++ @@ -10,7 +10,7 @@ Subject: [PATCH 40/50] openssh-7.1p2-audit-race-condition 3 files changed, 102 insertions(+), 7 deletions(-) diff --git a/monitor_wrap.c b/monitor_wrap.c -index 1a079c15..768a59f9 100644 +index 1a079c15d..768a59f95 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c @@ -1415,4 +1415,50 @@ mm_audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_ @@ -65,7 +65,7 @@ index 1a079c15..768a59f9 100644 +} #endif /* SSH_AUDIT_EVENTS */ diff --git a/monitor_wrap.h b/monitor_wrap.h -index 661ed63b..e957ba6e 100644 +index 661ed63be..e957ba6ea 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h @@ -93,6 +93,8 @@ void mm_audit_unsupported_body(struct ssh *, int); @@ -78,7 +78,7 @@ index 661ed63b..e957ba6e 100644 struct Session; diff --git a/session.c b/session.c -index 83fc9418..b4753d93 100644 +index e204a06dd..ef7f43899 100644 --- a/session.c +++ b/session.c @@ -167,6 +167,10 @@ static Session *sessions = NULL; @@ -150,7 +150,7 @@ index 83fc9418..b4753d93 100644 return ret; } -@@ -1532,6 +1559,33 @@ child_close_fds(struct ssh *ssh) +@@ -1527,6 +1554,33 @@ child_close_fds(struct ssh *ssh) log_redirect_stderr_to(NULL); } @@ -184,7 +184,7 @@ index 83fc9418..b4753d93 100644 /* * Performs common processing for the child, such as setting up the * environment, closing extra file descriptors, setting the user and group -@@ -1549,13 +1603,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) +@@ -1544,13 +1598,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); @@ -199,5 +199,5 @@ index 83fc9418..b4753d93 100644 if (s->authctxt->force_pwchange) { do_setusercontext(pw); -- -2.49.0 +2.52.0 diff --git a/0041-openssh-9.0p1-audit-log.patch b/0039-openssh-9.0p1-audit-log.patch similarity index 97% rename from 0041-openssh-9.0p1-audit-log.patch rename to 0039-openssh-9.0p1-audit-log.patch index e04f31b..b72fbea 100644 --- a/0041-openssh-9.0p1-audit-log.patch +++ b/0039-openssh-9.0p1-audit-log.patch @@ -1,7 +1,7 @@ -From 80d967a18261156573e7385f8e534a89d2767d67 Mon Sep 17 00:00:00 2001 +From fef6d48d6886001d384cef33e5ae6e5c278a7127 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 41/50] openssh-9.0p1-audit-log +Subject: [PATCH 39/53] openssh-9.0p1-audit-log --- audit-bsm.c | 2 +- @@ -11,7 +11,7 @@ Subject: [PATCH 41/50] openssh-9.0p1-audit-log 4 files changed, 81 insertions(+), 17 deletions(-) diff --git a/audit-bsm.c b/audit-bsm.c -index a49abb92..c6f56553 100644 +index a49abb929..c6f565532 100644 --- a/audit-bsm.c +++ b/audit-bsm.c @@ -405,7 +405,7 @@ audit_session_close(struct logininfo *li) @@ -24,7 +24,7 @@ index a49abb92..c6f56553 100644 /* not implemented */ } diff --git a/audit-linux.c b/audit-linux.c -index d484b82b..dcfde3a9 100644 +index d484b82b4..dcfde3a92 100644 --- a/audit-linux.c +++ b/audit-linux.c @@ -52,7 +52,7 @@ extern u_int utmp_len; @@ -217,7 +217,7 @@ index d484b82b..dcfde3a9 100644 void diff --git a/audit.c b/audit.c -index d0433c3a..28d51a14 100644 +index d0433c3a0..28d51a146 100644 --- a/audit.c +++ b/audit.c @@ -116,12 +116,22 @@ audit_event_lookup(ssh_audit_event_t ev) @@ -248,7 +248,7 @@ index d0433c3a..28d51a14 100644 void diff --git a/audit.h b/audit.h -index 45d66ccf..05ac132c 100644 +index 45d66ccff..05ac132cf 100644 --- a/audit.h +++ b/audit.h @@ -64,7 +64,7 @@ void audit_session_close(struct logininfo *); @@ -261,5 +261,5 @@ index 45d66ccf..05ac132c 100644 void audit_unsupported(struct ssh *, int); void audit_kex(struct ssh *, int, char *, char *, char *, char *); -- -2.49.0 +2.52.0 diff --git a/0042-openssh-7.7p1-fips.patch b/0040-openssh-7.7p1-fips.patch similarity index 99% rename from 0042-openssh-7.7p1-fips.patch rename to 0040-openssh-7.7p1-fips.patch index 54997e3..36e9f48 100644 --- a/0042-openssh-7.7p1-fips.patch +++ b/0040-openssh-7.7p1-fips.patch @@ -1,7 +1,7 @@ -From 79f9b2763d85ec592cb7e54dcf1c695d8dd138b1 Mon Sep 17 00:00:00 2001 +From 8b15e752713a43b5f745f1aff908a621ae64a958 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 28 Aug 2025 14:01:38 +0200 -Subject: [PATCH 42/54] openssh-7.7p1-fips +Subject: [PATCH 40/53] openssh-7.7p1-fips --- dh.c | 41 ++++++++++++++++++++++ @@ -22,7 +22,7 @@ Subject: [PATCH 42/54] openssh-7.7p1-fips sshconnect2.c | 9 ++++- sshd.c | 13 +++++++ sshkey.c | 37 ++++++++++++++++++++ - 19 files changed, 272 insertions(+), 30 deletions(-) + 18 files changed, 271 insertions(+), 30 deletions(-) diff --git a/dh.c b/dh.c index 168dea1dd..8c9a29fa7 100644 @@ -746,5 +746,5 @@ index 4e41a78c7..ca1cdb642 100644 return SSH_ERR_KEY_TYPE_UNKNOWN; return impl->funcs->verify(key, sig, siglen, data, dlen, -- -2.51.0 +2.52.0 diff --git a/0043-openssh-8.7p1-ssh-manpage.patch b/0041-openssh-8.7p1-ssh-manpage.patch similarity index 87% rename from 0043-openssh-8.7p1-ssh-manpage.patch rename to 0041-openssh-8.7p1-ssh-manpage.patch index 89c6ea1..c8e108e 100644 --- a/0043-openssh-8.7p1-ssh-manpage.patch +++ b/0041-openssh-8.7p1-ssh-manpage.patch @@ -1,14 +1,14 @@ -From 299a602802d7c7d121306eb2aeae1502871a35cb Mon Sep 17 00:00:00 2001 +From ed328b6f6d3e88b28934d7d6788f328785be3359 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 43/50] openssh-8.7p1-ssh-manpage +Subject: [PATCH 41/53] openssh-8.7p1-ssh-manpage --- ssh.1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ssh.1 b/ssh.1 -index 6a9fbdc5..755cdef2 100644 +index 6a9fbdc5b..755cdef2b 100644 --- a/ssh.1 +++ b/ssh.1 @@ -510,12 +510,12 @@ For full details of the options listed below, and their possible values, see @@ -43,5 +43,5 @@ index 6a9fbdc5..755cdef2 100644 .It RevokedHostKeys .It SecurityKeyProvider -- -2.49.0 +2.52.0 diff --git a/0044-openssh-8.7p1-negotiate-supported-algs.patch b/0042-openssh-8.7p1-negotiate-supported-algs.patch similarity index 95% rename from 0044-openssh-8.7p1-negotiate-supported-algs.patch rename to 0042-openssh-8.7p1-negotiate-supported-algs.patch index f4c3b8a..6f17b9a 100644 --- a/0044-openssh-8.7p1-negotiate-supported-algs.patch +++ b/0042-openssh-8.7p1-negotiate-supported-algs.patch @@ -1,7 +1,7 @@ -From 5c92430c08ac392b5b2ace899cc043247c923734 Mon Sep 17 00:00:00 2001 +From 028e2f357f3ed905f512dda984055b7db083a790 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 44/50] openssh-8.7p1-negotiate-supported-algs +Subject: [PATCH 42/53] openssh-8.7p1-negotiate-supported-algs --- regress/hostkey-agent.sh | 32 +++++++++++++++++++++++++------- @@ -9,7 +9,7 @@ Subject: [PATCH 44/50] openssh-8.7p1-negotiate-supported-algs 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh -index 28dcfe17..b9e716dc 100644 +index 28dcfe170..b9e716dcd 100644 --- a/regress/hostkey-agent.sh +++ b/regress/hostkey-agent.sh @@ -17,8 +17,21 @@ trace "make CA key" @@ -84,7 +84,7 @@ index 28dcfe17..b9e716dc 100644 opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` diff --git a/sshconnect2.c b/sshconnect2.c -index 14f7671a..ad3f560f 100644 +index 3e02f485d..e7e3da669 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -221,7 +221,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, @@ -129,5 +129,5 @@ index 14f7671a..ad3f560f 100644 /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) -- -2.49.0 +2.52.0 diff --git a/0045-openssh-9.0p1-evp-fips-kex.patch b/0043-openssh-9.0p1-evp-fips-kex.patch similarity index 98% rename from 0045-openssh-9.0p1-evp-fips-kex.patch rename to 0043-openssh-9.0p1-evp-fips-kex.patch index 610cea0..a21e234 100644 --- a/0045-openssh-9.0p1-evp-fips-kex.patch +++ b/0043-openssh-9.0p1-evp-fips-kex.patch @@ -1,7 +1,7 @@ -From be23afbab800c9b5ffea56b3f410a04156c08df2 Mon Sep 17 00:00:00 2001 +From 01f8e0679caa93447159430c1067b29909a7aa94 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 45/50] openssh-9.0p1-evp-fips-kex +Subject: [PATCH 43/53] openssh-9.0p1-evp-fips-kex --- dh.c | 98 +++++++++++++++++++++++++++++++++----- @@ -12,7 +12,7 @@ Subject: [PATCH 45/50] openssh-9.0p1-evp-fips-kex 5 files changed, 382 insertions(+), 42 deletions(-) diff --git a/dh.c b/dh.c -index 8c9a29fa..ea0a0b09 100644 +index 8c9a29fa7..ea0a0b093 100644 --- a/dh.c +++ b/dh.c @@ -37,6 +37,9 @@ @@ -140,7 +140,7 @@ index 8c9a29fa..ea0a0b09 100644 DH * diff --git a/kex.c b/kex.c -index 71fbe5cb..ce6a7b81 100644 +index 71fbe5cbe..ce6a7b818 100644 --- a/kex.c +++ b/kex.c @@ -1614,3 +1614,142 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, @@ -287,7 +287,7 @@ index 71fbe5cb..ce6a7b81 100644 +} +#endif /* WITH_OPENSSL */ diff --git a/kex.h b/kex.h -index 6a55aadf..48f3bb87 100644 +index 6a55aadf4..48f3bb875 100644 --- a/kex.h +++ b/kex.h @@ -37,6 +37,9 @@ @@ -311,7 +311,7 @@ index 6a55aadf..48f3bb87 100644 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(const char *, const u_char *, int); diff --git a/kexdh.c b/kexdh.c -index 0faab21b..32e1de51 100644 +index 0faab21b0..32e1de514 100644 --- a/kexdh.c +++ b/kexdh.c @@ -35,6 +35,10 @@ @@ -404,7 +404,7 @@ index 0faab21b..32e1de51 100644 } diff --git a/kexecdh.c b/kexecdh.c -index efb2e55a..d92ba54f 100644 +index efb2e55a6..d92ba54f8 100644 --- a/kexecdh.c +++ b/kexecdh.c @@ -35,17 +35,57 @@ @@ -612,5 +612,5 @@ index efb2e55a..d92ba54f 100644 return r; } -- -2.49.0 +2.52.0 diff --git a/0046-openssh-8.7p1-nohostsha1proof.patch b/0044-openssh-8.7p1-nohostsha1proof.patch similarity index 95% rename from 0046-openssh-8.7p1-nohostsha1proof.patch rename to 0044-openssh-8.7p1-nohostsha1proof.patch index 9e75c8a..8da1b2b 100644 --- a/0046-openssh-8.7p1-nohostsha1proof.patch +++ b/0044-openssh-8.7p1-nohostsha1proof.patch @@ -1,7 +1,7 @@ -From e4ca3b9dba1cc832a9974493c91207d42e218a68 Mon Sep 17 00:00:00 2001 +From 80160fc4e11c894ca0bbf5fe51254933190cfb90 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 46/50] openssh-8.7p1-nohostsha1proof +Subject: [PATCH 44/53] openssh-8.7p1-nohostsha1proof --- compat.c | 6 +++++ @@ -18,7 +18,7 @@ Subject: [PATCH 46/50] openssh-8.7p1-nohostsha1proof 11 files changed, 90 insertions(+), 24 deletions(-) diff --git a/compat.c b/compat.c -index b59f0bfc..4e611dc3 100644 +index b59f0bfc0..4e611dc39 100644 --- a/compat.c +++ b/compat.c @@ -42,6 +42,7 @@ void @@ -52,7 +52,7 @@ index b59f0bfc..4e611dc3 100644 /* Always returns pointer to allocated memory, caller must free. */ diff --git a/compat.h b/compat.h -index 1a19060f..2e6db5bf 100644 +index 1a19060fc..2e6db5bf9 100644 --- a/compat.h +++ b/compat.h @@ -30,7 +30,7 @@ @@ -65,7 +65,7 @@ index 1a19060f..2e6db5bf 100644 /* #define unused 0x00000020 */ #define SSH_BUG_DEBUG 0x00000040 diff --git a/monitor.c b/monitor.c -index fbc35782..19cb058e 100644 +index fbc357825..19cb058ee 100644 --- a/monitor.c +++ b/monitor.c @@ -747,11 +747,12 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) @@ -120,7 +120,7 @@ index fbc35782..19cb058e 100644 sshbuf_reset(m); diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c -index caf8f57f..09016aea 100644 +index caf8f57f7..09016aead 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c @@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype, int bits) @@ -134,7 +134,7 @@ index caf8f57f..09016aea 100644 kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c -index 3babe604..cc80fe97 100644 +index 3babe604d..cc80fe97c 100644 --- a/regress/unittests/sshkey/test_file.c +++ b/regress/unittests/sshkey/test_file.c @@ -109,6 +109,7 @@ sshkey_file_tests(void) @@ -155,7 +155,7 @@ index 3babe604..cc80fe97 100644 TEST_START("load RSA cert with SHA512 signature"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0); diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c -index 0aff7c9b..951122e1 100644 +index 0aff7c9bf..951122e1a 100644 --- a/regress/unittests/sshkey/test_fuzz.c +++ b/regress/unittests/sshkey/test_fuzz.c @@ -338,13 +338,14 @@ sshkey_fuzz_tests(void) @@ -175,7 +175,7 @@ index 0aff7c9b..951122e1 100644 TEST_START("fuzz RSA SHA256 sig"); buf = load_file("rsa_1"); diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c -index 5bf4b65c..6d0a35bb 100644 +index 5bf4b65cc..6d0a35bbf 100644 --- a/regress/unittests/sshkey/test_sshkey.c +++ b/regress/unittests/sshkey/test_sshkey.c @@ -61,6 +61,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type, @@ -241,7 +241,7 @@ index 5bf4b65c..6d0a35bb 100644 SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); ASSERT_PTR_EQ(k4, NULL); diff --git a/serverloop.c b/serverloop.c -index 40ddfb04..9c5b1567 100644 +index 40ddfb042..9c5b15678 100644 --- a/serverloop.c +++ b/serverloop.c @@ -80,6 +80,7 @@ @@ -265,7 +265,7 @@ index 40ddfb04..9c5b1567 100644 sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); if ((r = sshbuf_put_cstring(sigbuf, diff --git a/ssh-rsa.c b/ssh-rsa.c -index 6c2f771a..8dd4ab01 100644 +index 6c2f771a3..8dd4ab01e 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c @@ -509,7 +509,8 @@ ssh_rsa_verify(const struct sshkey *key, @@ -279,7 +279,7 @@ index 6c2f771a..8dd4ab01 100644 goto out; } diff --git a/sshconnect2.c b/sshconnect2.c -index ad3f560f..3941e089 100644 +index e7e3da669..5beae1c10 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1434,6 +1434,14 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, @@ -298,7 +298,7 @@ index ad3f560f..3941e089 100644 } diff --git a/sshd-session.c b/sshd-session.c -index a808ac9a..c3349a8a 100644 +index 5eae9aed7..7aa767020 100644 --- a/sshd-session.c +++ b/sshd-session.c @@ -1316,6 +1316,27 @@ main(int ac, char **av) @@ -330,5 +330,5 @@ index a808ac9a..c3349a8a 100644 channel_init_channels(ssh); channel_set_af(ssh, options.address_family); -- -2.49.0 +2.52.0 diff --git a/0047-openssh-9.6p1-pam-rhost.patch b/0045-openssh-9.6p1-pam-rhost.patch similarity index 80% rename from 0047-openssh-9.6p1-pam-rhost.patch rename to 0045-openssh-9.6p1-pam-rhost.patch index 968e60a..690e475 100644 --- a/0047-openssh-9.6p1-pam-rhost.patch +++ b/0045-openssh-9.6p1-pam-rhost.patch @@ -1,14 +1,14 @@ -From 497de886faaddec60b7ad1013396c7d4f3145968 Mon Sep 17 00:00:00 2001 +From 9d41ec0c0d8de6637677c9ab7605c9e1104e5d28 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 47/50] openssh-9.6p1-pam-rhost +Subject: [PATCH 45/53] openssh-9.6p1-pam-rhost --- auth-pam.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/auth-pam.c b/auth-pam.c -index a042c3c8..a321e0d3 100644 +index a042c3c8e..a321e0d3e 100644 --- a/auth-pam.c +++ b/auth-pam.c @@ -741,7 +741,7 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt) @@ -21,5 +21,5 @@ index a042c3c8..a321e0d3 100644 sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, sshpam_rhost); -- -2.49.0 +2.52.0 diff --git a/0048-openssh-9.9p1-separate-keysign.patch b/0046-openssh-9.9p1-separate-keysign.patch similarity index 76% rename from 0048-openssh-9.9p1-separate-keysign.patch rename to 0046-openssh-9.9p1-separate-keysign.patch index 8d0f691..4180959 100644 --- a/0048-openssh-9.9p1-separate-keysign.patch +++ b/0046-openssh-9.9p1-separate-keysign.patch @@ -1,14 +1,14 @@ -From b97b1040bc0918fe9be89cdb482d046270e92d9c Mon Sep 17 00:00:00 2001 +From 4ab4e72b3c16635cde9c03d2d95f3948cb21d445 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 48/50] openssh-9.9p1-separate-keysign +Subject: [PATCH 46/53] openssh-9.9p1-separate-keysign --- ssh_config.5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssh_config.5 b/ssh_config.5 -index a43b2a27..9d5da2a6 100644 +index a43b2a276..9d5da2a68 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -797,7 +797,7 @@ or @@ -21,5 +21,5 @@ index a43b2a27..9d5da2a6 100644 Sets the escape character (default: .Ql ~ ) . -- -2.49.0 +2.52.0 diff --git a/0049-openssh-9.9p1-openssl-mlkem.patch b/0047-openssh-9.9p1-openssl-mlkem.patch similarity index 98% rename from 0049-openssh-9.9p1-openssl-mlkem.patch rename to 0047-openssh-9.9p1-openssl-mlkem.patch index e04d194..bc0b886 100644 --- a/0049-openssh-9.9p1-openssl-mlkem.patch +++ b/0047-openssh-9.9p1-openssl-mlkem.patch @@ -1,7 +1,7 @@ -From 0a621a2ccb8444e4c6da906b0e112e0522658122 Mon Sep 17 00:00:00 2001 +From 793361ec77a36ebf008b595cf5c14ef9df8f22ff Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 49/50] openssh-9.9p1-openssl-mlkem +Subject: [PATCH 47/53] openssh-9.9p1-openssl-mlkem --- kex-names.c | 20 +++ @@ -9,7 +9,7 @@ Subject: [PATCH 49/50] openssh-9.9p1-openssl-mlkem 2 files changed, 311 insertions(+) diff --git a/kex-names.c b/kex-names.c -index cd3902ad..36a953ab 100644 +index cd3902ad2..36a953ab2 100644 --- a/kex-names.c +++ b/kex-names.c @@ -108,6 +108,19 @@ static const struct kexalg gss_kexalgs[] = { @@ -54,7 +54,7 @@ index cd3902ad..36a953ab 100644 if (strcmp(k->name, name) == 0) return k; diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c -index 2b5d3960..670049dc 100644 +index 2b5d39608..670049dcd 100644 --- a/kexmlkem768x25519.c +++ b/kexmlkem768x25519.c @@ -48,10 +48,127 @@ @@ -394,5 +394,5 @@ index 2b5d3960..670049dc 100644 #else /* USE_MLKEM768X25519 */ int -- -2.49.0 +2.52.0 diff --git a/0050-openssh-9.9p2-error_processing.patch b/0048-openssh-9.9p2-error_processing.patch similarity index 77% rename from 0050-openssh-9.9p2-error_processing.patch rename to 0048-openssh-9.9p2-error_processing.patch index aed1c30..cc4c825 100644 --- a/0050-openssh-9.9p2-error_processing.patch +++ b/0048-openssh-9.9p2-error_processing.patch @@ -1,14 +1,14 @@ -From fd32e753ae7f3b314712e6aa8b2bed3c1fca1ef5 Mon Sep 17 00:00:00 2001 +From 444e38f66ef7454f262beed18734b86279fea88f Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 16 May 2025 14:53:54 +0200 -Subject: [PATCH 50/51] openssh-9.9p2-error_processing +Subject: [PATCH 48/53] openssh-9.9p2-error_processing --- ssh-agent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ssh-agent.c b/ssh-agent.c -index 798bf9b6..dfb6ac72 100644 +index 798bf9b60..dfb6ac725 100644 --- a/ssh-agent.c +++ b/ssh-agent.c @@ -1377,6 +1377,8 @@ process_add_identity(SocketEntry *e) @@ -21,5 +21,5 @@ index 798bf9b6..dfb6ac72 100644 goto out; } -- -2.49.0 +2.52.0 diff --git a/0051-Provide-better-error-for-non-supported-private-keys.patch b/0049-Provide-better-error-for-non-supported-private-keys.patch similarity index 81% rename from 0051-Provide-better-error-for-non-supported-private-keys.patch rename to 0049-Provide-better-error-for-non-supported-private-keys.patch index 9c1aa4d..183d9f3 100644 --- a/0051-Provide-better-error-for-non-supported-private-keys.patch +++ b/0049-Provide-better-error-for-non-supported-private-keys.patch @@ -1,7 +1,7 @@ -From 4965cdbc1ee1e6a0c665797bb8b944d96d3d411f Mon Sep 17 00:00:00 2001 +From df9a81d4c07e12c1b2a7dffe5ed9affc228a9842 Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Wed, 16 Apr 2025 15:11:59 +0200 -Subject: [PATCH 51/53] Provide better error for non-supported private keys +Subject: [PATCH 49/53] Provide better error for non-supported private keys Signed-off-by: Zoltan Fridrich --- @@ -23,5 +23,5 @@ index ca1cdb642..aada474e0 100644 } return SSH_ERR_LIBCRYPTO_ERROR; -- -2.49.0 +2.52.0 diff --git a/0052-Ignore-bad-hostkeys-in-known_hosts-file.patch b/0050-Ignore-bad-hostkeys-in-known_hosts-file.patch similarity index 94% rename from 0052-Ignore-bad-hostkeys-in-known_hosts-file.patch rename to 0050-Ignore-bad-hostkeys-in-known_hosts-file.patch index f071225..e2d6178 100644 --- a/0052-Ignore-bad-hostkeys-in-known_hosts-file.patch +++ b/0050-Ignore-bad-hostkeys-in-known_hosts-file.patch @@ -1,7 +1,7 @@ -From 9ed09ef158a113e21be7b3fefa7c5f932632749b Mon Sep 17 00:00:00 2001 +From afcce638f76cfa43d152d4b45e8b986b9de5fab8 Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Mon, 5 May 2025 11:52:25 +0200 -Subject: [PATCH 52/53] Ignore bad hostkeys in known_hosts file +Subject: [PATCH 50/53] Ignore bad hostkeys in known_hosts file Signed-off-by: Zoltan Fridrich --- @@ -82,5 +82,5 @@ index abc8b8439..33787a8d4 100644 fatal("Invalid number of ConnectionAttempts"); -- -2.49.0 +2.52.0 diff --git a/0053-support-authentication-indicators-in-GSSAPI.patch b/0051-support-authentication-indicators-in-GSSAPI.patch similarity index 98% rename from 0053-support-authentication-indicators-in-GSSAPI.patch rename to 0051-support-authentication-indicators-in-GSSAPI.patch index 237e45d..646ce48 100644 --- a/0053-support-authentication-indicators-in-GSSAPI.patch +++ b/0051-support-authentication-indicators-in-GSSAPI.patch @@ -1,7 +1,7 @@ -From 5d5a66e96ad03132f65371070f4fa475f10207d9 Mon Sep 17 00:00:00 2001 +From 06c50491651d0a916c99126228bc5b2f573fa72f Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 10 Jun 2024 23:00:03 +0300 -Subject: [PATCH] support authentication indicators in GSSAPI +Subject: [PATCH 51/53] support authentication indicators in GSSAPI RFC 6680 defines a set of GSSAPI extensions to handle attributes associated with the GSSAPI names. MIT Kerberos and FreeIPA use @@ -285,7 +285,7 @@ index 9d5435eda..5c0491cf1 100644 sizeof(ssh_gssapi_client)); return 0; diff --git a/servconf.c b/servconf.c -index e7e4ad046..aab653244 100644 +index 8b708cbf4..ecf5c66d4 100644 --- a/servconf.c +++ b/servconf.c @@ -147,6 +147,7 @@ initialize_server_options(ServerOptions *options) @@ -337,7 +337,7 @@ index e7e4ad046..aab653244 100644 case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -3351,6 +3363,7 @@ dump_config(ServerOptions *o) +@@ -3350,6 +3362,7 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms); @@ -366,7 +366,7 @@ index 7c7e5d434..7c41df417 100644 M_CP_STRARRAYOPT(allow_users, num_allow_users); \ M_CP_STRARRAYOPT(deny_users, num_deny_users); \ diff --git a/ssh-gss.h b/ssh-gss.h -index a894e23c9..59cf46d47 100644 +index 329dc9da0..1506719a9 100644 --- a/ssh-gss.h +++ b/ssh-gss.h @@ -34,6 +34,12 @@ @@ -382,7 +382,7 @@ index a894e23c9..59cf46d47 100644 #ifdef KRB5 # ifndef HEIMDAL # ifdef HAVE_GSSAPI_GENERIC_H -@@ -107,6 +113,7 @@ typedef struct { +@@ -112,6 +118,7 @@ typedef struct { ssh_gssapi_ccache store; int used; int updated; @@ -446,5 +446,5 @@ index 583a01cdb..90ab87edd 100644 The default is handled system-wide by .Xr crypto-policies 7 . -- -2.49.0 +2.52.0 diff --git a/0054-openssh-10.0-mlkem-nist.patch b/0052-NIST-curves-hybrid-KEX-implementation.patch similarity index 97% rename from 0054-openssh-10.0-mlkem-nist.patch rename to 0052-NIST-curves-hybrid-KEX-implementation.patch index 9c3f105..8edc3ed 100644 --- a/0054-openssh-10.0-mlkem-nist.patch +++ b/0052-NIST-curves-hybrid-KEX-implementation.patch @@ -1,3 +1,23 @@ +From d064766faf7b874e9e3596b85d1d7b374c76cba4 Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Mon, 20 Oct 2025 16:07:31 +0200 +Subject: [PATCH 52/53] NIST curves hybrid KEX implementation + +--- + crypto_api.h | 4 + + kex-names.c | 12 +- + kex.c | 1 + + kex.h | 19 + + kexgen.c | 54 +++ + kexmlkem768x25519.c | 598 +++++++++++++++++++++++++++++-- + monitor.c | 2 + + regress/unittests/kex/test_kex.c | 4 + + ssh-keyscan.c | 2 + + ssh_api.c | 4 + + sshconnect2.c | 2 + + sshd-auth.c | 2 + + 12 files changed, 681 insertions(+), 23 deletions(-) + diff --git a/crypto_api.h b/crypto_api.h index 8bbc3a08a..6940bbf0e 100644 --- a/crypto_api.h @@ -891,7 +911,7 @@ index 670049dcd..463d18771 100644 + #endif /* USE_MLKEM768X25519 */ diff --git a/monitor.c b/monitor.c -index 58fbac9df..75413ce71 100644 +index 19cb058ee..4fe270e86 100644 --- a/monitor.c +++ b/monitor.c @@ -2009,6 +2009,8 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) @@ -974,10 +994,10 @@ index 5beae1c10..6d9f1238b 100644 #if defined(GSSAPI) && defined(WITH_OPENSSL) diff --git a/sshd-auth.c b/sshd-auth.c -index 897db9b43..a1b43ba5a 100644 +index de61be5ac..6b5e20eef 100644 --- a/sshd-auth.c +++ b/sshd-auth.c -@@ -918,6 +918,8 @@ do_ssh2_kex(struct ssh *ssh) +@@ -914,6 +914,8 @@ do_ssh2_kex(struct ssh *ssh) kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; @@ -986,3 +1006,6 @@ index 897db9b43..a1b43ba5a 100644 kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; +-- +2.52.0 + diff --git a/1000-openssh-coverity.patch b/1000-openssh-6.7p1-coverity.patch similarity index 91% rename from 1000-openssh-coverity.patch rename to 1000-openssh-6.7p1-coverity.patch index 88362eb..0cf2c69 100644 --- a/1000-openssh-coverity.patch +++ b/1000-openssh-6.7p1-coverity.patch @@ -1,7 +1,7 @@ -From 24c411970682dc67873c36bac05b4b460d68a628 Mon Sep 17 00:00:00 2001 +From 194961cdbf4f212f9a845dfbf9b02ccbbb67f151 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 50/50] openssh-6.7p1-coverity +Subject: [PATCH 53/53] openssh-6.7p1-coverity --- auth-krb5.c | 2 ++ @@ -20,7 +20,7 @@ Subject: [PATCH 50/50] openssh-6.7p1-coverity 13 files changed, 28 insertions(+), 11 deletions(-) diff --git a/auth-krb5.c b/auth-krb5.c -index bae153c9..209a3265 100644 +index bae153c93..209a32655 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -427,6 +427,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm @@ -40,7 +40,7 @@ index bae153c9..209a3265 100644 } /* make sure the KRB5CCNAME is set for non-standard location */ diff --git a/gss-genr.c b/gss-genr.c -index 3034370c..c357e973 100644 +index 3034370c7..c357e973a 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, @@ -55,7 +55,7 @@ index 3034370c..c357e973 100644 (p = strsep(&cp, ","))) { if (sshbuf_len(buf) != 0 && diff --git a/krl.c b/krl.c -index 0d0f6953..d8517f12 100644 +index 0d0f69534..d8517f124 100644 --- a/krl.c +++ b/krl.c @@ -1202,6 +1202,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) @@ -83,7 +83,7 @@ index 0d0f6953..d8517f12 100644 KRL_DBG(("revoked by explicit key")); return SSH_ERR_KEY_REVOKED; diff --git a/loginrec.c b/loginrec.c -index c4a9bd48..2583612c 100644 +index c4a9bd485..2583612c6 100644 --- a/loginrec.c +++ b/loginrec.c @@ -683,9 +683,11 @@ construct_utmp(struct logininfo *li, @@ -99,7 +99,7 @@ index c4a9bd48..2583612c 100644 MIN_SIZEOF(ut->ut_host, li->hostname)); # endif diff --git a/misc.c b/misc.c -index 09722962..cd71c1b2 100644 +index 097229620..cd71c1b2b 100644 --- a/misc.c +++ b/misc.c @@ -1556,6 +1556,8 @@ sanitise_stdfd(void) @@ -120,7 +120,7 @@ index 09722962..cd71c1b2 100644 } diff --git a/monitor.c b/monitor.c -index 19cb058e..58fbac9d 100644 +index 4fe270e86..75413ce71 100644 --- a/monitor.c +++ b/monitor.c @@ -415,7 +415,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) @@ -142,7 +142,7 @@ index 19cb058e..58fbac9d 100644 error: diff --git a/openbsd-compat/bindresvport.c b/openbsd-compat/bindresvport.c -index 346c7fe5..f42792fd 100644 +index 346c7fe56..f42792fde 100644 --- a/openbsd-compat/bindresvport.c +++ b/openbsd-compat/bindresvport.c @@ -59,7 +59,7 @@ bindresvport_sa(int sd, struct sockaddr *sa) @@ -155,7 +155,7 @@ index 346c7fe5..f42792fd 100644 if (sa == NULL) { diff --git a/openbsd-compat/bsd-pselect.c b/openbsd-compat/bsd-pselect.c -index 26bdc3e0..8e2939b9 100644 +index 26bdc3e08..8e2939b95 100644 --- a/openbsd-compat/bsd-pselect.c +++ b/openbsd-compat/bsd-pselect.c @@ -85,13 +85,13 @@ pselect_notify_setup(void) @@ -186,7 +186,7 @@ index 26bdc3e0..8e2939b9 100644 FD_CLR(notify_pipe[0], readset); } diff --git a/readconf.c b/readconf.c -index ea9d293c..9680c38c 100644 +index ea9d293c3..9680c38c8 100644 --- a/readconf.c +++ b/readconf.c @@ -2164,6 +2164,7 @@ parse_pubkey_algos: @@ -198,10 +198,10 @@ index ea9d293c..9680c38c 100644 } free(arg2); diff --git a/servconf.c b/servconf.c -index 8b708cbf..e7e4ad04 100644 +index ecf5c66d4..aab653244 100644 --- a/servconf.c +++ b/servconf.c -@@ -2293,8 +2293,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -2305,8 +2305,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, if (*activep && *charptr == NULL) { *charptr = tilde_expand_filename(arg, getuid()); /* increase optional counter */ @@ -214,7 +214,7 @@ index 8b708cbf..e7e4ad04 100644 break; diff --git a/serverloop.c b/serverloop.c -index 9c5b1567..768ee9fa 100644 +index 9c5b15678..768ee9fa4 100644 --- a/serverloop.c +++ b/serverloop.c @@ -511,7 +511,7 @@ server_request_tun(struct ssh *ssh) @@ -227,10 +227,10 @@ index 9c5b1567..768ee9fa 100644 auth_opts->force_tun_device != (int)tun) goto done; diff --git a/ssh-agent.c b/ssh-agent.c -index 798bf9b6..0e39dff7 100644 +index dfb6ac725..a17e681e1 100644 --- a/ssh-agent.c +++ b/ssh-agent.c -@@ -1593,6 +1593,7 @@ sanitize_pkcs11_provider(const char *provider) +@@ -1595,6 +1595,7 @@ sanitize_pkcs11_provider(const char *provider) if (pkcs11_uri_parse(provider, uri) != 0) { error("Failed to parse PKCS#11 URI"); @@ -239,7 +239,7 @@ index 798bf9b6..0e39dff7 100644 } /* validate also provider from URI */ diff --git a/ssh-keygen.c b/ssh-keygen.c -index 792aafde..96b3474d 100644 +index 792aafde0..96b3474d6 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c @@ -2424,6 +2424,9 @@ update_krl_from_file(struct passwd *pw, const char *file, int wild_ca, @@ -253,5 +253,5 @@ index 792aafde..96b3474d 100644 if (strncasecmp(cp, "key:", 4) == 0) { cp += 4; -- -2.49.0 +2.52.0 diff --git a/openssh.spec b/openssh.spec index c9600a6..8387ca4 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 8%{?dist} +Release: 9%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -67,125 +67,121 @@ Source23: parallel_test.Makefile #https://bugzilla.mindrot.org/show_bug.cgi?id=1641 (WONTFIX) Patch0001: 0001-openssh-7.8p1-role-mls.patch -#https://bugzilla.redhat.com/show_bug.cgi?id=781634 -Patch0002: 0002-openssh-6.6p1-privsep-selinux.patch -Patch0003: 0003-openssh-6.6p1-keycat.patch +Patch0002: 0002-openssh-6.6p1-keycat.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1644 -Patch0004: 0004-openssh-6.6p1-allow-ip-opts.patch +Patch0003: 0003-openssh-6.6p1-allow-ip-opts.patch #(drop?) https://bugzilla.mindrot.org/show_bug.cgi?id=1925 -Patch0005: 0005-openssh-5.9p1-ipv6man.patch -Patch0006: 0006-openssh-5.8p2-sigpipe.patch +Patch0004: 0004-openssh-5.9p1-ipv6man.patch +Patch0005: 0005-openssh-5.8p2-sigpipe.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1789 -Patch0007: 0007-openssh-7.2p2-x11.patch -Patch0008: 0008-openssh-5.1p1-askpass-progress.patch +Patch0006: 0006-openssh-7.2p2-x11.patch +Patch0007: 0007-openssh-5.1p1-askpass-progress.patch #https://bugzilla.redhat.com/show_bug.cgi?id=198332 -Patch0009: 0009-openssh-4.3p2-askpass-grab-info.patch +Patch0008: 0008-openssh-4.3p2-askpass-grab-info.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1635 (WONTFIX) -Patch0010: 0010-openssh-8.7p1-redhat.patch +Patch0009: 0009-openssh-8.7p1-redhat.patch # warn users for unsupported UsePAM=no (#757545) -Patch0011: 0011-openssh-7.8p1-UsePAM-warning.patch +Patch0010: 0010-openssh-7.8p1-UsePAM-warning.patch # GSSAPI Key Exchange (RFC 4462 + RFC 8732) # from https://github.com/openssh-gsskex/openssh-gsskex/tree/fedora/master # and # Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures # upstream MR: # https://github.com/openssh-gsskex/openssh-gsskex/pull/21 -Patch0012: 0012-openssh-9.6p1-gssapi-keyex.patch +Patch0011: 0011-openssh-9.6p1-gssapi-keyex.patch #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html -Patch0013: 0013-openssh-6.6p1-force_krb.patch +Patch0012: 0012-openssh-6.6p1-force_krb.patch # Improve ccache handling in openssh (#991186, #1199363, #1566494) # https://bugzilla.mindrot.org/show_bug.cgi?id=2775 -Patch0014: 0014-openssh-7.7p1-gssapi-new-unique.patch +Patch0013: 0013-openssh-7.7p1-gssapi-new-unique.patch # Respect k5login_directory option in krk5.conf (#1328243) -Patch0015: 0015-openssh-7.2p2-k5login_directory.patch +Patch0014: 0014-openssh-7.2p2-k5login_directory.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1780 -Patch0016: 0016-openssh-6.6p1-kuserok.patch +Patch0015: 0015-openssh-6.6p1-kuserok.patch # Use tty allocation for a remote scp (#985650) -Patch0017: 0017-openssh-6.4p1-fromto-remote.patch -# privsep_preauth: use SELinux context from selinux-policy (#1008580) -Patch0018: 0018-openssh-6.6.1p1-selinux-contexts.patch +Patch0016: 0016-openssh-6.4p1-fromto-remote.patch # log via monitor in chroots without /dev/log (#2681) -Patch0019: 0019-openssh-6.6.1p1-log-in-chroot.patch +Patch0017: 0017-openssh-6.6.1p1-log-in-chroot.patch # scp file into non-existing directory (#1142223) -Patch0020: 0020-openssh-6.6.1p1-scp-non-existing-directory.patch +Patch0018: 0018-openssh-6.6.1p1-scp-non-existing-directory.patch # add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843) # CVE-2014-9278 -Patch0021: 0021-openssh-6.6p1-GSSAPIEnablek5users.patch +Patch0019: 0019-openssh-6.6p1-GSSAPIEnablek5users.patch # apply upstream patch and make sshd -T more consistent (#1187521) -Patch0022: 0022-openssh-6.8p1-sshdT-output.patch +Patch0020: 0020-openssh-6.8p1-sshdT-output.patch # Add sftp option to force mode of created files (#1191055) -Patch0023: 0023-openssh-6.7p1-sftp-force-permission.patch +Patch0021: 0021-openssh-6.7p1-sftp-force-permission.patch # make s390 use /dev/ crypto devices -- ignore closefrom -Patch0024: 0024-openssh-7.2p2-s390-closefrom.patch +Patch0022: 0022-openssh-7.2p2-s390-closefrom.patch # Move MAX_DISPLAYS to a configuration option (#1341302) -Patch0025: 0025-openssh-7.3p1-x11-max-displays.patch +Patch0023: 0023-openssh-7.3p1-x11-max-displays.patch # Pass inetd flags for SELinux down to openbsd compat level -Patch0026: 0026-openssh-7.6p1-cleanup-selinux.patch +Patch0024: 0024-openssh-7.6p1-cleanup-selinux.patch # Sandbox adjustments for s390 and audit -Patch0027: 0027-openssh-7.5p1-sandbox.patch +Patch0025: 0025-openssh-7.5p1-sandbox.patch # PKCS#11 URIs (upstream #2817, 2nd iteration) # https://github.com/Jakuje/openssh-portable/commits/jjelen-pkcs11 # git show > ~/devel/fedora/openssh/openssh-8.0p1-pkcs11-uri.patch -Patch0028: 0028-openssh-8.0p1-pkcs11-uri.patch +Patch0026: 0026-openssh-8.0p1-pkcs11-uri.patch # Unbreak scp between two IPv6 hosts (#1620333) -Patch0029: 0029-openssh-7.8p1-scp-ipv6.patch +Patch0027: 0027-openssh-7.8p1-scp-ipv6.patch # Mention crypto-policies in manual pages (#1668325) # clarify rhbz#2068423 on the man page of ssh_config -Patch0030: 0030-openssh-8.0p1-crypto-policies.patch +Patch0028: 0028-openssh-8.0p1-crypto-policies.patch # Use OpenSSL KDF (#1631761) -Patch0031: 0031-openssh-8.0p1-openssl-kdf.patch +Patch0029: 0029-openssh-8.0p1-openssl-kdf.patch # sk-dummy.so built with -fvisibility=hidden does not work -Patch0032: 0032-openssh-8.2p1-visibility.patch +Patch0030: 0030-openssh-8.2p1-visibility.patch # Do not break X11 without IPv6 -Patch0033: 0033-openssh-8.2p1-x11-without-ipv6.patch +Patch0031: 0031-openssh-8.2p1-x11-without-ipv6.patch # sshd provides PAM an incorrect error code (#1879503) -Patch0034: 0034-openssh-8.0p1-preserve-pam-errors.patch +Patch0032: 0032-openssh-8.0p1-preserve-pam-errors.patch # Implement kill switch for SCP protocol -Patch0035: 0035-openssh-8.7p1-scp-kill-switch.patch +Patch0033: 0033-openssh-8.7p1-scp-kill-switch.patch # Workaround for lack of sftp_realpath in older versions of RHEL # https://bugzilla.redhat.com/show_bug.cgi?id=2038854 # https://github.com/openssh/openssh-portable/pull/299 # downstream only -Patch0036: 0036-openssh-8.7p1-recursive-scp.patch +Patch0034: 0034-openssh-8.7p1-recursive-scp.patch # Downstream alias for MinRSABits -Patch0037: 0037-openssh-8.7p1-minrsabits.patch +Patch0035: 0035-openssh-8.7p1-minrsabits.patch # downstream only, IBMCA tentative fix # From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14 -Patch0038: 0038-openssh-8.7p1-ibmca.patch +Patch0036: 0036-openssh-8.7p1-ibmca.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1402 # https://bugzilla.redhat.com/show_bug.cgi?id=1171248 # record pfs= field in CRYPTO_SESSION audit event -Patch0039: 0039-openssh-7.6p1-audit.patch +Patch0037: 0037-openssh-7.6p1-audit.patch # Audit race condition in forked child (#1310684) -Patch0040: 0040-openssh-7.1p2-audit-race-condition.patch +Patch0038: 0038-openssh-7.1p2-audit-race-condition.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2049947 -Patch0041: 0041-openssh-9.0p1-audit-log.patch -Patch0042: 0042-openssh-7.7p1-fips.patch +Patch0039: 0039-openssh-9.0p1-audit-log.patch +Patch0040: 0040-openssh-7.7p1-fips.patch # Add missing options from ssh_config into ssh manpage # upstream bug: # https://bugzilla.mindrot.org/show_bug.cgi?id=3455 -Patch0043: 0043-openssh-8.7p1-ssh-manpage.patch +Patch0041: 0041-openssh-8.7p1-ssh-manpage.patch # Don't propose disallowed algorithms during hostkey negotiation # upstream MR: # https://github.com/openssh/openssh-portable/pull/323 -Patch0044: 0044-openssh-8.7p1-negotiate-supported-algs.patch -Patch0045: 0045-openssh-9.0p1-evp-fips-kex.patch -Patch0046: 0046-openssh-8.7p1-nohostsha1proof.patch -Patch0047: 0047-openssh-9.6p1-pam-rhost.patch -Patch0048: 0048-openssh-9.9p1-separate-keysign.patch -Patch0049: 0049-openssh-9.9p1-openssl-mlkem.patch +Patch0042: 0042-openssh-8.7p1-negotiate-supported-algs.patch +Patch0043: 0043-openssh-9.0p1-evp-fips-kex.patch +Patch0044: 0044-openssh-8.7p1-nohostsha1proof.patch +Patch0045: 0045-openssh-9.6p1-pam-rhost.patch +Patch0046: 0046-openssh-9.9p1-separate-keysign.patch +Patch0047: 0047-openssh-9.9p1-openssl-mlkem.patch # https://www.openwall.com/lists/oss-security/2025/02/22/1 -Patch0050: 0050-openssh-9.9p2-error_processing.patch +Patch0048: 0048-openssh-9.9p2-error_processing.patch # https://github.com/openssh/openssh-portable/pull/564 -Patch0051: 0051-Provide-better-error-for-non-supported-private-keys.patch +Patch0049: 0049-Provide-better-error-for-non-supported-private-keys.patch # https://github.com/openssh/openssh-portable/pull/567 -Patch0052: 0052-Ignore-bad-hostkeys-in-known_hosts-file.patch +Patch0050: 0050-Ignore-bad-hostkeys-in-known_hosts-file.patch # https://github.com/openssh/openssh-portable/pull/500 -Patch0053: 0053-support-authentication-indicators-in-GSSAPI.patch -Patch0054: 0054-openssh-10.0-mlkem-nist.patch +Patch0051: 0051-support-authentication-indicators-in-GSSAPI.patch +Patch0052: 0052-NIST-curves-hybrid-KEX-implementation.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 -Patch1000: 1000-openssh-coverity.patch +Patch1000: 1000-openssh-6.7p1-coverity.patch License: BSD-3-Clause AND BSD-2-Clause AND ISC AND SSH-OpenSSH AND ssh-keyscan AND sprintf AND LicenseRef-Fedora-Public-Domain AND X11-distribute-modifications-variant Requires: /sbin/nologin @@ -587,6 +583,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Mon Dec 01 2025 Dmitry Belyavskiy - 10.0p1-9 +- rebuilt + * Mon Nov 03 2025 Dmitry Belyavskiy - 10.0p1-8 - Implement mlkem768nistp256-sha256 and mlkem1024nistp384-sha384 KEX methods From 84bc3aa05748eaa14c9f1759b8fc7a409b5792de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pavol=20=C5=BD=C3=A1=C4=8Dik?= Date: Wed, 10 Dec 2025 12:25:47 +0100 Subject: [PATCH 79/80] Do not fail sshd-auth with gssapi-keyex and no hostkeys With GSSAPI key exchange enabled, sshd must support the "null" host key algorithm. This update make sure that the server does not abort the connection if no host key is provided. --- 0011-openssh-9.6p1-gssapi-keyex.patch | 17 +++++++++++++---- openssh.spec | 5 ++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/0011-openssh-9.6p1-gssapi-keyex.patch b/0011-openssh-9.6p1-gssapi-keyex.patch index c8ac581..b59220d 100644 --- a/0011-openssh-9.6p1-gssapi-keyex.patch +++ b/0011-openssh-9.6p1-gssapi-keyex.patch @@ -1,4 +1,4 @@ -From f4b968d4fd79a47ad3796fc489dd9e5f7fc9d4f2 Mon Sep 17 00:00:00 2001 +From f458a6a7d77264d4ef44e94794a106a8f5ae1ef3 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 11/53] openssh-9.6p1-gssapi-keyex @@ -38,14 +38,14 @@ Subject: [PATCH 11/53] openssh-9.6p1-gssapi-keyex ssh_config | 2 + ssh_config.5 | 58 ++++ sshconnect2.c | 154 ++++++++++- - sshd-auth.c | 53 ++++ + sshd-auth.c | 55 +++- sshd-session.c | 9 +- sshd.c | 3 +- sshd_config | 2 + sshd_config.5 | 31 +++ sshkey.c | 72 ++++- sshkey.h | 1 + - 41 files changed, 2984 insertions(+), 76 deletions(-) + 41 files changed, 2985 insertions(+), 77 deletions(-) create mode 100644 kexgssc.c create mode 100644 kexgsss.c @@ -4023,9 +4023,18 @@ index 1ee6000ab..0af15bcc1 100644 static int diff --git a/sshd-auth.c b/sshd-auth.c -index 30eecd8a4..62f1dc808 100644 +index 30eecd8a4..acad1e388 100644 --- a/sshd-auth.c +++ b/sshd-auth.c +@@ -718,7 +718,7 @@ main(int ac, char **av) + break; + } + } +- if (!have_key) ++ if (!have_key && !options.gss_keyex) + fatal("internal error: received no hostkeys"); + + /* Ensure that umask disallows at least group and world write */ @@ -840,6 +840,48 @@ do_ssh2_kex(struct ssh *ssh) free(hkalgs); diff --git a/openssh.spec b/openssh.spec index 8387ca4..1a684c3 100644 --- a/openssh.spec +++ b/openssh.spec @@ -43,7 +43,7 @@ Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 9%{?dist} +Release: 10%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -583,6 +583,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Wed Dec 10 2025 Pavol Žáčik - 10.0p1-10 +- Update gssapi-keyex patch to not abort KEX without hostkey + * Mon Dec 01 2025 Dmitry Belyavskiy - 10.0p1-9 - rebuilt From be36f8dbd60f4d2e7e1e8b21c615a615f1182f84 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Wed, 17 Dec 2025 15:38:20 +0100 Subject: [PATCH 80/80] Rebase to OpenSSH 10.2p1 --- .gitignore | 2 + 0001-openssh-7.8p1-role-mls.patch | 56 +- 0002-openssh-6.6p1-keycat.patch | 32 +- 0003-openssh-6.6p1-allow-ip-opts.patch | 6 +- 0004-openssh-5.9p1-ipv6man.patch | 4 +- 0005-openssh-5.8p2-sigpipe.patch | 6 +- 0006-openssh-7.2p2-x11.patch | 10 +- 0007-openssh-5.1p1-askpass-progress.patch | 2 +- 0008-openssh-4.3p2-askpass-grab-info.patch | 2 +- 0009-openssh-8.7p1-redhat.patch | 12 +- 0010-openssh-7.8p1-UsePAM-warning.patch | 6 +- 0011-openssh-9.6p1-gssapi-keyex.patch | 287 ++--- 0012-openssh-6.6p1-force_krb.patch | 8 +- 0013-openssh-7.7p1-gssapi-new-unique.patch | 34 +- 0014-openssh-7.2p2-k5login_directory.patch | 6 +- 0015-openssh-6.6p1-kuserok.patch | 26 +- 0016-openssh-6.4p1-fromto-remote.patch | 6 +- 0017-openssh-6.6.1p1-log-in-chroot.patch | 36 +- ...h-6.6.1p1-scp-non-existing-directory.patch | 6 +- 0019-openssh-6.6p1-GSSAPIEnablek5users.patch | 22 +- 0020-openssh-6.8p1-sshdT-output.patch | 6 +- ...-openssh-6.7p1-sftp-force-permission.patch | 18 +- 0022-openssh-7.2p2-s390-closefrom.patch | 2 +- ...> 0023-openssh-7.6p1-cleanup-selinux.patch | 38 +- ....patch => 0024-openssh-7.5p1-sandbox.patch | 12 +- ...patch => 0025-openssh-7.8p1-scp-ipv6.patch | 8 +- ...> 0026-openssh-8.0p1-crypto-policies.patch | 32 +- ...ch => 0027-openssh-8.0p1-openssl-kdf.patch | 16 +- ...tch => 0028-openssh-8.2p1-visibility.patch | 14 +- ... 0029-openssh-8.2p1-x11-without-ipv6.patch | 8 +- ...30-openssh-8.0p1-preserve-pam-errors.patch | 14 +- ...> 0031-openssh-8.7p1-scp-kill-switch.patch | 18 +- ... => 0032-openssh-8.7p1-recursive-scp.patch | 34 +- ...tch => 0033-openssh-8.7p1-minrsabits.patch | 12 +- ...ca.patch => 0034-openssh-8.7p1-ibmca.patch | 4 +- ...it.patch => 0035-openssh-7.6p1-audit.patch | 232 ++--- ...6-openssh-7.1p2-audit-race-condition.patch | 30 +- ...atch => 0037-openssh-9.0p1-audit-log.patch | 26 +- ...ips.patch => 0038-openssh-7.7p1-fips.patch | 133 +-- ...ch => 0039-openssh-8.7p1-ssh-manpage.patch | 4 +- ...enssh-8.7p1-negotiate-supported-algs.patch | 6 +- ...h => 0041-openssh-9.0p1-evp-fips-kex.patch | 36 +- ...> 0042-openssh-8.7p1-nohostsha1proof.patch | 72 +- ... 0043-openssh-9.9p1-separate-keysign.patch | 6 +- ... => 0044-openssh-9.9p1-openssl-mlkem.patch | 42 +- 0045-openssh-9.6p1-pam-rhost.patch | 25 - ... 0045-openssh-9.9p2-error_processing.patch | 8 +- ...error-for-non-supported-private-keys.patch | 8 +- ...ore-bad-hostkeys-in-known_hosts-file.patch | 12 +- ...-authentication-indicators-in-GSSAPI.patch | 32 +- ...IST-curves-hybrid-KEX-implementation.patch | 421 ++++++-- ...-disable-GSSAPIDelegateCredentials-s.patch | 139 +++ ... 0051-openssh-7.3p1-x11-max-displays.patch | 50 +- ...ch => 0052-openssh-10.2p1-pkcs11-uri.patch | 979 ++++++++++-------- 1000-openssh-6.7p1-coverity.patch | 78 +- openssh.spec | 83 +- sources | 4 +- 57 files changed, 1795 insertions(+), 1436 deletions(-) rename 0024-openssh-7.6p1-cleanup-selinux.patch => 0023-openssh-7.6p1-cleanup-selinux.patch (91%) rename 0025-openssh-7.5p1-sandbox.patch => 0024-openssh-7.5p1-sandbox.patch (76%) rename 0027-openssh-7.8p1-scp-ipv6.patch => 0025-openssh-7.8p1-scp-ipv6.patch (75%) rename 0028-openssh-8.0p1-crypto-policies.patch => 0026-openssh-8.0p1-crypto-policies.patch (96%) rename 0029-openssh-8.0p1-openssl-kdf.patch => 0027-openssh-8.0p1-openssl-kdf.patch (90%) rename 0030-openssh-8.2p1-visibility.patch => 0028-openssh-8.2p1-visibility.patch (75%) rename 0031-openssh-8.2p1-x11-without-ipv6.patch => 0029-openssh-8.2p1-x11-without-ipv6.patch (76%) rename 0032-openssh-8.0p1-preserve-pam-errors.patch => 0030-openssh-8.0p1-preserve-pam-errors.patch (79%) rename 0033-openssh-8.7p1-scp-kill-switch.patch => 0031-openssh-8.7p1-scp-kill-switch.patch (75%) rename 0034-openssh-8.7p1-recursive-scp.patch => 0032-openssh-8.7p1-recursive-scp.patch (86%) rename 0035-openssh-8.7p1-minrsabits.patch => 0033-openssh-8.7p1-minrsabits.patch (81%) rename 0036-openssh-8.7p1-ibmca.patch => 0034-openssh-8.7p1-ibmca.patch (85%) rename 0037-openssh-7.6p1-audit.patch => 0035-openssh-7.6p1-audit.patch (91%) rename 0038-openssh-7.1p2-audit-race-condition.patch => 0036-openssh-7.1p2-audit-race-condition.patch (86%) rename 0039-openssh-9.0p1-audit-log.patch => 0037-openssh-9.0p1-audit-log.patch (92%) rename 0040-openssh-7.7p1-fips.patch => 0038-openssh-7.7p1-fips.patch (89%) rename 0041-openssh-8.7p1-ssh-manpage.patch => 0039-openssh-8.7p1-ssh-manpage.patch (91%) rename 0042-openssh-8.7p1-negotiate-supported-algs.patch => 0040-openssh-8.7p1-negotiate-supported-algs.patch (96%) rename 0043-openssh-9.0p1-evp-fips-kex.patch => 0041-openssh-9.0p1-evp-fips-kex.patch (95%) rename 0044-openssh-8.7p1-nohostsha1proof.patch => 0042-openssh-8.7p1-nohostsha1proof.patch (84%) rename 0046-openssh-9.9p1-separate-keysign.patch => 0043-openssh-9.9p1-separate-keysign.patch (77%) rename 0047-openssh-9.9p1-openssl-mlkem.patch => 0044-openssh-9.9p1-openssl-mlkem.patch (91%) delete mode 100644 0045-openssh-9.6p1-pam-rhost.patch rename 0048-openssh-9.9p2-error_processing.patch => 0045-openssh-9.9p2-error_processing.patch (69%) rename 0049-Provide-better-error-for-non-supported-private-keys.patch => 0046-Provide-better-error-for-non-supported-private-keys.patch (68%) rename 0050-Ignore-bad-hostkeys-in-known_hosts-file.patch => 0047-Ignore-bad-hostkeys-in-known_hosts-file.patch (88%) rename 0051-support-authentication-indicators-in-GSSAPI.patch => 0048-support-authentication-indicators-in-GSSAPI.patch (95%) rename 0052-NIST-curves-hybrid-KEX-implementation.patch => 0049-NIST-curves-hybrid-KEX-implementation.patch (73%) create mode 100644 0050-Provide-a-way-to-disable-GSSAPIDelegateCredentials-s.patch rename 0023-openssh-7.3p1-x11-max-displays.patch => 0051-openssh-7.3p1-x11-max-displays.patch (82%) rename 0026-openssh-8.0p1-pkcs11-uri.patch => 0052-openssh-10.2p1-pkcs11-uri.patch (86%) diff --git a/.gitignore b/.gitignore index c400ff6..98996cc 100644 --- a/.gitignore +++ b/.gitignore @@ -66,3 +66,5 @@ pam_ssh_agent_auth-0.9.2.tar.bz2 /openssh-9.9p1.tar.gz.asc /openssh-10.0p1.tar.gz /openssh-10.0p1.tar.gz.asc +/openssh-10.2p1.tar.gz +/openssh-10.2p1.tar.gz.asc diff --git a/0001-openssh-7.8p1-role-mls.patch b/0001-openssh-7.8p1-role-mls.patch index be26347..0377e8c 100644 --- a/0001-openssh-7.8p1-role-mls.patch +++ b/0001-openssh-7.8p1-role-mls.patch @@ -1,4 +1,4 @@ -From 03708ca29702203727ea0e4ca64425b7f1b6f755 Mon Sep 17 00:00:00 2001 +From b6875ceaca4be9e0de0d6d260d8fcff1772f5fb5 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 01/53] openssh-7.8p1-role-mls @@ -26,10 +26,10 @@ Subject: [PATCH 01/53] openssh-7.8p1-role-mls create mode 100644 openbsd-compat/port-linux-sshd.c diff --git a/auth-pam.c b/auth-pam.c -index 13c0a792e..b4100ea1c 100644 +index 5591f094e..70bcae83a 100644 --- a/auth-pam.c +++ b/auth-pam.c -@@ -1238,7 +1238,7 @@ is_pam_session_open(void) +@@ -1261,7 +1261,7 @@ is_pam_session_open(void) * during the ssh authentication process. */ int @@ -102,7 +102,7 @@ index 75eb4e3a3..f7898ab3e 100644 authctxt->postponed = 0; diff --git a/auth2-hostbased.c b/auth2-hostbased.c -index eb21479a0..a3be6e497 100644 +index 9d8b860eb..976484fc5 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -129,7 +129,16 @@ userauth_hostbased(struct ssh *ssh, const char *method) @@ -123,10 +123,10 @@ index eb21479a0..a3be6e497 100644 (r = sshbuf_put_cstring(b, method)) != 0 || (r = sshbuf_put_string(b, pkalg, alen)) != 0 || diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index aa24fda05..267a27d24 100644 +index 15ad3000c..c326a69ba 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c -@@ -206,9 +206,16 @@ userauth_pubkey(struct ssh *ssh, const char *method) +@@ -204,9 +204,16 @@ userauth_pubkey(struct ssh *ssh, const char *method) goto done; } /* reconstruct packet */ @@ -146,7 +146,7 @@ index aa24fda05..267a27d24 100644 (r = sshbuf_put_cstring(b, userstyle)) != 0 || (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || diff --git a/auth2.c b/auth2.c -index 82f6e6211..5ba45c12e 100644 +index b9bb46f59..1345d3257 100644 --- a/auth2.c +++ b/auth2.c @@ -271,6 +271,9 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) @@ -186,10 +186,10 @@ index 82f6e6211..5ba45c12e 100644 if ((r = kex_server_update_ext_info(ssh)) != 0) fatal_fr(r, "kex_server_update_ext_info failed"); diff --git a/misc.c b/misc.c -index dd0bd032a..c932f9bbb 100644 +index ce77ec943..5bed34735 100644 --- a/misc.c +++ b/misc.c -@@ -806,6 +806,7 @@ char * +@@ -822,6 +822,7 @@ char * colon(char *cp) { int flag = 0; @@ -197,7 +197,7 @@ index dd0bd032a..c932f9bbb 100644 if (*cp == ':') /* Leading colon is part of file name. */ return NULL; -@@ -821,6 +822,13 @@ colon(char *cp) +@@ -837,6 +838,13 @@ colon(char *cp) return (cp); if (*cp == '/') return NULL; @@ -212,10 +212,10 @@ index dd0bd032a..c932f9bbb 100644 return NULL; } diff --git a/monitor.c b/monitor.c -index 2179553d3..02b3eaaa3 100644 +index a9e854bec..85dc1b1b7 100644 --- a/monitor.c +++ b/monitor.c -@@ -120,6 +120,9 @@ int mm_answer_sign(struct ssh *, int, struct sshbuf *); +@@ -110,6 +110,9 @@ int mm_answer_sign(struct ssh *, int, struct sshbuf *); int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); int mm_answer_authserv(struct ssh *, int, struct sshbuf *); @@ -225,7 +225,7 @@ index 2179553d3..02b3eaaa3 100644 int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); -@@ -194,6 +197,9 @@ struct mon_table mon_dispatch_proto20[] = { +@@ -184,6 +187,9 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, @@ -235,7 +235,7 @@ index 2179553d3..02b3eaaa3 100644 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, #ifdef USE_PAM -@@ -912,6 +918,9 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -919,6 +925,9 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m) /* Allow service/style information on the auth context */ monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); @@ -245,7 +245,7 @@ index 2179553d3..02b3eaaa3 100644 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); #ifdef USE_PAM -@@ -986,6 +995,26 @@ key_base_type_match(const char *method, const struct sshkey *key, +@@ -993,6 +1002,26 @@ key_base_type_match(const char *method, const struct sshkey *key, return found; } @@ -272,7 +272,7 @@ index 2179553d3..02b3eaaa3 100644 int mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) { -@@ -1358,7 +1387,7 @@ monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) +@@ -1364,7 +1393,7 @@ monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) struct sshbuf *b; struct sshkey *hostkey = NULL; const u_char *p; @@ -281,7 +281,7 @@ index 2179553d3..02b3eaaa3 100644 size_t len; u_char type; int hostbound = 0, r, fail = 0; -@@ -1389,6 +1418,8 @@ monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) +@@ -1395,6 +1424,8 @@ monitor_valid_userblob(struct ssh *ssh, const u_char *data, u_int datalen) fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse userstyle"); @@ -290,7 +290,7 @@ index 2179553d3..02b3eaaa3 100644 xasprintf(&userstyle, "%s%s%s", authctxt->user, authctxt->style ? ":" : "", authctxt->style ? authctxt->style : ""); -@@ -1439,7 +1470,7 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen, +@@ -1445,7 +1476,7 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen, { struct sshbuf *b; const u_char *p; @@ -299,7 +299,7 @@ index 2179553d3..02b3eaaa3 100644 size_t len; int r, fail = 0; u_char type; -@@ -1460,6 +1491,8 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen, +@@ -1466,6 +1497,8 @@ monitor_valid_hostbasedblob(const u_char *data, u_int datalen, fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) fatal_fr(r, "parse userstyle"); @@ -324,10 +324,10 @@ index 3f8a9bea3..9dcd9c293 100644 MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, MONITOR_REQ_PAM_INIT_CTX = 104, MONITOR_ANS_PAM_INIT_CTX = 105, diff --git a/monitor_wrap.c b/monitor_wrap.c -index bd900b2f0..ef3ab1b18 100644 +index 33494b73f..347eb6870 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c -@@ -442,6 +442,27 @@ mm_inform_authserv(char *service, char *style) +@@ -453,6 +453,27 @@ mm_inform_authserv(char *service, char *style) sshbuf_free(m); } @@ -356,10 +356,10 @@ index bd900b2f0..ef3ab1b18 100644 int mm_auth_password(struct ssh *ssh, char *password) diff --git a/monitor_wrap.h b/monitor_wrap.h -index 7134afeec..38a280c87 100644 +index c87295388..9b42ddbcb 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h -@@ -46,6 +46,9 @@ int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, +@@ -50,6 +50,9 @@ int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, const u_char *, size_t, const char *, const char *, const char *, u_int compat); void mm_inform_authserv(char *, char *); @@ -370,10 +370,10 @@ index 7134afeec..38a280c87 100644 char *mm_auth2_read_banner(void); int mm_auth_password(struct ssh *, char *); diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in -index 1d549954f..78e6fa5b1 100644 +index 53c87db6d..39531ae77 100644 --- a/openbsd-compat/Makefile.in +++ b/openbsd-compat/Makefile.in -@@ -100,7 +100,8 @@ PORTS= port-aix.o \ +@@ -102,7 +102,8 @@ PORTS= port-aix.o \ port-prngd.o \ port-solaris.o \ port-net.o \ @@ -881,7 +881,7 @@ index 959430de1..055c825e4 100644 #ifdef LINUX_OOM_ADJUST diff --git a/platform.c b/platform.c -index 4c4fe57ea..1bfb4beae 100644 +index fd1a7a7c2..bcf1b0491 100644 --- a/platform.c +++ b/platform.c @@ -140,7 +140,7 @@ platform_setusercontext_post_groups(struct passwd *pw) @@ -894,10 +894,10 @@ index 4c4fe57ea..1bfb4beae 100644 } diff --git a/sshd-session.c b/sshd-session.c -index c64eb29fc..74d2cbc78 100644 +index 8979f743b..cb4b0523d 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -1328,6 +1328,9 @@ main(int ac, char **av) +@@ -1306,6 +1306,9 @@ main(int ac, char **av) restore_uid(); } #endif diff --git a/0002-openssh-6.6p1-keycat.patch b/0002-openssh-6.6p1-keycat.patch index 8664ab5..b196636 100644 --- a/0002-openssh-6.6p1-keycat.patch +++ b/0002-openssh-6.6p1-keycat.patch @@ -1,4 +1,4 @@ -From 29ac74175c56664e0d2c7bb9362cfa0b25bb0fb4 Mon Sep 17 00:00:00 2001 +From 5f16fff915643a515adbbd2e0cd12717938e3570 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 02/53] openssh-6.6p1-keycat @@ -35,7 +35,7 @@ index 000000000..630ec628c + + diff --git a/Makefile.in b/Makefile.in -index 4617cebcd..438efc51e 100644 +index ba17a79f0..a3a495c1b 100644 --- a/Makefile.in +++ b/Makefile.in @@ -23,6 +23,7 @@ SSH_PROGRAM=@bindir@/ssh @@ -46,7 +46,7 @@ index 4617cebcd..438efc51e 100644 SSHD_SESSION=$(libexecdir)/sshd-session SSHD_AUTH=$(libexecdir)/sshd-auth SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper -@@ -57,6 +58,7 @@ CHANNELLIBS=@CHANNELLIBS@ +@@ -58,6 +59,7 @@ CHANNELLIBS=@CHANNELLIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ SSHDLIBS=@SSHDLIBS@ @@ -54,16 +54,16 @@ index 4617cebcd..438efc51e 100644 LIBEDIT=@LIBEDIT@ LIBFIDO2=@LIBFIDO2@ LIBWTMPDB=@LIBWTMPDB@ -@@ -74,7 +76,7 @@ MKDIR_P=@MKDIR_P@ +@@ -75,7 +77,7 @@ MKDIR_P=@MKDIR_P@ .SUFFIXES: .lo -TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) $(SK_STANDALONE) +TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) sshd-auth$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT) $(SK_STANDALONE) - XMSS_OBJS=\ - ssh-xmss.o \ -@@ -260,6 +262,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS) + LIBOPENSSH_OBJS=\ + ssh_api.o \ +@@ -252,6 +254,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(P11HELPER_OBJS) ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) @@ -73,7 +73,7 @@ index 4617cebcd..438efc51e 100644 ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) -@@ -447,6 +452,7 @@ install-files: +@@ -439,6 +444,7 @@ install-files: $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) @@ -82,10 +82,10 @@ index 4617cebcd..438efc51e 100644 $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 diff --git a/configure.ac b/configure.ac -index ee77a0484..d546788cc 100644 +index db5211013..fd632a5a8 100644 --- a/configure.ac +++ b/configure.ac -@@ -3566,6 +3566,7 @@ AC_ARG_WITH([pam], +@@ -3648,6 +3648,7 @@ AC_ARG_WITH([pam], PAM_MSG="yes" SSHDLIBS="$SSHDLIBS -lpam" @@ -93,7 +93,7 @@ index ee77a0484..d546788cc 100644 AC_DEFINE([USE_PAM], [1], [Define if you want to enable PAM support]) -@@ -3576,6 +3577,7 @@ AC_ARG_WITH([pam], +@@ -3658,6 +3659,7 @@ AC_ARG_WITH([pam], ;; *) SSHDLIBS="$SSHDLIBS -ldl" @@ -101,7 +101,7 @@ index ee77a0484..d546788cc 100644 ;; esac fi -@@ -4801,6 +4803,7 @@ AC_ARG_WITH([selinux], +@@ -4883,6 +4885,7 @@ AC_ARG_WITH([selinux], fi ] ) AC_SUBST([SSHDLIBS]) @@ -109,7 +109,7 @@ index ee77a0484..d546788cc 100644 # Check whether user wants Kerberos 5 support KRB5_MSG="no" -@@ -5812,6 +5815,9 @@ fi +@@ -5894,6 +5897,9 @@ fi if test ! -z "${SSHDLIBS}"; then echo " +for sshd: ${SSHDLIBS}" fi @@ -120,10 +120,10 @@ index ee77a0484..d546788cc 100644 echo "" diff --git a/misc.c b/misc.c -index c932f9bbb..1e31acc95 100644 +index 5bed34735..7e27a38d1 100644 --- a/misc.c +++ b/misc.c -@@ -2897,6 +2897,13 @@ subprocess(const char *tag, const char *command, +@@ -2921,6 +2921,13 @@ subprocess(const char *tag, const char *command, error("%s: dup2: %s", tag, strerror(errno)); _exit(1); } @@ -238,7 +238,7 @@ index 055c825e4..c004071d1 100644 #ifdef LINUX_OOM_ADJUST diff --git a/platform.c b/platform.c -index 1bfb4beae..0d12f3111 100644 +index bcf1b0491..c92a0cba6 100644 --- a/platform.c +++ b/platform.c @@ -55,7 +55,7 @@ platform_setusercontext(struct passwd *pw) diff --git a/0003-openssh-6.6p1-allow-ip-opts.patch b/0003-openssh-6.6p1-allow-ip-opts.patch index ec85893..ea11b6c 100644 --- a/0003-openssh-6.6p1-allow-ip-opts.patch +++ b/0003-openssh-6.6p1-allow-ip-opts.patch @@ -1,4 +1,4 @@ -From 22410e0a4b292f9a27b4d17eb923ed9809e8c0ae Mon Sep 17 00:00:00 2001 +From 7ffeef7e8218c544b6f4a09c5d43e9b748de5a5f Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 03/53] openssh-6.6p1-allow-ip-opts @@ -8,10 +8,10 @@ Subject: [PATCH 03/53] openssh-6.6p1-allow-ip-opts 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/sshd-session.c b/sshd-session.c -index 74d2cbc78..316e2970e 100644 +index cb4b0523d..1c72e664a 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -778,12 +778,32 @@ check_ip_options(struct ssh *ssh) +@@ -754,12 +754,32 @@ check_ip_options(struct ssh *ssh) if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, &option_size) >= 0 && option_size != 0) { diff --git a/0004-openssh-5.9p1-ipv6man.patch b/0004-openssh-5.9p1-ipv6man.patch index e43c447..6ec8afc 100644 --- a/0004-openssh-5.9p1-ipv6man.patch +++ b/0004-openssh-5.9p1-ipv6man.patch @@ -1,4 +1,4 @@ -From 9f7414f535da29a79d3312b3c3c1ed5fcedf912b Mon Sep 17 00:00:00 2001 +From f653eed40e15c4c521ce683a604b46ed81cade6a Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 04/53] openssh-5.9p1-ipv6man @@ -22,7 +22,7 @@ index 697f4e42a..db92ac9af 100644 .Xr scp 1 , .Xr sftp 1 , diff --git a/sshd.8 b/sshd.8 -index 08ebf53a1..2aa732717 100644 +index 7fbca776a..0226a8303 100644 --- a/sshd.8 +++ b/sshd.8 @@ -1018,6 +1018,8 @@ concurrently for different ports, this contains the process ID of the one diff --git a/0005-openssh-5.8p2-sigpipe.patch b/0005-openssh-5.8p2-sigpipe.patch index e8f5fc5..a2a3714 100644 --- a/0005-openssh-5.8p2-sigpipe.patch +++ b/0005-openssh-5.8p2-sigpipe.patch @@ -1,4 +1,4 @@ -From 030764b5f9c86e3f585c1acc8bec7b4b7af4614e Mon Sep 17 00:00:00 2001 +From 6ac14fb92cf0d0676f19282f30b9e427025be31b Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 05/53] openssh-5.8p2-sigpipe @@ -8,10 +8,10 @@ Subject: [PATCH 05/53] openssh-5.8p2-sigpipe 1 file changed, 3 insertions(+) diff --git a/ssh-keyscan.c b/ssh-keyscan.c -index 3436c0b5c..9f76ad225 100644 +index f9788114d..11618ae8a 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c -@@ -798,6 +798,9 @@ main(int argc, char **argv) +@@ -776,6 +776,9 @@ main(int argc, char **argv) if (maxfd > fdlim_get(0)) fdlim_set(maxfd); fdcon = xcalloc(maxfd, sizeof(con)); diff --git a/0006-openssh-7.2p2-x11.patch b/0006-openssh-7.2p2-x11.patch index 1dfeb14..dceef7b 100644 --- a/0006-openssh-7.2p2-x11.patch +++ b/0006-openssh-7.2p2-x11.patch @@ -1,4 +1,4 @@ -From 7fd98c9696df1e7f5feae99762bdde002b98eebe Mon Sep 17 00:00:00 2001 +From d6dc5be6e969ecffe30b9972706b3c92d930d81f Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 06/53] openssh-7.2p2-x11 @@ -8,10 +8,10 @@ Subject: [PATCH 06/53] openssh-7.2p2-x11 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/channels.c b/channels.c -index bfe2e3b2d..d46531ce0 100644 +index 80014ff34..5ce6bd400 100644 --- a/channels.c +++ b/channels.c -@@ -5098,11 +5098,13 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, +@@ -5169,11 +5169,13 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, } static int @@ -26,7 +26,7 @@ index bfe2e3b2d..d46531ce0 100644 sock = socket(AF_UNIX, SOCK_STREAM, 0); if (sock == -1) { error("socket: %.100s", strerror(errno)); -@@ -5110,11 +5112,12 @@ connect_local_xsocket_path(const char *pathname) +@@ -5181,11 +5183,12 @@ connect_local_xsocket_path(const char *pathname) } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; @@ -42,7 +42,7 @@ index bfe2e3b2d..d46531ce0 100644 return -1; } -@@ -5122,8 +5125,18 @@ static int +@@ -5193,8 +5196,18 @@ static int connect_local_xsocket(u_int dnr) { char buf[1024]; diff --git a/0007-openssh-5.1p1-askpass-progress.patch b/0007-openssh-5.1p1-askpass-progress.patch index 63b77d8..66b351e 100644 --- a/0007-openssh-5.1p1-askpass-progress.patch +++ b/0007-openssh-5.1p1-askpass-progress.patch @@ -1,4 +1,4 @@ -From 8e3dd528906915d8b82a65b9a56e0c9201d32ece Mon Sep 17 00:00:00 2001 +From c62cd7ce2539c1eac6d0133c07441c617cbc7bc3 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 07/53] openssh-5.1p1-askpass-progress diff --git a/0008-openssh-4.3p2-askpass-grab-info.patch b/0008-openssh-4.3p2-askpass-grab-info.patch index b781c76..8108482 100644 --- a/0008-openssh-4.3p2-askpass-grab-info.patch +++ b/0008-openssh-4.3p2-askpass-grab-info.patch @@ -1,4 +1,4 @@ -From 02f18438ad18ae5fc1015b9122f98c16e42f8389 Mon Sep 17 00:00:00 2001 +From d124ab0f6eea910dc5f03cdd808f6fa792bf2b7a Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 08/53] openssh-4.3p2-askpass-grab-info diff --git a/0009-openssh-8.7p1-redhat.patch b/0009-openssh-8.7p1-redhat.patch index e0844c6..8e75aa5 100644 --- a/0009-openssh-8.7p1-redhat.patch +++ b/0009-openssh-8.7p1-redhat.patch @@ -1,4 +1,4 @@ -From 73e8653026dc5b08ff9a194be7f1a3f5374ff4da Mon Sep 17 00:00:00 2001 +From c76607384ff077ba1c45759e749562cccaeaa335 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 09/53] openssh-8.7p1-redhat @@ -17,10 +17,10 @@ Subject: [PATCH 09/53] openssh-8.7p1-redhat create mode 100644 sshd_config_redhat_cp diff --git a/ssh_config b/ssh_config -index cc5663562..181691873 100644 +index 238a0c5e3..d9324c957 100644 --- a/ssh_config +++ b/ssh_config -@@ -44,3 +44,10 @@ +@@ -43,3 +43,10 @@ # ProxyCommand ssh -q -W %h:%p gateway.example.com # RekeyLimit 1G 1h # UserKnownHostsFile ~/.ssh/known_hosts.d/%k @@ -75,7 +75,7 @@ index 0f4a3a724..608203e4b 100644 #AddressFamily any #ListenAddress 0.0.0.0 diff --git a/sshd_config.0 b/sshd_config.0 -index 2f77b4f4c..49349bb30 100644 +index c63d729a9..8c5217c0b 100644 --- a/sshd_config.0 +++ b/sshd_config.0 @@ -1219,9 +1219,9 @@ DESCRIPTION @@ -92,10 +92,10 @@ index 2f77b4f4c..49349bb30 100644 TCPKeepAlive Specifies whether the system should send TCP keepalive messages diff --git a/sshd_config.5 b/sshd_config.5 -index c07717375..035a50c8c 100644 +index 6ae606f1e..aa9f0af76 100644 --- a/sshd_config.5 +++ b/sshd_config.5 -@@ -1942,7 +1942,7 @@ By default no subsystems are defined. +@@ -1941,7 +1941,7 @@ By default no subsystems are defined. .It Cm SyslogFacility Gives the facility code that is used when logging messages from .Xr sshd 8 . diff --git a/0010-openssh-7.8p1-UsePAM-warning.patch b/0010-openssh-7.8p1-UsePAM-warning.patch index 183f1ba..521abe4 100644 --- a/0010-openssh-7.8p1-UsePAM-warning.patch +++ b/0010-openssh-7.8p1-UsePAM-warning.patch @@ -1,4 +1,4 @@ -From 9c047ae43abfe2bddb8abbe1bd7d97a301d36afa Mon Sep 17 00:00:00 2001 +From 5f6dbc98a184ce485aef90321ae9fc1ba45293f8 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 10/53] openssh-7.8p1-UsePAM-warning @@ -9,10 +9,10 @@ Subject: [PATCH 10/53] openssh-7.8p1-UsePAM-warning 2 files changed, 6 insertions(+) diff --git a/sshd-session.c b/sshd-session.c -index 316e2970e..c759f95a4 100644 +index 1c72e664a..9804dc334 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -1127,6 +1127,10 @@ main(int ac, char **av) +@@ -1103,6 +1103,10 @@ main(int ac, char **av) "enabled authentication methods"); } diff --git a/0011-openssh-9.6p1-gssapi-keyex.patch b/0011-openssh-9.6p1-gssapi-keyex.patch index b59220d..2e5b723 100644 --- a/0011-openssh-9.6p1-gssapi-keyex.patch +++ b/0011-openssh-9.6p1-gssapi-keyex.patch @@ -1,4 +1,4 @@ -From f458a6a7d77264d4ef44e94794a106a8f5ae1ef3 Mon Sep 17 00:00:00 2001 +From c992408da3ca7aeae129c731c7753019a16ed226 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 11/53] openssh-9.6p1-gssapi-keyex @@ -13,10 +13,10 @@ Subject: [PATCH 11/53] openssh-9.6p1-gssapi-keyex canohost.h | 3 + clientloop.c | 12 + configure.ac | 24 ++ - gss-genr.c | 302 ++++++++++++++++++++- + gss-genr.c | 312 ++++++++++++++++++++- gss-serv-krb5.c | 97 ++++++- gss-serv.c | 200 ++++++++++++-- - kex-names.c | 62 ++++- + kex-names.c | 60 +++- kex.c | 35 ++- kex.h | 34 +++ kexdh.c | 10 + @@ -29,7 +29,7 @@ Subject: [PATCH 11/53] openssh-9.6p1-gssapi-keyex monitor_wrap.h | 4 +- readconf.c | 70 +++++ readconf.h | 6 + - servconf.c | 47 ++++ + servconf.c | 46 ++++ servconf.h | 3 + session.c | 10 +- ssh-gss.h | 64 ++++- @@ -45,23 +45,23 @@ Subject: [PATCH 11/53] openssh-9.6p1-gssapi-keyex sshd_config.5 | 31 +++ sshkey.c | 72 ++++- sshkey.h | 1 + - 41 files changed, 2985 insertions(+), 77 deletions(-) + 41 files changed, 2993 insertions(+), 76 deletions(-) create mode 100644 kexgssc.c create mode 100644 kexgsss.c diff --git a/Makefile.in b/Makefile.in -index 438efc51e..78f659487 100644 +index a3a495c1b..a36eb82ed 100644 --- a/Makefile.in +++ b/Makefile.in -@@ -117,6 +117,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ +@@ -108,6 +108,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kex.o kex-names.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ kexgexc.o kexgexs.o \ kexsntrup761x25519.o kexmlkem768x25519.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 misc-agent.o -@@ -138,7 +139,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rhosts.o auth-passwd.o \ +@@ -131,7 +132,7 @@ SSHD_SESSION_OBJS=sshd-session.o auth-rhosts.o auth-passwd.o \ auth2-chall.o groupaccess.o \ auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ @@ -70,7 +70,7 @@ index 438efc51e..78f659487 100644 auth2-gss.o gss-serv.o gss-serv-krb5.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ sftp-server.o sftp-common.o \ -@@ -150,7 +151,7 @@ SSHD_AUTH_OBJS=sshd-auth.o \ +@@ -143,7 +144,7 @@ SSHD_AUTH_OBJS=sshd-auth.o \ serverloop.o auth.o auth2.o auth-options.o session.o auth2-chall.o \ groupaccess.o auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ auth2-none.o auth2-passwd.o auth2-pubkey.o auth2-pubkeyfile.o \ @@ -79,20 +79,20 @@ index 438efc51e..78f659487 100644 monitor_wrap.o auth-krb5.o \ audit.o audit-bsm.o audit-linux.o platform.o \ loginrec.o auth-pam.o auth-shadow.o auth-sia.o \ -@@ -563,7 +564,7 @@ regress-prep: +@@ -554,7 +555,7 @@ regress-prep: ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile REGRESSLIBS=libssh.a $(LIBCOMPAT) --TESTLIBS=$(LIBS) $(CHANNELLIBS) -+TESTLIBS=$(LIBS) $(CHANNELLIBS) $(GSSLIBS) +-TESTLIBS=$(LIBS) $(CHANNELLIBS) @TESTLIBS@ ++TESTLIBS=$(LIBS) $(CHANNELLIBS) $(GSSLIBS) @TESTLIBS@ regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ diff --git a/auth.c b/auth.c -index 9a6e5a319..e4578169b 100644 +index 8d9404743..d25653ee4 100644 --- a/auth.c +++ b/auth.c -@@ -356,7 +356,8 @@ auth_root_allowed(struct ssh *ssh, const char *method) +@@ -354,7 +354,8 @@ auth_root_allowed(struct ssh *ssh, const char *method) case PERMIT_NO_PASSWD: if (strcmp(method, "publickey") == 0 || strcmp(method, "hostbased") == 0 || @@ -218,7 +218,7 @@ index 99637a89b..a05908cf3 100644 #endif &methodcfg_passwd, diff --git a/auth2.c b/auth2.c -index 5ba45c12e..8ec41de23 100644 +index 1345d3257..5a4b932a9 100644 --- a/auth2.c +++ b/auth2.c @@ -71,6 +71,7 @@ extern Authmethod method_passwd; @@ -356,10 +356,10 @@ index 26d62855a..0cadc9f18 100644 int get_peer_port(int); char *get_local_ipaddr(int); diff --git a/clientloop.c b/clientloop.c -index 916fc077b..4655f91fe 100644 +index 49d048d85..33adf31dc 100644 --- a/clientloop.c +++ b/clientloop.c -@@ -115,6 +115,10 @@ +@@ -107,6 +107,10 @@ #include "ssherr.h" #include "hostfile.h" @@ -370,7 +370,7 @@ index 916fc077b..4655f91fe 100644 /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" -@@ -1591,6 +1595,14 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, +@@ -1604,6 +1608,14 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, /* Do channel operations. */ channel_after_poll(ssh, pfd, npfd_active); @@ -386,10 +386,10 @@ index 916fc077b..4655f91fe 100644 if (conn_in_ready) client_process_net_input(ssh); diff --git a/configure.ac b/configure.ac -index d546788cc..13c70a983 100644 +index fd632a5a8..adccaebd4 100644 --- a/configure.ac +++ b/configure.ac -@@ -786,6 +786,30 @@ int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) +@@ -813,6 +813,30 @@ int main(void) { 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]) @@ -421,7 +421,7 @@ index d546788cc..13c70a983 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 aa34b71c5..3034370c7 100644 +index 8f1f54afb..f2d6f59e5 100644 --- a/gss-genr.c +++ b/gss-genr.c @@ -42,9 +42,33 @@ @@ -458,7 +458,7 @@ index aa34b71c5..3034370c7 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) +@@ -60,6 +84,169 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) return 0; } @@ -527,19 +527,29 @@ index aa34b71c5..3034370c7 100644 + for (i = 0; i < gss_supported->count; i++) { + if (gss_supported->elements[i].length < 128 && + (*check)(NULL, &(gss_supported->elements[i]), host, client)) { ++ EVP_MD_CTX * ctx = NULL; ++ EVP_MD *md5 = NULL; /* Here we don't use MD5 for crypto purposes */ ++ unsigned int md_size = sizeof(digest); + + deroid[0] = SSH_GSS_OIDTYPE; + deroid[1] = gss_supported->elements[i].length; -+ -+ if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || -+ (r = ssh_digest_update(md, deroid, 2)) != 0 || -+ (r = ssh_digest_update(md, -+ gss_supported->elements[i].elements, -+ gss_supported->elements[i].length)) != 0 || -+ (r = ssh_digest_final(md, digest, sizeof(digest))) != 0) ++ if ((md5 = EVP_MD_fetch(NULL, "MD5", "provider=default,-fips")) == NULL) ++ fatal_fr(r, "MD5 fetch failed"); ++ if ((ctx = EVP_MD_CTX_new()) == NULL) { ++ EVP_MD_free(md5); ++ fatal_fr(r, "digest ctx failed"); ++ } ++ if (EVP_DigestInit(ctx, md5) <= 0 ++ || EVP_DigestUpdate(ctx, deroid, 2) <= 0 ++ || EVP_DigestUpdate(ctx, gss_supported->elements[i].elements, ++ gss_supported->elements[i].length) <= 0 ++ || EVP_DigestFinal(ctx, digest, &md_size) <= 0) { ++ EVP_MD_free(md5); ++ EVP_MD_CTX_free(ctx); + fatal_fr(r, "digest failed"); -+ ssh_digest_free(md); -+ md = NULL; ++ } ++ EVP_MD_free(md5); md5 = NULL; ++ EVP_MD_CTX_free(ctx); ctx = NULL; + + encoded = xmalloc(ssh_digest_bytes(SSH_DIGEST_MD5) + * 2); @@ -618,7 +628,7 @@ index aa34b71c5..3034370c7 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) -@@ -168,6 +345,7 @@ ssh_gssapi_build_ctx(Gssctxt **ctx) +@@ -168,6 +355,7 @@ ssh_gssapi_build_ctx(Gssctxt **ctx) (*ctx)->creds = GSS_C_NO_CREDENTIAL; (*ctx)->client = GSS_C_NO_NAME; (*ctx)->client_creds = GSS_C_NO_CREDENTIAL; @@ -626,7 +636,7 @@ index aa34b71c5..3034370c7 100644 } /* Delete our context, providing it has been built correctly */ -@@ -193,6 +371,12 @@ ssh_gssapi_delete_ctx(Gssctxt **ctx) +@@ -193,6 +381,12 @@ ssh_gssapi_delete_ctx(Gssctxt **ctx) gss_release_name(&ms, &(*ctx)->client); if ((*ctx)->client_creds != GSS_C_NO_CREDENTIAL) gss_release_cred(&ms, &(*ctx)->client_creds); @@ -639,7 +649,7 @@ index aa34b71c5..3034370c7 100644 free(*ctx); *ctx = NULL; -@@ -216,7 +400,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, +@@ -216,7 +410,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, } ctx->major = gss_init_sec_context(&ctx->minor, @@ -648,7 +658,7 @@ index aa34b71c5..3034370c7 100644 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -245,9 +429,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) +@@ -245,9 +439,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) return (ctx->major); } @@ -692,7 +702,7 @@ index aa34b71c5..3034370c7 100644 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); -@@ -255,6 +473,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) +@@ -255,6 +483,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) return (ctx->major); } @@ -712,7 +722,7 @@ index aa34b71c5..3034370c7 100644 void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, const char *context, const struct sshbuf *session_id) -@@ -271,11 +502,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, +@@ -271,11 +512,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, } int @@ -730,7 +740,7 @@ index aa34b71c5..3034370c7 100644 /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && -@@ -285,6 +521,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +@@ -285,6 +531,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); @@ -741,7 +751,7 @@ index aa34b71c5..3034370c7 100644 if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); -@@ -294,10 +534,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) +@@ -294,10 +544,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) GSS_C_NO_BUFFER); } @@ -950,11 +960,11 @@ index a151bc1e4..8d2b677f7 100644 #endif /* KRB5 */ diff --git a/gss-serv.c b/gss-serv.c -index 025a118f8..a5cca7973 100644 +index b0e9c3b49..6bac42931 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -1,7 +1,7 @@ - /* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ + /* $OpenBSD: gss-serv.c,v 1.33 2025/09/29 21:30:15 dtucker Exp $ */ /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -1245,7 +1255,7 @@ index 025a118f8..a5cca7973 100644 /* Privileged */ diff --git a/kex-names.c b/kex-names.c -index ec840c1f9..6c0b7c2b3 100644 +index a20ce602a..31e395aa2 100644 --- a/kex-names.c +++ b/kex-names.c @@ -45,6 +45,10 @@ @@ -1259,22 +1269,22 @@ index ec840c1f9..6c0b7c2b3 100644 struct kexalg { char *name; u_int type; -@@ -89,15 +93,28 @@ static const struct kexalg kexalgs[] = { +@@ -90,9 +94,22 @@ static const struct kexalg kexalgs[] = { #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ - { NULL, 0, -1, -1}, + { NULL, 0, -1, -1, 0 }, }; +static const struct kexalg gss_kexalgs[] = { +#ifdef GSSAPI -+ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, ++ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1, KEX_NOT_PQ }, ++ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1, KEX_NOT_PQ }, ++ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1, KEX_NOT_PQ }, ++ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256, KEX_NOT_PQ }, ++ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512, KEX_NOT_PQ }, + { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, -+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, ++ NID_X9_62_prime256v1, SSH_DIGEST_SHA256, KEX_NOT_PQ }, ++ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256, KEX_NOT_PQ }, +#endif -+ { NULL, 0, -1, -1}, ++ { NULL, 0, -1, -1, 0}, +}; -char * @@ -1282,16 +1292,9 @@ index ec840c1f9..6c0b7c2b3 100644 +static char * +kex_alg_list_internal(char sep, const struct kexalg *algs) { - char *ret = NULL, *tmp; - size_t nlen, rlen = 0; + char *ret = NULL; const struct kexalg *k; - -- for (k = kexalgs; k->name != NULL; k++) { -+ for (k = algs; k->name != NULL; k++) { - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(k->name); -@@ -112,6 +129,18 @@ kex_alg_list(char sep) +@@ -104,6 +121,18 @@ kex_alg_list(char sep) return ret; } @@ -1310,7 +1313,7 @@ index ec840c1f9..6c0b7c2b3 100644 static const struct kexalg * kex_alg_by_name(const char *name) { -@@ -121,6 +150,10 @@ kex_alg_by_name(const char *name) +@@ -113,6 +142,10 @@ kex_alg_by_name(const char *name) if (strcmp(k->name, name) == 0) return k; } @@ -1321,7 +1324,7 @@ index ec840c1f9..6c0b7c2b3 100644 return NULL; } -@@ -334,3 +367,26 @@ kex_assemble_names(char **listp, const char *def, const char *all) +@@ -336,3 +369,26 @@ kex_assemble_names(char **listp, const char *def, const char *all) free(ret); return r; } @@ -1349,10 +1352,10 @@ index ec840c1f9..6c0b7c2b3 100644 + return 1; +} diff --git a/kex.c b/kex.c -index 6b957e5e1..19a56e8e9 100644 +index 814fad947..9a2ce6d88 100644 --- a/kex.c +++ b/kex.c -@@ -297,17 +297,37 @@ static int +@@ -295,17 +295,37 @@ static int kex_compose_ext_info_server(struct ssh *ssh, struct sshbuf *m) { int r; @@ -1396,7 +1399,7 @@ index 6b957e5e1..19a56e8e9 100644 (r = sshbuf_put_cstring(m, "0")) != 0) { error_fr(r, "compose"); return r; -@@ -737,6 +757,9 @@ kex_free(struct kex *kex) +@@ -735,6 +755,9 @@ kex_free(struct kex *kex) sshbuf_free(kex->server_version); sshbuf_free(kex->client_pub); sshbuf_free(kex->session_id); @@ -1407,7 +1410,7 @@ index 6b957e5e1..19a56e8e9 100644 sshkey_free(kex->initial_hostkey); free(kex->failed_choice); diff --git a/kex.h b/kex.h -index d08988b3e..0e080ea38 100644 +index 55baa6a1e..206ce60ed 100644 --- a/kex.h +++ b/kex.h @@ -29,6 +29,10 @@ @@ -1437,7 +1440,7 @@ index d08988b3e..0e080ea38 100644 KEX_MAX }; -@@ -165,6 +178,13 @@ struct kex { +@@ -169,6 +182,13 @@ struct kex { u_int flags; int hash_alg; int ec_nid; @@ -1451,8 +1454,8 @@ index d08988b3e..0e080ea38 100644 char *failed_choice; int (*verify_host_key)(struct sshkey *, struct ssh *); struct sshkey *(*load_host_public_key)(int, int, struct ssh *); -@@ -191,8 +211,10 @@ int kex_hash_from_name(const char *); - int kex_nid_from_name(const char *); +@@ -196,8 +216,10 @@ int kex_nid_from_name(const char *); + int kex_is_pq_from_name(const char *); int kex_names_valid(const char *); char *kex_alg_list(char); +char *kex_gss_alg_list(char); @@ -1462,7 +1465,7 @@ index d08988b3e..0e080ea38 100644 int kex_assemble_names(char **, const char *, const char *); void kex_proposal_populate_entries(struct ssh *, char *prop[PROPOSAL_MAX], const char *, const char *, const char *, const char *, const char *); -@@ -226,6 +248,12 @@ int kexgex_client(struct ssh *); +@@ -231,6 +253,12 @@ int kexgex_client(struct ssh *); int kexgex_server(struct ssh *); int kex_gen_client(struct ssh *); int kex_gen_server(struct ssh *); @@ -1475,7 +1478,7 @@ index d08988b3e..0e080ea38 100644 int kex_dh_keypair(struct kex *); int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, -@@ -264,6 +292,12 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, +@@ -269,6 +297,12 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, const BIGNUM *, const u_char *, size_t, u_char *, size_t *); @@ -1489,10 +1492,10 @@ index d08988b3e..0e080ea38 100644 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); diff --git a/kexdh.c b/kexdh.c -index c1084f214..0faab21b0 100644 +index 191bdced0..6d5a7813d 100644 --- a/kexdh.c +++ b/kexdh.c -@@ -49,13 +49,23 @@ kex_dh_keygen(struct kex *kex) +@@ -50,13 +50,23 @@ kex_dh_keygen(struct kex *kex) { switch (kex->kex_type) { case KEX_DH_GRP1_SHA1: @@ -1517,7 +1520,7 @@ index c1084f214..0faab21b0 100644 break; case KEX_DH_GRP18_SHA512: diff --git a/kexgen.c b/kexgen.c -index 40d688d62..15df591ca 100644 +index 494d4b233..58edc79ad 100644 --- a/kexgen.c +++ b/kexgen.c @@ -44,7 +44,7 @@ @@ -2849,10 +2852,10 @@ index 000000000..8362081ea + +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --git a/monitor.c b/monitor.c -index 02b3eaaa3..2ef16cc8e 100644 +index 85dc1b1b7..d463d6a9c 100644 --- a/monitor.c +++ b/monitor.c -@@ -147,6 +147,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); +@@ -137,6 +137,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); @@ -2861,7 +2864,7 @@ index 02b3eaaa3..2ef16cc8e 100644 #endif #ifdef SSH_AUDIT_EVENTS -@@ -224,11 +226,18 @@ struct mon_table mon_dispatch_proto20[] = { +@@ -214,11 +216,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}, @@ -2880,7 +2883,7 @@ index 02b3eaaa3..2ef16cc8e 100644 {MONITOR_REQ_STATE, MON_ONCE, mm_answer_state}, #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, -@@ -299,6 +308,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -289,6 +298,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) monitor_permit(mon_dispatch, MONITOR_REQ_STATE, 1); monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -2891,7 +2894,7 @@ index 02b3eaaa3..2ef16cc8e 100644 /* The first few requests do not require asynchronous access */ while (!authenticated) { -@@ -351,8 +364,15 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -341,8 +354,15 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { auth_log(ssh, authenticated, partial, auth_method, auth_submethod); @@ -2908,7 +2911,7 @@ index 02b3eaaa3..2ef16cc8e 100644 if (authenticated || partial) { auth2_update_session_info(authctxt, auth_method, auth_submethod); -@@ -421,6 +441,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -429,6 +449,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); @@ -2919,7 +2922,7 @@ index 02b3eaaa3..2ef16cc8e 100644 if (auth_opts->permit_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); -@@ -1890,6 +1914,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1896,6 +1920,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif @@ -2937,7 +2940,7 @@ index 02b3eaaa3..2ef16cc8e 100644 #endif /* WITH_OPENSSL */ kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; -@@ -1981,8 +2016,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1987,8 +2022,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) u_char *p; int r; @@ -2948,7 +2951,7 @@ index 02b3eaaa3..2ef16cc8e 100644 if ((r = sshbuf_get_string(m, &p, &len)) != 0) fatal_fr(r, "parse"); -@@ -2014,8 +2049,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -2020,8 +2055,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) OM_uint32 flags = 0; /* GSI needs this */ int r; @@ -2959,7 +2962,7 @@ index 02b3eaaa3..2ef16cc8e 100644 if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) fatal_fr(r, "ssh_gssapi_get_buffer_desc"); -@@ -2035,6 +2070,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -2041,6 +2076,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); @@ -2967,7 +2970,7 @@ index 02b3eaaa3..2ef16cc8e 100644 } return (0); } -@@ -2046,8 +2082,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -2052,8 +2088,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) OM_uint32 ret; int r; @@ -2978,7 +2981,7 @@ index 02b3eaaa3..2ef16cc8e 100644 if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) -@@ -2073,13 +2109,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -2079,13 +2115,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) { @@ -3000,7 +3003,7 @@ index 02b3eaaa3..2ef16cc8e 100644 sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) -@@ -2088,7 +2128,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -2094,7 +2134,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); @@ -3013,7 +3016,7 @@ index 02b3eaaa3..2ef16cc8e 100644 if ((displayname = ssh_gssapi_displayname()) != NULL) auth2_record_info(authctxt, "%s", displayname); -@@ -2096,5 +2140,84 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -2102,5 +2146,84 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) /* Monitor loop will terminate if authenticated */ return (authenticated); } @@ -3112,10 +3115,10 @@ index 9dcd9c293..dbc7e0037 100644 struct ssh; diff --git a/monitor_wrap.c b/monitor_wrap.c -index ef3ab1b18..b6e3b3f39 100644 +index 347eb6870..08dc29e12 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c -@@ -1131,13 +1131,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) +@@ -1142,13 +1142,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) } int @@ -3132,7 +3135,7 @@ index ef3ab1b18..b6e3b3f39 100644 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); mm_request_receive_expect(pmonitor->m_recvfd, -@@ -1150,6 +1152,59 @@ mm_ssh_gssapi_userok(char *user) +@@ -1161,6 +1163,59 @@ mm_ssh_gssapi_userok(char *user) debug3_f("user %sauthenticated", authenticated ? "" : "not "); return (authenticated); } @@ -3193,10 +3196,10 @@ index ef3ab1b18..b6e3b3f39 100644 /* diff --git a/monitor_wrap.h b/monitor_wrap.h -index 38a280c87..672dce525 100644 +index 9b42ddbcb..12c489c33 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h -@@ -67,8 +67,10 @@ void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); +@@ -71,8 +71,10 @@ void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); 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 *); @@ -3209,10 +3212,10 @@ index 38a280c87..672dce525 100644 #ifdef USE_PAM diff --git a/readconf.c b/readconf.c -index 7cbe7d2c2..6c04ed43c 100644 +index d99205944..eab734aaf 100644 --- a/readconf.c +++ b/readconf.c -@@ -71,6 +71,7 @@ +@@ -65,6 +65,7 @@ #include "myproposal.h" #include "digest.h" #include "version.h" @@ -3220,7 +3223,7 @@ index 7cbe7d2c2..6c04ed43c 100644 /* Format of the configuration file: -@@ -165,6 +166,8 @@ typedef enum { +@@ -159,6 +160,8 @@ typedef enum { oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, @@ -3229,7 +3232,7 @@ index 7cbe7d2c2..6c04ed43c 100644 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, -@@ -212,10 +215,22 @@ static struct { +@@ -206,10 +209,22 @@ static struct { /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, @@ -3252,7 +3255,7 @@ index 7cbe7d2c2..6c04ed43c 100644 #endif #ifdef ENABLE_PKCS11 { "pkcs11provider", oPKCS11Provider }, -@@ -1320,10 +1335,42 @@ parse_time: +@@ -1326,10 +1341,42 @@ parse_time: intptr = &options->gss_authentication; goto parse_flag; @@ -3295,7 +3298,7 @@ index 7cbe7d2c2..6c04ed43c 100644 case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -2662,7 +2709,13 @@ initialize_options(Options * options) +@@ -2698,7 +2745,13 @@ initialize_options(Options * options) options->fwd_opts.streamlocal_bind_unlink = -1; options->pubkey_authentication = -1; options->gss_authentication = -1; @@ -3309,7 +3312,7 @@ index 7cbe7d2c2..6c04ed43c 100644 options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; -@@ -2826,8 +2879,18 @@ fill_default_options(Options * options) +@@ -2863,8 +2916,18 @@ fill_default_options(Options * options) options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3328,7 +3331,7 @@ index 7cbe7d2c2..6c04ed43c 100644 if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -3656,7 +3719,14 @@ dump_client_config(Options *o, const char *host) +@@ -3692,7 +3755,14 @@ dump_client_config(Options *o, const char *host) dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); #ifdef GSSAPI dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); @@ -3344,7 +3347,7 @@ index 7cbe7d2c2..6c04ed43c 100644 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); diff --git a/readconf.h b/readconf.h -index cd49139b1..368523dd7 100644 +index 942149f9a..b96e3279e 100644 --- a/readconf.h +++ b/readconf.h @@ -39,7 +39,13 @@ typedef struct { @@ -3362,10 +3365,10 @@ index cd49139b1..368523dd7 100644 * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ diff --git a/servconf.c b/servconf.c -index f7bc92377..d4f7fd66f 100644 +index 48ec8c4ec..3b93ca829 100644 --- a/servconf.c +++ b/servconf.c -@@ -69,6 +69,7 @@ +@@ -67,6 +67,7 @@ #include "myproposal.h" #include "digest.h" #include "version.h" @@ -3373,7 +3376,7 @@ index f7bc92377..d4f7fd66f 100644 #if !defined(SSHD_PAM_SERVICE) # define SSHD_PAM_SERVICE "sshd" -@@ -138,8 +139,11 @@ initialize_server_options(ServerOptions *options) +@@ -136,8 +137,11 @@ initialize_server_options(ServerOptions *options) options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; @@ -3385,7 +3388,7 @@ index f7bc92377..d4f7fd66f 100644 options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; -@@ -380,10 +384,18 @@ fill_default_server_options(ServerOptions *options) +@@ -374,10 +378,18 @@ fill_default_server_options(ServerOptions *options) options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -3404,7 +3407,7 @@ index f7bc92377..d4f7fd66f 100644 if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -568,6 +580,7 @@ typedef enum { +@@ -562,6 +574,7 @@ typedef enum { sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, @@ -3412,7 +3415,7 @@ index f7bc92377..d4f7fd66f 100644 sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -653,12 +666,22 @@ static struct { +@@ -647,12 +660,22 @@ static struct { #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, @@ -3435,7 +3438,7 @@ index f7bc92377..d4f7fd66f 100644 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, /* alias */ -@@ -1649,6 +1672,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1643,6 +1666,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->gss_authentication; goto parse_flag; @@ -3446,7 +3449,7 @@ index f7bc92377..d4f7fd66f 100644 case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1657,6 +1684,22 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1651,6 +1678,22 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->gss_strict_acceptor; goto parse_flag; @@ -3469,12 +3472,12 @@ index f7bc92377..d4f7fd66f 100644 case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -3254,6 +3297,10 @@ dump_config(ServerOptions *o) +@@ -3256,7 +3299,10 @@ dump_config(ServerOptions *o) #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); + dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); -+ dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); + dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); + dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); + dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms); #endif @@ -3497,10 +3500,10 @@ index 9beb90fae..c3f501400 100644 * authentication. */ int kbd_interactive_authentication; /* If true, permit */ diff --git a/session.c b/session.c -index 6444c77f3..b3833e44c 100644 +index f265fdc3e..b8f0c1a58 100644 --- a/session.c +++ b/session.c -@@ -2668,13 +2668,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +@@ -2630,13 +2630,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) #ifdef KRB5 if (options.kerberos_ticket_cleanup && @@ -3680,10 +3683,10 @@ index db92ac9af..6a9fbdc5b 100644 (key types), .Ar key-ca-sign diff --git a/ssh.c b/ssh.c -index dc4886d0e..c23d3b9e3 100644 +index 3b03108db..8d27f6379 100644 --- a/ssh.c +++ b/ssh.c -@@ -835,6 +835,8 @@ main(int ac, char **av) +@@ -847,6 +847,8 @@ main(int ac, char **av) else if (strcmp(optarg, "kex") == 0 || strcasecmp(optarg, "KexAlgorithms") == 0) cp = kex_alg_list('\n'); @@ -3692,7 +3695,7 @@ index dc4886d0e..c23d3b9e3 100644 else if (strcmp(optarg, "key") == 0) cp = sshkey_alg_list(0, 0, 0, '\n'); else if (strcmp(optarg, "key-cert") == 0) -@@ -865,8 +867,8 @@ main(int ac, char **av) +@@ -877,8 +879,8 @@ main(int ac, char **av) } else if (strcmp(optarg, "help") == 0) { cp = xstrdup( "cipher\ncipher-auth\ncompression\nkex\n" @@ -3704,7 +3707,7 @@ index dc4886d0e..c23d3b9e3 100644 if (cp == NULL) fatal("Unsupported query \"%s\"", optarg); diff --git a/ssh_config b/ssh_config -index 181691873..209248d69 100644 +index d9324c957..ca7c5853b 100644 --- a/ssh_config +++ b/ssh_config @@ -24,6 +24,8 @@ @@ -3717,7 +3720,7 @@ index 181691873..209248d69 100644 # CheckHostIP no # AddressFamily any diff --git a/ssh_config.5 b/ssh_config.5 -index 894d73831..3a8e246c4 100644 +index f7066cbaa..8a4b469cf 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -976,10 +976,68 @@ The default is @@ -3790,7 +3793,7 @@ index 894d73831..3a8e246c4 100644 Indicates that .Xr ssh 1 diff --git a/sshconnect2.c b/sshconnect2.c -index 1ee6000ab..0af15bcc1 100644 +index b3679c9d7..b253f991b 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -222,6 +222,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, @@ -4023,10 +4026,10 @@ index 1ee6000ab..0af15bcc1 100644 static int diff --git a/sshd-auth.c b/sshd-auth.c -index 30eecd8a4..acad1e388 100644 +index 9c31515de..5a4ee733c 100644 --- a/sshd-auth.c +++ b/sshd-auth.c -@@ -718,7 +718,7 @@ main(int ac, char **av) +@@ -696,7 +696,7 @@ main(int ac, char **av) break; } } @@ -4035,7 +4038,7 @@ index 30eecd8a4..acad1e388 100644 fatal("internal error: received no hostkeys"); /* Ensure that umask disallows at least group and world write */ -@@ -840,6 +840,48 @@ do_ssh2_kex(struct ssh *ssh) +@@ -819,6 +819,48 @@ do_ssh2_kex(struct ssh *ssh) free(hkalgs); @@ -4084,7 +4087,7 @@ index 30eecd8a4..acad1e388 100644 /* start key exchange */ if ((r = kex_setup(ssh, myproposal)) != 0) fatal_r(r, "kex_setup"); -@@ -857,6 +899,17 @@ do_ssh2_kex(struct ssh *ssh) +@@ -836,6 +878,17 @@ do_ssh2_kex(struct ssh *ssh) # ifdef OPENSSL_HAS_ECC kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif /* OPENSSL_HAS_ECC */ @@ -4103,10 +4106,10 @@ index 30eecd8a4..acad1e388 100644 kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; diff --git a/sshd-session.c b/sshd-session.c -index c759f95a4..3cfe71806 100644 +index 9804dc334..6e28020e9 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -616,8 +616,8 @@ notify_hostkeys(struct ssh *ssh) +@@ -592,8 +592,8 @@ notify_hostkeys(struct ssh *ssh) } debug3_f("sent %u hostkeys", nkeys); if (nkeys == 0) @@ -4117,7 +4120,7 @@ index c759f95a4..3cfe71806 100644 sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } -@@ -1159,8 +1159,9 @@ main(int ac, char **av) +@@ -1135,8 +1135,9 @@ main(int ac, char **av) break; } } @@ -4130,7 +4133,7 @@ index c759f95a4..3cfe71806 100644 /* Ensure that umask disallows at least group and world write */ new_umask = umask(0077) | 0022; diff --git a/sshd.c b/sshd.c -index 4a93e29e4..c9ea8e385 100644 +index 3c76b60b0..3ab81e268 100644 --- a/sshd.c +++ b/sshd.c @@ -1676,7 +1676,8 @@ main(int ac, char **av) @@ -4157,7 +4160,7 @@ index 48af6321b..8db9f0fb1 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 035a50c8c..8bc6586e6 100644 +index aa9f0af76..b90068bf3 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -739,6 +739,11 @@ Specifies whether to automatically destroy the user's credentials cache @@ -4206,12 +4209,12 @@ index 035a50c8c..8bc6586e6 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 ab80752b8..4e41a78c7 100644 +index afd7822c4..148fee2b7 100644 --- a/sshkey.c +++ b/sshkey.c -@@ -129,6 +129,75 @@ extern const struct sshkey_impl sshkey_xmss_impl; - extern const struct sshkey_impl sshkey_xmss_cert_impl; - #endif +@@ -114,6 +114,75 @@ extern const struct sshkey_impl sshkey_rsa_sha512_impl; + extern const struct sshkey_impl sshkey_rsa_sha512_cert_impl; + #endif /* WITH_OPENSSL */ +static int ssh_gss_equal(const struct sshkey *, const struct sshkey *) +{ @@ -4285,15 +4288,15 @@ index ab80752b8..4e41a78c7 100644 const struct sshkey_impl * const keyimpls[] = { &sshkey_ed25519_impl, &sshkey_ed25519_cert_impl, -@@ -167,6 +236,7 @@ const struct sshkey_impl * const keyimpls[] = { - &sshkey_xmss_impl, - &sshkey_xmss_cert_impl, - #endif +@@ -144,6 +213,7 @@ const struct sshkey_impl * const keyimpls[] = { + &sshkey_rsa_sha512_impl, + &sshkey_rsa_sha512_cert_impl, + #endif /* WITH_OPENSSL */ + &sshkey_gss_kex_impl, NULL }; -@@ -336,7 +406,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) +@@ -314,7 +384,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) for (i = 0; keyimpls[i] != NULL; i++) { impl = keyimpls[i]; @@ -4303,10 +4306,10 @@ index ab80752b8..4e41a78c7 100644 if (!include_sigonly && impl->sigonly) continue; diff --git a/sshkey.h b/sshkey.h -index 19bbbac7d..4a318d05b 100644 +index c3262b896..931d1f79b 100644 --- a/sshkey.h +++ b/sshkey.h -@@ -75,6 +75,7 @@ enum sshkey_types { +@@ -67,6 +67,7 @@ enum sshkey_types { KEY_ECDSA_SK_CERT, KEY_ED25519_SK, KEY_ED25519_SK_CERT, diff --git a/0012-openssh-6.6p1-force_krb.patch b/0012-openssh-6.6p1-force_krb.patch index 861112c..70f75fb 100644 --- a/0012-openssh-6.6p1-force_krb.patch +++ b/0012-openssh-6.6p1-force_krb.patch @@ -1,4 +1,4 @@ -From 41d42d41834ed9b60a627fe6025cfe99be72e82c Mon Sep 17 00:00:00 2001 +From 577b0fea53270292bd0b4979eb5369619b2f5adb Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 12/53] openssh-6.6p1-force_krb @@ -217,10 +217,10 @@ index 8d2b677f7..14502c5a6 100644 /* This writes out any forwarded credentials from the structure populated * during userauth. Called after we have setuid to the user */ diff --git a/session.c b/session.c -index b3833e44c..40f36af17 100644 +index b8f0c1a58..3eae5bdf3 100644 --- a/session.c +++ b/session.c -@@ -680,6 +680,29 @@ do_exec(struct ssh *ssh, Session *s, const char *command) +@@ -642,6 +642,29 @@ do_exec(struct ssh *ssh, Session *s, const char *command) command = auth_opts->force_command; forced = "(key-option)"; } @@ -266,7 +266,7 @@ index 8ec451926..db34d77f4 100644 /* draft-ietf-secsh-gsskeyex-06 */ diff --git a/sshd.8 b/sshd.8 -index 2aa732717..049d0a945 100644 +index 0226a8303..e2d8ff003 100644 --- a/sshd.8 +++ b/sshd.8 @@ -286,6 +286,7 @@ Finally, the server and the client enter an authentication dialog. diff --git a/0013-openssh-7.7p1-gssapi-new-unique.patch b/0013-openssh-7.7p1-gssapi-new-unique.patch index cd10771..89fb40d 100644 --- a/0013-openssh-7.7p1-gssapi-new-unique.patch +++ b/0013-openssh-7.7p1-gssapi-new-unique.patch @@ -1,4 +1,4 @@ -From ecc21a6a6d63b033a649f2446e2d2d38c19ae129 Mon Sep 17 00:00:00 2001 +From 1a5b32dbf550467a4ae19351667bcfdf9c52e44d Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 13/53] openssh-7.7p1-gssapi-new-unique @@ -17,7 +17,7 @@ Subject: [PATCH 13/53] openssh-7.7p1-gssapi-new-unique 10 files changed, 279 insertions(+), 71 deletions(-) diff --git a/auth-krb5.c b/auth-krb5.c -index c99e4e430..77714e3de 100644 +index 9d2f1f0ea..035032221 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -51,6 +51,7 @@ @@ -475,7 +475,7 @@ index 14502c5a6..df55512d3 100644 int diff --git a/gss-serv.c b/gss-serv.c -index a5cca7973..9d5435eda 100644 +index 6bac42931..d2bc03486 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -414,13 +414,15 @@ ssh_gssapi_cleanup_creds(void) @@ -508,10 +508,10 @@ index a5cca7973..9d5435eda 100644 ok = mm_ssh_gssapi_update_creds(&gssapi_client.store); diff --git a/servconf.c b/servconf.c -index d4f7fd66f..55aa5bf02 100644 +index 3b93ca829..7bf1507df 100644 --- a/servconf.c +++ b/servconf.c -@@ -138,6 +138,7 @@ initialize_server_options(ServerOptions *options) +@@ -136,6 +136,7 @@ initialize_server_options(ServerOptions *options) options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; @@ -519,7 +519,7 @@ index d4f7fd66f..55aa5bf02 100644 options->gss_authentication=-1; options->gss_keyex = -1; options->gss_cleanup_creds = -1; -@@ -382,6 +383,8 @@ fill_default_server_options(ServerOptions *options) +@@ -376,6 +377,8 @@ fill_default_server_options(ServerOptions *options) options->kerberos_ticket_cleanup = 1; if (options->kerberos_get_afs_token == -1) options->kerberos_get_afs_token = 0; @@ -528,7 +528,7 @@ index d4f7fd66f..55aa5bf02 100644 if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_keyex == -1) -@@ -564,7 +567,7 @@ typedef enum { +@@ -558,7 +561,7 @@ typedef enum { sPort, sHostKeyFile, sLoginGraceTime, sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, @@ -537,7 +537,7 @@ index d4f7fd66f..55aa5bf02 100644 sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, -@@ -655,11 +658,13 @@ static struct { +@@ -649,11 +652,13 @@ static struct { #else { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif @@ -551,7 +551,7 @@ index d4f7fd66f..55aa5bf02 100644 #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, -@@ -1668,6 +1673,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1662,6 +1667,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->kerberos_get_afs_token; goto parse_flag; @@ -562,7 +562,7 @@ index d4f7fd66f..55aa5bf02 100644 case sGssAuthentication: intptr = &options->gss_authentication; goto parse_flag; -@@ -3293,6 +3302,7 @@ dump_config(ServerOptions *o) +@@ -3295,6 +3304,7 @@ dump_config(ServerOptions *o) # ifdef USE_AFS dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif @@ -584,10 +584,10 @@ index c3f501400..a4a38d6d7 100644 int gss_keyex; /* If true, permit GSSAPI key exchange */ int gss_cleanup_creds; /* If true, destroy cred cache on logout */ diff --git a/session.c b/session.c -index 40f36af17..c095a483a 100644 +index 3eae5bdf3..b8a2dae92 100644 --- a/session.c +++ b/session.c -@@ -1025,7 +1025,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) +@@ -987,7 +987,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) /* Allow any GSSAPI methods that we've used to alter * the child's environment as they see fit */ @@ -597,7 +597,7 @@ index 40f36af17..c095a483a 100644 #endif /* Set basic environment. */ -@@ -1101,7 +1102,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) +@@ -1063,7 +1064,7 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) } #endif #ifdef KRB5 @@ -629,10 +629,10 @@ index db34d77f4..a894e23c9 100644 char *ssh_gssapi_server_mechanisms(void); diff --git a/sshd-session.c b/sshd-session.c -index 3cfe71806..1e15d4f0a 100644 +index 6e28020e9..028d5850e 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -1349,7 +1349,7 @@ main(int ac, char **av) +@@ -1327,7 +1327,7 @@ main(int ac, char **av) #ifdef GSSAPI if (options.gss_authentication) { temporarily_use_uid(authctxt->pw); @@ -642,10 +642,10 @@ index 3cfe71806..1e15d4f0a 100644 } #endif diff --git a/sshd_config.5 b/sshd_config.5 -index 8bc6586e6..1251d4d54 100644 +index b90068bf3..cae0fd0b4 100644 --- a/sshd_config.5 +++ b/sshd_config.5 -@@ -1033,6 +1033,14 @@ Specifies whether to automatically destroy the user's ticket cache +@@ -1032,6 +1032,14 @@ Specifies whether to automatically destroy the user's ticket cache file on logout. The default is .Cm yes . diff --git a/0014-openssh-7.2p2-k5login_directory.patch b/0014-openssh-7.2p2-k5login_directory.patch index 6984887..fa07e55 100644 --- a/0014-openssh-7.2p2-k5login_directory.patch +++ b/0014-openssh-7.2p2-k5login_directory.patch @@ -1,4 +1,4 @@ -From 30824076a227458d225a8b0e3c64771e8ac8fb75 Mon Sep 17 00:00:00 2001 +From 0b19c3dabb1e23837238e90238f1ab5fa3c99df8 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 14/53] openssh-7.2p2-k5login_directory @@ -11,7 +11,7 @@ Subject: [PATCH 14/53] openssh-7.2p2-k5login_directory 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/auth-krb5.c b/auth-krb5.c -index 77714e3de..74f56d47f 100644 +index 035032221..4910aa38a 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -465,5 +465,21 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm @@ -83,7 +83,7 @@ index df55512d3..820f794cf 100644 } diff --git a/sshd.8 b/sshd.8 -index 049d0a945..6784286dc 100644 +index e2d8ff003..fa33f5232 100644 --- a/sshd.8 +++ b/sshd.8 @@ -880,6 +880,10 @@ rlogin/rsh. diff --git a/0015-openssh-6.6p1-kuserok.patch b/0015-openssh-6.6p1-kuserok.patch index 5ddd72b..a403c7c 100644 --- a/0015-openssh-6.6p1-kuserok.patch +++ b/0015-openssh-6.6p1-kuserok.patch @@ -1,4 +1,4 @@ -From 44a1791e7f1ae1791e14e0974314d6016bec004a Mon Sep 17 00:00:00 2001 +From d0c2e8ddde548c79144547152b523346ae9f0358 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 15/53] openssh-6.6p1-kuserok @@ -13,7 +13,7 @@ Subject: [PATCH 15/53] openssh-6.6p1-kuserok 6 files changed, 139 insertions(+), 7 deletions(-) diff --git a/auth-krb5.c b/auth-krb5.c -index 74f56d47f..bae153c93 100644 +index 4910aa38a..b9c261a24 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -55,6 +55,21 @@ @@ -189,10 +189,10 @@ index 820f794cf..187faf929 100644 if ((fp = fopen(file, "r")) == NULL) { int saved_errno = errno; diff --git a/servconf.c b/servconf.c -index 55aa5bf02..5dd5ca213 100644 +index 7bf1507df..8f4b2b43e 100644 --- a/servconf.c +++ b/servconf.c -@@ -145,6 +145,7 @@ initialize_server_options(ServerOptions *options) +@@ -143,6 +143,7 @@ initialize_server_options(ServerOptions *options) options->gss_strict_acceptor = -1; options->gss_store_rekey = -1; options->gss_kex_algorithms = NULL; @@ -200,7 +200,7 @@ index 55aa5bf02..5dd5ca213 100644 options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; -@@ -399,6 +400,8 @@ fill_default_server_options(ServerOptions *options) +@@ -393,6 +394,8 @@ fill_default_server_options(ServerOptions *options) if (options->gss_kex_algorithms == NULL) options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX); #endif @@ -209,7 +209,7 @@ index 55aa5bf02..5dd5ca213 100644 if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -567,7 +570,7 @@ typedef enum { +@@ -561,7 +564,7 @@ typedef enum { sPort, sHostKeyFile, sLoginGraceTime, sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, @@ -218,7 +218,7 @@ index 55aa5bf02..5dd5ca213 100644 sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost, -@@ -659,12 +662,14 @@ static struct { +@@ -653,12 +656,14 @@ static struct { { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif { "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL }, @@ -233,7 +233,7 @@ index 55aa5bf02..5dd5ca213 100644 #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, -@@ -2441,6 +2446,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -2431,6 +2436,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, } break; @@ -244,7 +244,7 @@ index 55aa5bf02..5dd5ca213 100644 case sMatch: if (cmdline) fatal("Match directive not supported as a command-line " -@@ -2995,6 +3004,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) +@@ -2997,6 +3006,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(client_alive_interval); M_CP_INTOPT(ip_qos_interactive); M_CP_INTOPT(ip_qos_bulk); @@ -252,7 +252,7 @@ index 55aa5bf02..5dd5ca213 100644 M_CP_INTOPT(rekey_limit); M_CP_INTOPT(rekey_interval); M_CP_INTOPT(log_level); -@@ -3303,6 +3313,7 @@ dump_config(ServerOptions *o) +@@ -3305,6 +3315,7 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache); @@ -285,10 +285,10 @@ index 8db9f0fb1..ea5a878e6 100644 # GSSAPI options #GSSAPIAuthentication no diff --git a/sshd_config.5 b/sshd_config.5 -index 1251d4d54..0fcb409a6 100644 +index cae0fd0b4..c360fcfff 100644 --- a/sshd_config.5 +++ b/sshd_config.5 -@@ -1041,6 +1041,10 @@ The default value +@@ -1040,6 +1040,10 @@ The default value .Cm no can lead to overwriting previous tickets by subseqent connections to the same user account. @@ -299,7 +299,7 @@ index 1251d4d54..0fcb409a6 100644 .It Cm KexAlgorithms Specifies the permitted KEX (Key Exchange) algorithms that the server will offer to clients. -@@ -1355,6 +1359,7 @@ Available keywords are +@@ -1354,6 +1358,7 @@ Available keywords are .Cm IPQoS , .Cm KbdInteractiveAuthentication , .Cm KerberosAuthentication , diff --git a/0016-openssh-6.4p1-fromto-remote.patch b/0016-openssh-6.4p1-fromto-remote.patch index 903b03f..2a2575e 100644 --- a/0016-openssh-6.4p1-fromto-remote.patch +++ b/0016-openssh-6.4p1-fromto-remote.patch @@ -1,4 +1,4 @@ -From 5ade3deb755112e2062bd9ca136b6faee48cfee0 Mon Sep 17 00:00:00 2001 +From d755d647c33f96cd4ec7d5499d11ecd443bdb098 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 16/53] openssh-6.4p1-fromto-remote @@ -8,10 +8,10 @@ Subject: [PATCH 16/53] openssh-6.4p1-fromto-remote 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scp.c b/scp.c -index 57c242ffc..716ae386b 100644 +index c5f573cc1..d97a54cc4 100644 --- a/scp.c +++ b/scp.c -@@ -1162,7 +1162,10 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) +@@ -1148,7 +1148,10 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) addargs(&alist, "%s", ssh_program); addargs(&alist, "-x"); addargs(&alist, "-oClearAllForwardings=yes"); diff --git a/0017-openssh-6.6.1p1-log-in-chroot.patch b/0017-openssh-6.6.1p1-log-in-chroot.patch index de5a784..6704616 100644 --- a/0017-openssh-6.6.1p1-log-in-chroot.patch +++ b/0017-openssh-6.6.1p1-log-in-chroot.patch @@ -1,4 +1,4 @@ -From a1509d4351de8bd1f8d85cdb9a7958000c10a4e2 Mon Sep 17 00:00:00 2001 +From 674851677d1e38cf6992948f8f452e46107a2014 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 17/53] openssh-6.6.1p1-log-in-chroot @@ -16,7 +16,7 @@ Subject: [PATCH 17/53] openssh-6.6.1p1-log-in-chroot 9 files changed, 52 insertions(+), 22 deletions(-) diff --git a/log.c b/log.c -index 6617f2672..9782cfb06 100644 +index 5969c4a16..49b0c8a68 100644 --- a/log.c +++ b/log.c @@ -196,6 +196,11 @@ void @@ -57,10 +57,10 @@ index 8e8dfc23f..70048a8af 100644 int log_change_level(LogLevel); int log_is_on_stderr(void); diff --git a/monitor.c b/monitor.c -index 2ef16cc8e..43c10a4ec 100644 +index d463d6a9c..453469665 100644 --- a/monitor.c +++ b/monitor.c -@@ -2001,9 +2001,22 @@ monitor_init(void) +@@ -2007,9 +2007,22 @@ monitor_init(void) } void @@ -99,10 +99,10 @@ index dbc7e0037..d4d631ddc 100644 struct Authctxt; void monitor_child_preauth(struct ssh *, struct monitor *); diff --git a/session.c b/session.c -index c095a483a..dab771d3f 100644 +index b8a2dae92..d034f5c65 100644 --- a/session.c +++ b/session.c -@@ -169,6 +169,7 @@ login_cap_t *lc; +@@ -162,6 +162,7 @@ login_cap_t *lc; static int is_child = 0; static int in_chroot = 0; @@ -110,7 +110,7 @@ index c095a483a..dab771d3f 100644 /* File containing userauth info, if ExposeAuthInfo set */ static char *auth_info_file = NULL; -@@ -670,6 +671,7 @@ do_exec(struct ssh *ssh, Session *s, const char *command) +@@ -632,6 +633,7 @@ do_exec(struct ssh *ssh, Session *s, const char *command) int ret; const char *forced = NULL, *tty = NULL; char session_type[1024]; @@ -118,7 +118,7 @@ index c095a483a..dab771d3f 100644 if (options.adm_forced_command) { original_command = command; -@@ -729,6 +731,10 @@ do_exec(struct ssh *ssh, Session *s, const char *command) +@@ -691,6 +693,10 @@ do_exec(struct ssh *ssh, Session *s, const char *command) tty += 5; } @@ -129,7 +129,7 @@ index c095a483a..dab771d3f 100644 verbose("Starting session: %s%s%s for %s from %.200s port %d id %d", session_type, tty == NULL ? "" : " on ", -@@ -1507,14 +1513,6 @@ child_close_fds(struct ssh *ssh) +@@ -1469,14 +1475,6 @@ child_close_fds(struct ssh *ssh) /* Stop directing logs to a high-numbered fd before we close it */ log_redirect_stderr_to(NULL); @@ -144,7 +144,7 @@ index c095a483a..dab771d3f 100644 } /* -@@ -1647,8 +1645,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) +@@ -1609,8 +1607,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) exit(1); } @@ -153,7 +153,7 @@ index c095a483a..dab771d3f 100644 do_rc_files(ssh, s, shell); /* restore SIGPIPE for child */ -@@ -1676,9 +1672,17 @@ do_child(struct ssh *ssh, Session *s, const char *command) +@@ -1638,9 +1634,17 @@ do_child(struct ssh *ssh, Session *s, const char *command) #ifdef WITH_SELINUX ssh_selinux_change_context("sftpd_t"); #endif @@ -184,10 +184,10 @@ index 2c70f89bc..bbb79f278 100644 + return (sftp_server_main(argc, argv, user_pw, 0)); } diff --git a/sftp-server.c b/sftp-server.c -index a4abb9f7c..4985da38f 100644 +index 777821acd..185ad1459 100644 --- a/sftp-server.c +++ b/sftp-server.c -@@ -1901,7 +1901,7 @@ sftp_server_usage(void) +@@ -1897,7 +1897,7 @@ sftp_server_usage(void) } int @@ -196,7 +196,7 @@ index a4abb9f7c..4985da38f 100644 { int i, r, in, out, ch, skipargs = 0, log_stderr = 0; ssize_t len, olen; -@@ -1913,7 +1913,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) +@@ -1909,7 +1909,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) extern char *__progname; __progname = ssh_get_progname(argv[0]); @@ -205,7 +205,7 @@ index a4abb9f7c..4985da38f 100644 pw = pwcopy(user_pw); -@@ -1986,7 +1986,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) +@@ -1982,7 +1982,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw) } } @@ -226,10 +226,10 @@ index 2bde8bb7f..ddf1a3968 100644 +int sftp_server_main(int, char **, struct passwd *, int); void sftp_server_cleanup_exit(int) __attribute__((noreturn)); diff --git a/sshd-session.c b/sshd-session.c -index 1e15d4f0a..87b6122b0 100644 +index 028d5850e..4a5eaa1ff 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -437,7 +437,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) +@@ -415,7 +415,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) #endif /* New socket pair */ @@ -238,7 +238,7 @@ index 1e15d4f0a..87b6122b0 100644 pmonitor->m_pid = fork(); if (pmonitor->m_pid == -1) -@@ -456,6 +456,11 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) +@@ -434,6 +434,11 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) close(pmonitor->m_sendfd); pmonitor->m_sendfd = -1; diff --git a/0018-openssh-6.6.1p1-scp-non-existing-directory.patch b/0018-openssh-6.6.1p1-scp-non-existing-directory.patch index 1c4f2c1..e50e1c2 100644 --- a/0018-openssh-6.6.1p1-scp-non-existing-directory.patch +++ b/0018-openssh-6.6.1p1-scp-non-existing-directory.patch @@ -1,4 +1,4 @@ -From 4cf88a3767f326788a795fde687f80b97e4a0964 Mon Sep 17 00:00:00 2001 +From 931f22f77ab2b9cebd96e113f1e3ab179dd1b6cb Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 18/53] openssh-6.6.1p1-scp-non-existing-directory @@ -8,10 +8,10 @@ Subject: [PATCH 18/53] openssh-6.6.1p1-scp-non-existing-directory 1 file changed, 4 insertions(+) diff --git a/scp.c b/scp.c -index 716ae386b..9554b188b 100644 +index d97a54cc4..e1992622f 100644 --- a/scp.c +++ b/scp.c -@@ -1876,6 +1876,10 @@ sink(int argc, char **argv, const char *src) +@@ -1866,6 +1866,10 @@ sink(int argc, char **argv, const char *src) free(vect[0]); continue; } diff --git a/0019-openssh-6.6p1-GSSAPIEnablek5users.patch b/0019-openssh-6.6p1-GSSAPIEnablek5users.patch index 4f500e0..4c0a60b 100644 --- a/0019-openssh-6.6p1-GSSAPIEnablek5users.patch +++ b/0019-openssh-6.6p1-GSSAPIEnablek5users.patch @@ -1,4 +1,4 @@ -From b14be52d0033c535732efa76f4b416e8a0d97b74 Mon Sep 17 00:00:00 2001 +From ef91c84a26a282adaf95e165ebcdd44a410c4328 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 19/53] openssh-6.6p1-GSSAPIEnablek5users @@ -33,10 +33,10 @@ index 187faf929..03188d9b3 100644 k5login_exists); } diff --git a/servconf.c b/servconf.c -index 5dd5ca213..c0de71108 100644 +index 8f4b2b43e..5e40f1b00 100644 --- a/servconf.c +++ b/servconf.c -@@ -146,6 +146,7 @@ initialize_server_options(ServerOptions *options) +@@ -144,6 +144,7 @@ initialize_server_options(ServerOptions *options) options->gss_store_rekey = -1; options->gss_kex_algorithms = NULL; options->use_kuserok = -1; @@ -44,7 +44,7 @@ index 5dd5ca213..c0de71108 100644 options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->permit_empty_passwd = -1; -@@ -402,6 +403,8 @@ fill_default_server_options(ServerOptions *options) +@@ -396,6 +397,8 @@ fill_default_server_options(ServerOptions *options) #endif if (options->use_kuserok == -1) options->use_kuserok = 1; @@ -53,7 +53,7 @@ index 5dd5ca213..c0de71108 100644 if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -585,7 +588,7 @@ typedef enum { +@@ -579,7 +582,7 @@ typedef enum { sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, @@ -62,7 +62,7 @@ index 5dd5ca213..c0de71108 100644 sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, -@@ -681,6 +684,7 @@ static struct { +@@ -675,6 +678,7 @@ static struct { { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, @@ -70,7 +70,7 @@ index 5dd5ca213..c0de71108 100644 #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, -@@ -689,6 +693,7 @@ static struct { +@@ -683,6 +687,7 @@ static struct { { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL }, @@ -78,7 +78,7 @@ index 5dd5ca213..c0de71108 100644 #endif { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, -@@ -2450,6 +2455,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -2440,6 +2445,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->use_kuserok; goto parse_flag; @@ -89,7 +89,7 @@ index 5dd5ca213..c0de71108 100644 case sMatch: if (cmdline) fatal("Match directive not supported as a command-line " -@@ -3005,6 +3014,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) +@@ -3007,6 +3016,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(ip_qos_interactive); M_CP_INTOPT(ip_qos_bulk); M_CP_INTOPT(use_kuserok); @@ -97,7 +97,7 @@ index 5dd5ca213..c0de71108 100644 M_CP_INTOPT(rekey_limit); M_CP_INTOPT(rekey_interval); M_CP_INTOPT(log_level); -@@ -3314,6 +3324,7 @@ dump_config(ServerOptions *o) +@@ -3316,6 +3326,7 @@ dump_config(ServerOptions *o) # endif dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache); dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); @@ -130,7 +130,7 @@ index ea5a878e6..33713c886 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 0fcb409a6..fe246fc21 100644 +index c360fcfff..a0fc6064f 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -739,6 +739,12 @@ Specifies whether to automatically destroy the user's credentials cache diff --git a/0020-openssh-6.8p1-sshdT-output.patch b/0020-openssh-6.8p1-sshdT-output.patch index 86b77ed..ed2379e 100644 --- a/0020-openssh-6.8p1-sshdT-output.patch +++ b/0020-openssh-6.8p1-sshdT-output.patch @@ -1,4 +1,4 @@ -From 18402a4f528d772e71d01cbd5d2a0dffb048fd89 Mon Sep 17 00:00:00 2001 +From cce18d636f4137a4e5401170538868b8b80651c1 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 20/53] openssh-6.8p1-sshdT-output @@ -8,10 +8,10 @@ Subject: [PATCH 20/53] openssh-6.8p1-sshdT-output 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/servconf.c b/servconf.c -index c0de71108..105e301d9 100644 +index 5e40f1b00..b63a7f0b0 100644 --- a/servconf.c +++ b/servconf.c -@@ -3366,7 +3366,7 @@ dump_config(ServerOptions *o) +@@ -3368,7 +3368,7 @@ dump_config(ServerOptions *o) dump_cfg_string(sXAuthLocation, o->xauth_location); dump_cfg_string(sCiphers, o->ciphers); dump_cfg_string(sMacs, o->macs); diff --git a/0021-openssh-6.7p1-sftp-force-permission.patch b/0021-openssh-6.7p1-sftp-force-permission.patch index 0cb6915..737430d 100644 --- a/0021-openssh-6.7p1-sftp-force-permission.patch +++ b/0021-openssh-6.7p1-sftp-force-permission.patch @@ -1,4 +1,4 @@ -From 2ea1fc3bf0996b06bb0fa6c41b2e1d49d4f203be Mon Sep 17 00:00:00 2001 +From 57ae33c2f43425725345c910d90ef6fed75d3b85 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 21/53] openssh-6.7p1-sftp-force-permission @@ -34,10 +34,10 @@ index 5311bf929..5e6e3aa44 100644 .Pp On some systems, diff --git a/sftp-server.c b/sftp-server.c -index 4985da38f..6ed1c27fa 100644 +index 185ad1459..e04fc63b3 100644 --- a/sftp-server.c +++ b/sftp-server.c -@@ -76,6 +76,10 @@ struct sshbuf *oqueue; +@@ -72,6 +72,10 @@ struct sshbuf *oqueue; /* Version of client */ static u_int version; @@ -48,7 +48,7 @@ index 4985da38f..6ed1c27fa 100644 /* SSH2_FXP_INIT received */ static int init_done; -@@ -745,6 +749,7 @@ process_open(u_int32_t id) +@@ -741,6 +745,7 @@ process_open(u_int32_t id) Attrib a; char *name; int r, handle, fd, flags, mode, status = SSH2_FX_FAILURE; @@ -56,7 +56,7 @@ index 4985da38f..6ed1c27fa 100644 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 || (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ -@@ -754,6 +759,10 @@ process_open(u_int32_t id) +@@ -750,6 +755,10 @@ process_open(u_int32_t id) debug3("request %u: open flags %d", id, pflags); flags = flags_from_portable(pflags); mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm : 0666; @@ -67,7 +67,7 @@ index 4985da38f..6ed1c27fa 100644 logit("open \"%s\" flags %s mode 0%o", name, string_from_portable(pflags), mode); if (readonly && -@@ -775,6 +784,8 @@ process_open(u_int32_t id) +@@ -771,6 +780,8 @@ process_open(u_int32_t id) } } } @@ -76,7 +76,7 @@ index 4985da38f..6ed1c27fa 100644 if (status != SSH2_FX_OK) send_status(id, status); free(name); -@@ -1894,7 +1905,7 @@ sftp_server_usage(void) +@@ -1890,7 +1901,7 @@ sftp_server_usage(void) fprintf(stderr, "usage: %s [-ehR] [-d start_directory] [-f log_facility] " "[-l log_level]\n\t[-P denied_requests] " @@ -85,7 +85,7 @@ index 4985da38f..6ed1c27fa 100644 " %s -Q protocol_feature\n", __progname, __progname); exit(1); -@@ -1918,7 +1929,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle +@@ -1914,7 +1925,7 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle pw = pwcopy(user_pw); while (!skipargs && (ch = getopt(argc, argv, @@ -94,7 +94,7 @@ index 4985da38f..6ed1c27fa 100644 switch (ch) { case 'Q': if (strcasecmp(optarg, "requests") != 0) { -@@ -1980,6 +1991,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle +@@ -1976,6 +1987,15 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle fatal("Invalid umask \"%s\"", optarg); (void)umask((mode_t)mask); break; diff --git a/0022-openssh-7.2p2-s390-closefrom.patch b/0022-openssh-7.2p2-s390-closefrom.patch index cd939d7..fa59fd6 100644 --- a/0022-openssh-7.2p2-s390-closefrom.patch +++ b/0022-openssh-7.2p2-s390-closefrom.patch @@ -1,4 +1,4 @@ -From dea189d1c1ed7d206db52cd6dcf72388c0ff5778 Mon Sep 17 00:00:00 2001 +From 25b593f41fa85bcaf1bbdc9c368325c4af033208 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 Subject: [PATCH 22/53] openssh-7.2p2-s390-closefrom diff --git a/0024-openssh-7.6p1-cleanup-selinux.patch b/0023-openssh-7.6p1-cleanup-selinux.patch similarity index 91% rename from 0024-openssh-7.6p1-cleanup-selinux.patch rename to 0023-openssh-7.6p1-cleanup-selinux.patch index a618fd1..d018772 100644 --- a/0024-openssh-7.6p1-cleanup-selinux.patch +++ b/0023-openssh-7.6p1-cleanup-selinux.patch @@ -1,7 +1,7 @@ -From 41acb1470333db97ed767b3459c6b34ccb84ec73 Mon Sep 17 00:00:00 2001 +From 4cacb1bda51a2d91cf4cc1c8058b989dfc0c58c8 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 24/53] openssh-7.6p1-cleanup-selinux +Subject: [PATCH 23/53] openssh-7.6p1-cleanup-selinux --- auth2-pubkey.c | 8 ++++-- @@ -16,10 +16,10 @@ Subject: [PATCH 24/53] openssh-7.6p1-cleanup-selinux 9 files changed, 46 insertions(+), 32 deletions(-) diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index 267a27d24..0d5ae0df7 100644 +index c326a69ba..b7300ca9e 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c -@@ -77,6 +77,8 @@ +@@ -75,6 +75,8 @@ /* import */ extern ServerOptions options; @@ -28,7 +28,7 @@ index 267a27d24..0d5ae0df7 100644 extern struct authmethod_cfg methodcfg_pubkey; static char * -@@ -485,7 +487,8 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key, +@@ -483,7 +485,8 @@ match_principals_command(struct passwd *user_pw, const struct sshkey *key, if ((pid = subprocess("AuthorizedPrincipalsCommand", command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, @@ -38,7 +38,7 @@ index 267a27d24..0d5ae0df7 100644 goto out; uid_swapped = 1; -@@ -755,7 +758,8 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key, +@@ -759,7 +762,8 @@ user_key_command_allowed2(struct passwd *user_pw, struct sshkey *key, if ((pid = subprocess("AuthorizedKeysCommand", command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD, @@ -49,10 +49,10 @@ index 267a27d24..0d5ae0df7 100644 uid_swapped = 1; diff --git a/misc.c b/misc.c -index 1e31acc95..097229620 100644 +index 7e27a38d1..2fd14159d 100644 --- a/misc.c +++ b/misc.c -@@ -2764,7 +2764,8 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) +@@ -2788,7 +2788,8 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) pid_t subprocess(const char *tag, const char *command, int ac, char **av, FILE **child, u_int flags, @@ -62,7 +62,7 @@ index 1e31acc95..097229620 100644 { FILE *f = NULL; struct stat st; -@@ -2898,7 +2899,7 @@ subprocess(const char *tag, const char *command, +@@ -2922,7 +2923,7 @@ subprocess(const char *tag, const char *command, _exit(1); } #ifdef WITH_SELINUX @@ -72,10 +72,10 @@ index 1e31acc95..097229620 100644 strerror(errno)); _exit(127); diff --git a/misc.h b/misc.h -index efecdf1ad..9efa9cf47 100644 +index f3c5a18c6..8cdfd7cec 100644 --- a/misc.h +++ b/misc.h -@@ -122,7 +122,7 @@ typedef void privrestore_fn(void); +@@ -124,7 +124,7 @@ typedef void privrestore_fn(void); #define SSH_SUBPROCESS_UNSAFE_PATH (1<<3) /* Don't check for safe cmd */ #define SSH_SUBPROCESS_PRESERVE_ENV (1<<4) /* Keep parent environment */ pid_t subprocess(const char *, const char *, int, char **, FILE **, u_int, @@ -235,7 +235,7 @@ index c004071d1..26c5f773b 100644 #ifdef LINUX_OOM_ADJUST diff --git a/platform.c b/platform.c -index 0d12f3111..f0800b1fc 100644 +index c92a0cba6..66d0c2a6b 100644 --- a/platform.c +++ b/platform.c @@ -33,6 +33,8 @@ @@ -259,10 +259,10 @@ index 0d12f3111..f0800b1fc 100644 } diff --git a/sshconnect.c b/sshconnect.c -index c86182d13..040848105 100644 +index 912a520c5..babe4a982 100644 --- a/sshconnect.c +++ b/sshconnect.c -@@ -925,7 +925,7 @@ load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template, +@@ -917,7 +917,7 @@ load_hostkeys_command(struct hostkeys *hostkeys, const char *command_template, if ((pid = subprocess(tag, command, ac, av, &f, SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_UNSAFE_PATH| @@ -272,10 +272,10 @@ index c86182d13..040848105 100644 load_hostkeys_file(hostkeys, hostfile_hostname, tag, f, 1); diff --git a/sshd-auth.c b/sshd-auth.c -index 62f1dc808..de61be5ac 100644 +index 5a4ee733c..f3c38a7d1 100644 --- a/sshd-auth.c +++ b/sshd-auth.c -@@ -122,7 +122,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; +@@ -120,7 +120,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; int debug_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ @@ -285,10 +285,10 @@ index 62f1dc808..de61be5ac 100644 /* Saved arguments to main(). */ static char **saved_argv; diff --git a/sshd-session.c b/sshd-session.c -index 87b6122b0..e86acf704 100644 +index 4a5eaa1ff..d6bece941 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -136,7 +136,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; +@@ -130,7 +130,7 @@ char *config_file_name = _PATH_SERVER_CONFIG_FILE; int debug_flag = 0; /* Flag indicating that the daemon is being started from inetd. */ @@ -297,7 +297,7 @@ index 87b6122b0..e86acf704 100644 /* debug goes to stderr unless inetd_flag is set */ static int log_stderr = 0; -@@ -1359,7 +1359,9 @@ main(int ac, char **av) +@@ -1337,7 +1337,9 @@ main(int ac, char **av) } #endif #ifdef WITH_SELINUX diff --git a/0025-openssh-7.5p1-sandbox.patch b/0024-openssh-7.5p1-sandbox.patch similarity index 76% rename from 0025-openssh-7.5p1-sandbox.patch rename to 0024-openssh-7.5p1-sandbox.patch index 82fda78..32b56db 100644 --- a/0025-openssh-7.5p1-sandbox.patch +++ b/0024-openssh-7.5p1-sandbox.patch @@ -1,17 +1,17 @@ -From 5cb527355936245bfb90aef0fddd23146b134772 Mon Sep 17 00:00:00 2001 +From 503297ec6f6eef3bb4906271d170fab848e27298 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 25/53] openssh-7.5p1-sandbox +Subject: [PATCH 24/53] openssh-7.5p1-sandbox --- sandbox-seccomp-filter.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index b31062c2b..1fabf99d0 100644 +index a0692dd2f..e0f2d4289 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c -@@ -277,6 +277,9 @@ static const struct sock_filter preauth_insns[] = { +@@ -305,6 +305,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_exit_group SC_ALLOW(__NR_exit_group), #endif @@ -21,7 +21,7 @@ index b31062c2b..1fabf99d0 100644 #ifdef __NR_futex SC_FUTEX(__NR_futex), #endif -@@ -295,6 +298,21 @@ static const struct sock_filter preauth_insns[] = { +@@ -323,6 +326,21 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_getpid SC_ALLOW(__NR_getpid), #endif @@ -43,7 +43,7 @@ index b31062c2b..1fabf99d0 100644 #ifdef __NR_getrandom SC_ALLOW(__NR_getrandom), #endif -@@ -304,6 +322,9 @@ static const struct sock_filter preauth_insns[] = { +@@ -332,6 +350,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_gettimeofday SC_ALLOW(__NR_gettimeofday), #endif diff --git a/0027-openssh-7.8p1-scp-ipv6.patch b/0025-openssh-7.8p1-scp-ipv6.patch similarity index 75% rename from 0027-openssh-7.8p1-scp-ipv6.patch rename to 0025-openssh-7.8p1-scp-ipv6.patch index 3070ed2..d1eb51a 100644 --- a/0027-openssh-7.8p1-scp-ipv6.patch +++ b/0025-openssh-7.8p1-scp-ipv6.patch @@ -1,17 +1,17 @@ -From e364c7688e94903c894533d4c09f6441f8ddd482 Mon Sep 17 00:00:00 2001 +From e1d86d265d9543c77fa90a33acc70246e68bf3bf Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 27/53] openssh-7.8p1-scp-ipv6 +Subject: [PATCH 25/53] openssh-7.8p1-scp-ipv6 --- scp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scp.c b/scp.c -index 9554b188b..7f9795a57 100644 +index e1992622f..621131ffc 100644 --- a/scp.c +++ b/scp.c -@@ -1183,7 +1183,9 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) +@@ -1169,7 +1169,9 @@ toremote(int argc, char **argv, enum scp_mode_e mode, char *sftp_direct) addargs(&alist, "%s", host); addargs(&alist, "%s", cmd); addargs(&alist, "%s", src); diff --git a/0028-openssh-8.0p1-crypto-policies.patch b/0026-openssh-8.0p1-crypto-policies.patch similarity index 96% rename from 0028-openssh-8.0p1-crypto-policies.patch rename to 0026-openssh-8.0p1-crypto-policies.patch index 35f4b24..5162ffa 100644 --- a/0028-openssh-8.0p1-crypto-policies.patch +++ b/0026-openssh-8.0p1-crypto-policies.patch @@ -1,7 +1,7 @@ -From 3b68d7133cd457b36929735c5cc1b8c6483d930e Mon Sep 17 00:00:00 2001 +From 6d9e08f061451f6cd464af5ec598fa99d15acadb Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 28/53] openssh-8.0p1-crypto-policies +Subject: [PATCH 26/53] openssh-8.0p1-crypto-policies --- ssh_config.5 | 164 ++++++++++++++++++++------------------------- @@ -9,7 +9,7 @@ Subject: [PATCH 28/53] openssh-8.0p1-crypto-policies 2 files changed, 140 insertions(+), 203 deletions(-) diff --git a/ssh_config.5 b/ssh_config.5 -index 8d5d07222..a43b2a276 100644 +index 8a4b469cf..8ac5e1633 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -438,17 +438,13 @@ A single argument of @@ -166,7 +166,7 @@ index 8d5d07222..a43b2a276 100644 .It Cm HostKeyAlias Specifies an alias that should be used instead of the real host name when looking up or saving the host key -@@ -1376,6 +1373,11 @@ it may be zero or more of: +@@ -1360,6 +1357,11 @@ it may be zero or more of: and .Cm pam . .It Cm KexAlgorithms @@ -178,7 +178,7 @@ index 8d5d07222..a43b2a276 100644 Specifies the permitted KEX (Key Exchange) algorithms that will be used and their preference order. The selected algorithm will be the first algorithm in this list that -@@ -1384,29 +1386,17 @@ Multiple algorithms must be comma-separated. +@@ -1368,29 +1370,17 @@ Multiple algorithms must be comma-separated. .Pp If the specified list begins with a .Sq + @@ -212,7 +212,7 @@ index 8d5d07222..a43b2a276 100644 The list of supported key exchange algorithms may also be obtained using .Qq ssh -Q kex . .It Cm KnownHostsCommand -@@ -1522,37 +1512,33 @@ function, and all code in the +@@ -1506,37 +1496,33 @@ function, and all code in the file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs @@ -259,7 +259,7 @@ index 8d5d07222..a43b2a276 100644 The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm NoHostAuthenticationForLocalhost -@@ -1741,39 +1727,31 @@ instead of continuing to execute and pass data. +@@ -1725,39 +1711,31 @@ instead of continuing to execute and pass data. The default is .Cm no . .It Cm PubkeyAcceptedAlgorithms @@ -311,7 +311,7 @@ index 8d5d07222..a43b2a276 100644 .It Cm PubkeyAuthentication Specifies whether to try public key authentication. The argument to this keyword must be -@@ -2497,7 +2475,9 @@ for those users who do not have a configuration file. +@@ -2504,7 +2482,9 @@ for those users who do not have a configuration file. This file must be world-readable. .El .Sh SEE ALSO @@ -323,7 +323,7 @@ index 8d5d07222..a43b2a276 100644 .An -nosplit OpenSSH is a derivative of the original and free diff --git a/sshd_config.5 b/sshd_config.5 -index 26fcdc840..583a01cdb 100644 +index a0fc6064f..c172d5aab 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -379,17 +379,13 @@ If the argument is @@ -497,7 +497,7 @@ index 26fcdc840..583a01cdb 100644 The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts -@@ -1052,6 +1025,11 @@ Specifies whether to look at .k5login file for user's aliases. +@@ -1051,6 +1024,11 @@ Specifies whether to look at .k5login file for user's aliases. The default is .Cm yes . .It Cm KexAlgorithms @@ -509,7 +509,7 @@ index 26fcdc840..583a01cdb 100644 Specifies the permitted KEX (Key Exchange) algorithms that the server will offer to clients. The ordering of this list is not important, as the client specifies the -@@ -1060,16 +1038,16 @@ Multiple algorithms must be comma-separated. +@@ -1059,16 +1037,16 @@ Multiple algorithms must be comma-separated. .Pp If the specified list begins with a .Sq + @@ -530,7 +530,7 @@ index 26fcdc840..583a01cdb 100644 .Pp The supported algorithms are: .Pp -@@ -1106,14 +1084,6 @@ sntrup761x25519-sha512 +@@ -1105,14 +1083,6 @@ sntrup761x25519-sha512 sntrup761x25519-sha512@openssh.com .El .Pp @@ -545,7 +545,7 @@ index 26fcdc840..583a01cdb 100644 The list of supported key exchange algorithms may also be obtained using .Qq ssh -Q KexAlgorithms . .It Cm ListenAddress -@@ -1200,21 +1170,26 @@ function, and all code in the +@@ -1199,21 +1169,26 @@ function, and all code in the file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs @@ -576,7 +576,7 @@ index 26fcdc840..583a01cdb 100644 .Pp The algorithms that contain .Qq -etm -@@ -1257,15 +1232,6 @@ umac-64-etm@openssh.com +@@ -1256,15 +1231,6 @@ umac-64-etm@openssh.com umac-128-etm@openssh.com .El .Pp @@ -592,7 +592,7 @@ index 26fcdc840..583a01cdb 100644 The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm Match -@@ -1753,36 +1719,25 @@ or equivalent.) +@@ -1751,36 +1717,25 @@ or equivalent.) The default is .Cm yes . .It Cm PubkeyAcceptedAlgorithms @@ -638,7 +638,7 @@ index 26fcdc840..583a01cdb 100644 .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . -@@ -2289,7 +2244,9 @@ This file should be writable by root only, but it is recommended +@@ -2281,7 +2236,9 @@ This file should be writable by root only, but it is recommended .El .Sh SEE ALSO .Xr sftp-server 8 , diff --git a/0029-openssh-8.0p1-openssl-kdf.patch b/0027-openssh-8.0p1-openssl-kdf.patch similarity index 90% rename from 0029-openssh-8.0p1-openssl-kdf.patch rename to 0027-openssh-8.0p1-openssl-kdf.patch index 9c7c06b..6f7f49b 100644 --- a/0029-openssh-8.0p1-openssl-kdf.patch +++ b/0027-openssh-8.0p1-openssl-kdf.patch @@ -1,7 +1,7 @@ -From e3fe562a76da5fed5dd7eaacd5645fd3afe972d3 Mon Sep 17 00:00:00 2001 +From d73633dd9770bea0c3802075842398faf3e55e30 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 29/53] openssh-8.0p1-openssl-kdf +Subject: [PATCH 27/53] openssh-8.0p1-openssl-kdf --- configure.ac | 1 + @@ -9,10 +9,10 @@ Subject: [PATCH 29/53] openssh-8.0p1-openssl-kdf 2 files changed, 108 insertions(+) diff --git a/configure.ac b/configure.ac -index d9bd2f516..d92a85809 100644 +index adccaebd4..805be4b5e 100644 --- a/configure.ac +++ b/configure.ac -@@ -3137,6 +3137,7 @@ if test "x$openssl" = "xyes" ; then +@@ -3182,6 +3182,7 @@ if test "x$openssl" = "xyes" ; then HMAC_CTX_init \ RSA_generate_key_ex \ RSA_get_default_method \ @@ -21,10 +21,10 @@ index d9bd2f516..d92a85809 100644 # OpenSSL_add_all_algorithms may be a macro. diff --git a/kex.c b/kex.c -index 19a56e8e9..8b200ff4a 100644 +index 9a2ce6d88..5f9530908 100644 --- a/kex.c +++ b/kex.c -@@ -40,6 +40,11 @@ +@@ -38,6 +38,11 @@ #ifdef WITH_OPENSSL #include #include @@ -36,7 +36,7 @@ index 19a56e8e9..8b200ff4a 100644 #endif #include "ssh.h" -@@ -1078,6 +1083,107 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) +@@ -1077,6 +1082,107 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) return r; } @@ -144,7 +144,7 @@ index 19a56e8e9..8b200ff4a 100644 static int derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, const struct sshbuf *shared_secret, u_char **keyp) -@@ -1141,6 +1247,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, +@@ -1140,6 +1246,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, ssh_digest_free(hashctx); return r; } diff --git a/0030-openssh-8.2p1-visibility.patch b/0028-openssh-8.2p1-visibility.patch similarity index 75% rename from 0030-openssh-8.2p1-visibility.patch rename to 0028-openssh-8.2p1-visibility.patch index 0bd9496..7c5eabf 100644 --- a/0030-openssh-8.2p1-visibility.patch +++ b/0028-openssh-8.2p1-visibility.patch @@ -1,17 +1,17 @@ -From 4fddbc429e679944b5f3bf93d5ba46d198bc868f Mon Sep 17 00:00:00 2001 +From ed5e5df9ec7ac96ac2a68c5711db00ed29d4d1cd Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 30/53] openssh-8.2p1-visibility +Subject: [PATCH 28/53] openssh-8.2p1-visibility --- regress/misc/sk-dummy/sk-dummy.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c -index 347b21227..344f8a8aa 100644 +index 4c96e8827..4af5209db 100644 --- a/regress/misc/sk-dummy/sk-dummy.c +++ b/regress/misc/sk-dummy/sk-dummy.c -@@ -81,7 +81,7 @@ skdebug(const char *func, const char *fmt, ...) +@@ -80,7 +80,7 @@ skdebug(const char *func, const char *fmt, ...) #endif } @@ -20,7 +20,7 @@ index 347b21227..344f8a8aa 100644 sk_api_version(void) { return SSH_SK_VERSION_MAJOR; -@@ -230,7 +230,7 @@ check_options(struct sk_option **options) +@@ -229,7 +229,7 @@ check_options(struct sk_option **options) return 0; } @@ -29,7 +29,7 @@ index 347b21227..344f8a8aa 100644 sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, const char *application, uint8_t flags, const char *pin, struct sk_option **options, struct sk_enroll_response **enroll_response) -@@ -478,7 +478,7 @@ sig_ed25519(const uint8_t *message, size_t message_len, +@@ -477,7 +477,7 @@ sig_ed25519(const uint8_t *message, size_t message_len, return ret; } @@ -38,7 +38,7 @@ index 347b21227..344f8a8aa 100644 sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, const char *application, const uint8_t *key_handle, size_t key_handle_len, uint8_t flags, const char *pin, struct sk_option **options, -@@ -535,7 +535,7 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, +@@ -534,7 +534,7 @@ sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, return ret; } diff --git a/0031-openssh-8.2p1-x11-without-ipv6.patch b/0029-openssh-8.2p1-x11-without-ipv6.patch similarity index 76% rename from 0031-openssh-8.2p1-x11-without-ipv6.patch rename to 0029-openssh-8.2p1-x11-without-ipv6.patch index 1f2d8b7..7063d7f 100644 --- a/0031-openssh-8.2p1-x11-without-ipv6.patch +++ b/0029-openssh-8.2p1-x11-without-ipv6.patch @@ -1,17 +1,17 @@ -From ee828e7c70d4bc7e3414703937317f208833ff0e Mon Sep 17 00:00:00 2001 +From c8dce0615eac6d2a724cdb3f288d7aaa1362f65b Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 31/53] openssh-8.2p1-x11-without-ipv6 +Subject: [PATCH 29/53] openssh-8.2p1-x11-without-ipv6 --- channels.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/channels.c b/channels.c -index 7438c1a58..95836d508 100644 +index 5ce6bd400..26ed9945f 100644 --- a/channels.c +++ b/channels.c -@@ -5055,6 +5055,16 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, +@@ -5123,6 +5123,16 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, debug2_f("bind port %d: %.100s", port, strerror(errno)); close(sock); diff --git a/0032-openssh-8.0p1-preserve-pam-errors.patch b/0030-openssh-8.0p1-preserve-pam-errors.patch similarity index 79% rename from 0032-openssh-8.0p1-preserve-pam-errors.patch rename to 0030-openssh-8.0p1-preserve-pam-errors.patch index 92777ce..4aa2ffb 100644 --- a/0032-openssh-8.0p1-preserve-pam-errors.patch +++ b/0030-openssh-8.0p1-preserve-pam-errors.patch @@ -1,17 +1,17 @@ -From 1aa49503ccce2e6390d9e7effacbaf695fa17e00 Mon Sep 17 00:00:00 2001 +From a3b6182e1d6b69a37a6c841baa43b818251036b1 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 32/53] openssh-8.0p1-preserve-pam-errors +Subject: [PATCH 30/53] openssh-8.0p1-preserve-pam-errors --- auth-pam.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/auth-pam.c b/auth-pam.c -index b4100ea1c..a042c3c8e 100644 +index 70bcae83a..70b2b8580 100644 --- a/auth-pam.c +++ b/auth-pam.c -@@ -523,7 +523,11 @@ sshpam_thread(void *ctxtp) +@@ -551,7 +551,11 @@ sshpam_thread(void *ctxtp) goto auth_fail; if (!do_pam_account()) { @@ -24,9 +24,9 @@ index b4100ea1c..a042c3c8e 100644 goto auth_fail; } if (sshpam_authctxt->force_pwchange) { -@@ -580,8 +584,10 @@ sshpam_thread(void *ctxtp) +@@ -608,8 +612,10 @@ sshpam_thread(void *ctxtp) pam_strerror(sshpam_handle, sshpam_err))) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); + fatal_fr(r, "buffer error"); /* XXX - can't do much about an error here */ - if (sshpam_err == PAM_ACCT_EXPIRED) - ssh_msg_send(ctxt->pam_csock, PAM_ACCT_EXPIRED, buffer); @@ -37,7 +37,7 @@ index b4100ea1c..a042c3c8e 100644 else if (sshpam_maxtries_reached) ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer); else -@@ -890,9 +896,11 @@ sshpam_query(void *ctx, char **name, char **info, +@@ -913,9 +919,11 @@ sshpam_query(void *ctx, char **name, char **info, free(msg); break; case PAM_ACCT_EXPIRED: diff --git a/0033-openssh-8.7p1-scp-kill-switch.patch b/0031-openssh-8.7p1-scp-kill-switch.patch similarity index 75% rename from 0033-openssh-8.7p1-scp-kill-switch.patch rename to 0031-openssh-8.7p1-scp-kill-switch.patch index 440eb3e..5c3594f 100644 --- a/0033-openssh-8.7p1-scp-kill-switch.patch +++ b/0031-openssh-8.7p1-scp-kill-switch.patch @@ -1,7 +1,7 @@ -From 687b69ae7e5a503afa0dd4341ff4fb954daf7ccd Mon Sep 17 00:00:00 2001 +From ca8b4de1019b859e2c68288a554d1905a6cf029f Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 33/53] openssh-8.7p1-scp-kill-switch +Subject: [PATCH 31/53] openssh-8.7p1-scp-kill-switch --- pathnames.h | 1 + @@ -10,11 +10,11 @@ Subject: [PATCH 33/53] openssh-8.7p1-scp-kill-switch 3 files changed, 16 insertions(+) diff --git a/pathnames.h b/pathnames.h -index 1158bec96..43f0c5708 100644 +index 0dcc49552..78bba2314 100644 --- a/pathnames.h +++ b/pathnames.h -@@ -42,6 +42,7 @@ - #define _PATH_HOST_XMSS_KEY_FILE SSHDIR "/ssh_host_xmss_key" +@@ -40,6 +40,7 @@ + #define _PATH_HOST_ED25519_KEY_FILE SSHDIR "/ssh_host_ed25519_key" #define _PATH_HOST_RSA_KEY_FILE SSHDIR "/ssh_host_rsa_key" #define _PATH_DH_MODULI SSHDIR "/moduli" +#define _PATH_SCP_KILL_SWITCH SSHDIR "/disable_scp" @@ -22,10 +22,10 @@ index 1158bec96..43f0c5708 100644 #ifndef _PATH_SSH_PROGRAM #define _PATH_SSH_PROGRAM "/usr/bin/ssh" diff --git a/scp.1 b/scp.1 -index aa2e2d8b5..373d72379 100644 +index 7bce0fe6f..2bb838c7d 100644 --- a/scp.1 +++ b/scp.1 -@@ -331,6 +331,13 @@ during download or upload. +@@ -334,6 +334,13 @@ during download or upload. By default a 32KB buffer is used. .El .El @@ -40,10 +40,10 @@ index aa2e2d8b5..373d72379 100644 .Ex -std scp .Sh SEE ALSO diff --git a/scp.c b/scp.c -index 7f9795a57..7ed1a54c9 100644 +index 621131ffc..3c213f83d 100644 --- a/scp.c +++ b/scp.c -@@ -649,6 +649,14 @@ main(int argc, char **argv) +@@ -633,6 +633,14 @@ main(int argc, char **argv) if (iamremote) mode = MODE_SCP; diff --git a/0034-openssh-8.7p1-recursive-scp.patch b/0032-openssh-8.7p1-recursive-scp.patch similarity index 86% rename from 0034-openssh-8.7p1-recursive-scp.patch rename to 0032-openssh-8.7p1-recursive-scp.patch index 4ca409a..adb5e3d 100644 --- a/0034-openssh-8.7p1-recursive-scp.patch +++ b/0032-openssh-8.7p1-recursive-scp.patch @@ -1,7 +1,7 @@ -From fa0cc1c401f634af14cd46eb376bd4a59e8f00f7 Mon Sep 17 00:00:00 2001 +From e6478b233cd2298c9e6e6128867421892ff8f0e4 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 34/53] openssh-8.7p1-recursive-scp +Subject: [PATCH 32/53] openssh-8.7p1-recursive-scp --- scp.c | 2 +- @@ -11,10 +11,10 @@ Subject: [PATCH 34/53] openssh-8.7p1-recursive-scp 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/scp.c b/scp.c -index 7ed1a54c9..0c87dd0e1 100644 +index 3c213f83d..78c79a755 100644 --- a/scp.c +++ b/scp.c -@@ -1388,7 +1388,7 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) +@@ -1378,7 +1378,7 @@ source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) if (src_is_dir && iamrecursive) { if (sftp_upload_dir(conn, src, abs_dst, pflag, @@ -24,10 +24,10 @@ index 7ed1a54c9..0c87dd0e1 100644 errs = 1; } diff --git a/sftp-client.c b/sftp-client.c -index 9f8ab4afa..873dec04f 100644 +index 840170ab6..9bf9cc047 100644 --- a/sftp-client.c +++ b/sftp-client.c -@@ -1003,7 +1003,7 @@ sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, +@@ -1001,7 +1001,7 @@ sftp_fsetstat(struct sftp_conn *conn, const u_char *handle, u_int handle_len, /* Implements both the realpath and expand-path operations */ static char * @@ -36,7 +36,7 @@ index 9f8ab4afa..873dec04f 100644 { struct sshbuf *msg; u_int expected_id, count, id; -@@ -1049,11 +1049,43 @@ sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) +@@ -1047,11 +1047,43 @@ sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) if ((r = sshbuf_get_u32(msg, &status)) != 0 || (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); @@ -85,7 +85,7 @@ index 9f8ab4afa..873dec04f 100644 } else if (type != SSH2_FXP_NAME) fatal("Expected SSH2_FXP_NAME(%u) packet, got %u", SSH2_FXP_NAME, type); -@@ -1078,9 +1110,9 @@ sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) +@@ -1076,9 +1108,9 @@ sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand) } char * @@ -97,7 +97,7 @@ index 9f8ab4afa..873dec04f 100644 } int -@@ -1094,9 +1126,9 @@ sftp_expand_path(struct sftp_conn *conn, const char *path) +@@ -1092,9 +1124,9 @@ sftp_expand_path(struct sftp_conn *conn, const char *path) { if (!sftp_can_expand_path(conn)) { debug3_f("no server support, fallback to realpath"); @@ -109,7 +109,7 @@ index 9f8ab4afa..873dec04f 100644 } int -@@ -2016,7 +2048,7 @@ sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst, +@@ -2014,7 +2046,7 @@ sftp_download_dir(struct sftp_conn *conn, const char *src, const char *dst, char *src_canon; int ret; @@ -143,10 +143,10 @@ index 9f8ab4afa..873dec04f 100644 from_path); return -1; diff --git a/sftp-client.h b/sftp-client.h -index 74cdae7dc..00ed6630c 100644 +index 873ad3849..fe58651c1 100644 --- a/sftp-client.h +++ b/sftp-client.h -@@ -111,7 +111,7 @@ int sftp_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); +@@ -112,7 +112,7 @@ int sftp_fsetstat(struct sftp_conn *, const u_char *, u_int, Attrib *); int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a); /* Canonicalise 'path' - caller must free result */ @@ -155,7 +155,7 @@ index 74cdae7dc..00ed6630c 100644 /* Canonicalisation with tilde expansion (requires server extension) */ char *sftp_expand_path(struct sftp_conn *, const char *); -@@ -163,7 +163,7 @@ int sftp_upload(struct sftp_conn *, const char *, const char *, +@@ -164,7 +164,7 @@ int sftp_upload(struct sftp_conn *, const char *, const char *, * times if 'pflag' is set */ int sftp_upload_dir(struct sftp_conn *, const char *, const char *, @@ -165,10 +165,10 @@ index 74cdae7dc..00ed6630c 100644 /* * Download a 'from_path' from the 'from' connection and upload it to diff --git a/sftp.c b/sftp.c -index bdedd1416..322e6d1f4 100644 +index 3b505eea2..2a99698a8 100644 --- a/sftp.c +++ b/sftp.c -@@ -809,7 +809,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, +@@ -801,7 +801,7 @@ process_put(struct sftp_conn *conn, const char *src, const char *dst, (rflag || global_rflag)) { if (sftp_upload_dir(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, 1, resume, @@ -177,7 +177,7 @@ index bdedd1416..322e6d1f4 100644 err = -1; } else { if (sftp_upload(conn, g.gl_pathv[i], abs_dst, -@@ -1644,7 +1644,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, +@@ -1636,7 +1636,7 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd, if (path1 == NULL || *path1 == '\0') path1 = xstrdup(startdir); path1 = sftp_make_absolute(path1, *pwd); @@ -186,7 +186,7 @@ index bdedd1416..322e6d1f4 100644 err = 1; break; } -@@ -2249,7 +2249,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) +@@ -2241,7 +2241,7 @@ interactive_loop(struct sftp_conn *conn, char *file1, char *file2) } #endif /* USE_LIBEDIT */ diff --git a/0035-openssh-8.7p1-minrsabits.patch b/0033-openssh-8.7p1-minrsabits.patch similarity index 81% rename from 0035-openssh-8.7p1-minrsabits.patch rename to 0033-openssh-8.7p1-minrsabits.patch index 264be9e..fcd994b 100644 --- a/0035-openssh-8.7p1-minrsabits.patch +++ b/0033-openssh-8.7p1-minrsabits.patch @@ -1,7 +1,7 @@ -From abf2f2c00cb708920e87f1a4f63490f812d00cf9 Mon Sep 17 00:00:00 2001 +From 14f25e21b4e2c5e625f266fcc9af42c2f89845de Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 35/53] openssh-8.7p1-minrsabits +Subject: [PATCH 33/53] openssh-8.7p1-minrsabits --- readconf.c | 1 + @@ -9,10 +9,10 @@ Subject: [PATCH 35/53] openssh-8.7p1-minrsabits 2 files changed, 2 insertions(+) diff --git a/readconf.c b/readconf.c -index 6c04ed43c..f340bf501 100644 +index eab734aaf..3f67f4de4 100644 --- a/readconf.c +++ b/readconf.c -@@ -343,6 +343,7 @@ static struct { +@@ -337,6 +337,7 @@ static struct { { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, { "requiredrsasize", oRequiredRSASize }, @@ -21,10 +21,10 @@ index 6c04ed43c..f340bf501 100644 { "obscurekeystroketiming", oObscureKeystrokeTiming }, { "channeltimeout", oChannelTimeout }, diff --git a/servconf.c b/servconf.c -index 15c99b303..84891544b 100644 +index b63a7f0b0..ac84b74d9 100644 --- a/servconf.c +++ b/servconf.c -@@ -788,6 +788,7 @@ static struct { +@@ -778,6 +778,7 @@ static struct { { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL }, diff --git a/0036-openssh-8.7p1-ibmca.patch b/0034-openssh-8.7p1-ibmca.patch similarity index 85% rename from 0036-openssh-8.7p1-ibmca.patch rename to 0034-openssh-8.7p1-ibmca.patch index 42e1bdd..803c899 100644 --- a/0036-openssh-8.7p1-ibmca.patch +++ b/0034-openssh-8.7p1-ibmca.patch @@ -1,7 +1,7 @@ -From fd2a2cae9a672b8a255566a19e0be6c8d21f363b Mon Sep 17 00:00:00 2001 +From e2c0fb233119584b04d61d243cd58433072559c2 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 36/53] openssh-8.7p1-ibmca +Subject: [PATCH 34/53] openssh-8.7p1-ibmca --- openbsd-compat/bsd-closefrom.c | 2 +- diff --git a/0037-openssh-7.6p1-audit.patch b/0035-openssh-7.6p1-audit.patch similarity index 91% rename from 0037-openssh-7.6p1-audit.patch rename to 0035-openssh-7.6p1-audit.patch index 308a200..1635f9f 100644 --- a/0037-openssh-7.6p1-audit.patch +++ b/0035-openssh-7.6p1-audit.patch @@ -1,7 +1,7 @@ -From 0a1cf7de02296d921d1ef32b0b0af0534f3b4306 Mon Sep 17 00:00:00 2001 +From c64eb340d925f3f7e29bb1c45b7d7b537ffa6197 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 37/53] openssh-7.6p1-audit +Subject: [PATCH 35/53] openssh-7.6p1-audit --- Makefile.in | 2 +- @@ -21,34 +21,34 @@ Subject: [PATCH 37/53] openssh-7.6p1-audit kex.h | 2 + mac.c | 14 +++ mac.h | 1 + - monitor.c | 194 +++++++++++++++++++++++++++-- + monitor.c | 193 +++++++++++++++++++++++++++-- monitor.h | 8 +- monitor_wrap.c | 130 +++++++++++++++++++- monitor_wrap.h | 11 +- packet.c | 98 +++++++++++++-- packet.h | 1 + - session.c | 83 ++++++++++++- + session.c | 82 ++++++++++++- session.h | 10 +- - sshd-session.c | 104 ++++++++++++++-- + sshd-session.c | 98 +++++++++++++-- sshd.c | 10 ++ - 27 files changed, 1258 insertions(+), 104 deletions(-) + 27 files changed, 1251 insertions(+), 103 deletions(-) create mode 100644 auditstub.c diff --git a/Makefile.in b/Makefile.in -index 6c417ef7c..a2942392e 100644 +index a36eb82ed..20d134c02 100644 --- a/Makefile.in +++ b/Makefile.in -@@ -119,7 +119,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ +@@ -110,7 +110,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ kexsntrup761x25519.o kexmlkem768x25519.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 +- sshbuf-io.o misc-agent.o ++ sshbuf-io.o misc-agent.o auditstub.o - SKOBJS= ssh-sk-client.o + P11OBJS= ssh-pkcs11-client.o diff --git a/audit-bsm.c b/audit-bsm.c -index ccfcf6f7f..a49abb929 100644 +index 4bce22c37..a6292cb8f 100644 --- a/audit-bsm.c +++ b/audit-bsm.c @@ -373,12 +373,25 @@ audit_connection_from(const char *host, int port) @@ -92,7 +92,7 @@ index ccfcf6f7f..a49abb929 100644 audit_event(struct ssh *ssh, ssh_audit_event_t event) { @@ -452,4 +471,28 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) - debug("%s: unhandled event %d", __func__, event); + debug_f("unhandled event %d", event); } } + @@ -121,10 +121,10 @@ index ccfcf6f7f..a49abb929 100644 +} #endif /* BSM */ diff --git a/audit-linux.c b/audit-linux.c -index 3fcbe5c53..d484b82b4 100644 +index 954eabe27..4d3e9d41e 100644 --- a/audit-linux.c +++ b/audit-linux.c -@@ -33,27 +33,40 @@ +@@ -33,29 +33,42 @@ #include "log.h" #include "audit.h" @@ -164,6 +164,8 @@ index 3fcbe5c53..d484b82b4 100644 - return 0; /* Must prevent login */ + goto fatal_report; /* Must prevent login */ } + if (hostname != NULL && strcmp(hostname, "UNKNOWN") == 0) + hostname = NULL; - rc = audit_log_acct_message(audit_fd, AUDIT_USER_LOGIN, + rc = audit_log_acct_message(audit_fd, event, NULL, "login", username ? username : "(unknown)", @@ -172,7 +174,7 @@ index 3fcbe5c53..d484b82b4 100644 saved_errno = errno; close(audit_fd); -@@ -65,9 +78,96 @@ linux_audit_record_event(int uid, const char *username, const char *hostname, +@@ -67,9 +80,96 @@ linux_audit_record_event(int uid, const char *username, const char *hostname, rc = 0; errno = saved_errno; @@ -270,7 +272,7 @@ index 3fcbe5c53..d484b82b4 100644 /* Below is the sshd audit API code */ void -@@ -76,49 +176,211 @@ audit_connection_from(const char *host, int port) +@@ -78,49 +178,211 @@ audit_connection_from(const char *host, int port) /* not implemented */ } @@ -379,7 +381,7 @@ index 3fcbe5c53..d484b82b4 100644 + ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); break; default: - debug("%s: unhandled event %d", __func__, event); + debug_f("unhandled event %d", event); break; } } @@ -780,10 +782,10 @@ index 000000000..639a798df +{ +} diff --git a/auth.c b/auth.c -index e4578169b..e10e804f3 100644 +index d25653ee4..38c34298e 100644 --- a/auth.c +++ b/auth.c -@@ -501,9 +501,6 @@ getpwnamallow(struct ssh *ssh, const char *user) +@@ -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 @@ -816,7 +818,7 @@ index 391630350..6be52d70b 100644 FILE *auth_openprincipals(const char *, struct passwd *, int); diff --git a/auth2-hostbased.c b/auth2-hostbased.c -index a3be6e497..8cebaffd9 100644 +index 976484fc5..e9421a868 100644 --- a/auth2-hostbased.c +++ b/auth2-hostbased.c @@ -157,7 +157,7 @@ userauth_hostbased(struct ssh *ssh, const char *method) @@ -850,10 +852,10 @@ index a3be6e497..8cebaffd9 100644 int hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index 0d5ae0df7..99cb810f4 100644 +index b7300ca9e..9f3371c07 100644 --- a/auth2-pubkey.c +++ b/auth2-pubkey.c -@@ -235,7 +235,7 @@ userauth_pubkey(struct ssh *ssh, const char *method) +@@ -233,7 +233,7 @@ userauth_pubkey(struct ssh *ssh, const char *method) /* test for correct signature */ authenticated = 0; if (mm_user_key_allowed(ssh, pw, key, 1, &authopts) && @@ -862,7 +864,7 @@ index 0d5ae0df7..99cb810f4 100644 sshbuf_ptr(b), sshbuf_len(b), (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, ssh->compat, &sig_details) == 0) { -@@ -328,6 +328,20 @@ done: +@@ -326,6 +326,20 @@ done: return authenticated; } @@ -884,7 +886,7 @@ index 0d5ae0df7..99cb810f4 100644 match_principals_file(struct passwd *pw, char *file, struct sshkey_cert *cert, struct sshauthopt **authoptsp) diff --git a/auth2.c b/auth2.c -index 8ec41de23..4a8515eaf 100644 +index 5a4b932a9..da24f7bcb 100644 --- a/auth2.c +++ b/auth2.c @@ -310,9 +310,6 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) @@ -898,7 +900,7 @@ index 8ec41de23..4a8515eaf 100644 #ifdef USE_PAM if (options.use_pam) diff --git a/cipher.c b/cipher.c -index 8a18da2df..57d553255 100644 +index 5e096cebf..9b42ffb9a 100644 --- a/cipher.c +++ b/cipher.c @@ -64,25 +64,6 @@ struct sshcipher_ctx { @@ -927,7 +929,7 @@ index 8a18da2df..57d553255 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, +@@ -411,7 +392,7 @@ cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr, void cipher_free(struct sshcipher_ctx *cc) { @@ -968,10 +970,10 @@ index 6533ff2bb..2e05a0210 100644 const struct sshcipher *cipher_by_name(const char *); diff --git a/kex.c b/kex.c -index 8b200ff4a..62f607d6f 100644 +index 5f9530908..44f350ce8 100644 --- a/kex.c +++ b/kex.c -@@ -68,6 +68,7 @@ +@@ -66,6 +66,7 @@ #include "sshbuf.h" #include "digest.h" #include "xmalloc.h" @@ -979,7 +981,7 @@ index 8b200ff4a..62f607d6f 100644 /* prototype */ static int kex_choose_conf(struct ssh *, uint32_t seq); -@@ -821,12 +822,16 @@ kex_start_rekex(struct ssh *ssh) +@@ -820,12 +821,16 @@ kex_start_rekex(struct ssh *ssh) } static int @@ -998,7 +1000,7 @@ index 8b200ff4a..62f607d6f 100644 if ((enc->cipher = cipher_by_name(name)) == NULL) { error_f("unsupported cipher %s", name); free(name); -@@ -847,8 +852,12 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) +@@ -846,8 +851,12 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) { char *name = match_list(client, server, NULL); @@ -1012,7 +1014,7 @@ index 8b200ff4a..62f607d6f 100644 if (mac_setup(mac, name) < 0) { error_f("unsupported MAC %s", name); free(name); -@@ -861,12 +870,16 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) +@@ -860,12 +869,16 @@ choose_mac(struct ssh *ssh, struct sshmac *mac, char *client, char *server) } static int @@ -1031,7 +1033,7 @@ index 8b200ff4a..62f607d6f 100644 #ifdef WITH_ZLIB if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; -@@ -1030,7 +1043,7 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) +@@ -1029,7 +1042,7 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) 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; @@ -1040,7 +1042,7 @@ index 8b200ff4a..62f607d6f 100644 sprop[nenc])) != 0) { kex->failed_choice = peer[nenc]; peer[nenc] = NULL; -@@ -1045,7 +1058,7 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) +@@ -1044,7 +1057,7 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) peer[nmac] = NULL; goto out; } @@ -1049,7 +1051,7 @@ index 8b200ff4a..62f607d6f 100644 sprop[ncomp])) != 0) { kex->failed_choice = peer[ncomp]; peer[ncomp] = NULL; -@@ -1068,6 +1081,10 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) +@@ -1067,6 +1080,10 @@ kex_choose_conf(struct ssh *ssh, uint32_t seq) 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); @@ -1060,7 +1062,7 @@ index 8b200ff4a..62f607d6f 100644 } /* XXX need runden? */ kex->we_need = need; -@@ -1337,6 +1354,36 @@ dump_digest(const char *msg, const u_char *digest, int len) +@@ -1336,6 +1353,36 @@ dump_digest(const char *msg, const u_char *digest, int len) } #endif @@ -1098,10 +1100,10 @@ index 8b200ff4a..62f607d6f 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 0e080ea38..6a55aadf4 100644 +index 206ce60ed..cb06e85a3 100644 --- a/kex.h +++ b/kex.h -@@ -255,6 +255,8 @@ int kexgss_client(struct ssh *); +@@ -260,6 +260,8 @@ int kexgss_client(struct ssh *); int kexgss_server(struct ssh *); #endif @@ -1111,10 +1113,10 @@ index 0e080ea38..6a55aadf4 100644 int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, struct sshbuf **); diff --git a/mac.c b/mac.c -index f3dda6692..bf051baa1 100644 +index c95f5ea06..354cfb408 100644 --- a/mac.c +++ b/mac.c -@@ -239,6 +239,20 @@ mac_clear(struct sshmac *mac) +@@ -230,6 +230,20 @@ mac_clear(struct sshmac *mac) mac->umac_ctx = NULL; } @@ -1147,10 +1149,10 @@ index 0b119d7a1..5fb593b9e 100644 #endif /* SSHMAC_H */ diff --git a/monitor.c b/monitor.c -index 43c10a4ec..fbc357825 100644 +index 453469665..b2f501790 100644 --- a/monitor.c +++ b/monitor.c -@@ -93,6 +93,7 @@ +@@ -83,6 +83,7 @@ #include "compat.h" #include "ssh2.h" #include "authfd.h" @@ -1158,7 +1160,7 @@ index 43c10a4ec..fbc357825 100644 #include "match.h" #include "ssherr.h" #include "sk-api.h" -@@ -110,6 +111,8 @@ extern struct sshbuf *loginmsg; +@@ -100,6 +101,8 @@ extern struct sshbuf *loginmsg; extern struct include_list includes; extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ @@ -1167,7 +1169,7 @@ index 43c10a4ec..fbc357825 100644 /* State exported from the child */ static struct sshbuf *child_state; -@@ -154,6 +157,11 @@ int mm_answer_gss_updatecreds(struct ssh *, int, struct sshbuf *); +@@ -144,6 +147,11 @@ int mm_answer_gss_updatecreds(struct ssh *, int, struct sshbuf *); #ifdef SSH_AUDIT_EVENTS int mm_answer_audit_event(struct ssh *, int, struct sshbuf *); int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); @@ -1179,7 +1181,7 @@ index 43c10a4ec..fbc357825 100644 #endif static Authctxt *authctxt; -@@ -214,6 +222,10 @@ struct mon_table mon_dispatch_proto20[] = { +@@ -204,6 +212,10 @@ struct mon_table mon_dispatch_proto20[] = { #endif #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, @@ -1190,7 +1192,7 @@ index 43c10a4ec..fbc357825 100644 #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, -@@ -249,6 +261,11 @@ struct mon_table mon_dispatch_postauth20[] = { +@@ -239,6 +251,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}, @@ -1202,7 +1204,7 @@ index 43c10a4ec..fbc357825 100644 #endif {0, 0, NULL} }; -@@ -1569,8 +1586,10 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1575,8 +1592,10 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) int r, ret, req_presence = 0, req_verify = 0, valid_data = 0; int encoded_ret; struct sshkey_sig_details *sig_details = NULL; @@ -1214,7 +1216,7 @@ index 43c10a4ec..fbc357825 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) -@@ -1579,6 +1598,8 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1585,6 +1604,8 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal_f("bad key, not previously allowed"); @@ -1223,7 +1225,7 @@ index 43c10a4ec..fbc357825 100644 /* Empty signature algorithm means NULL. */ if (*sigalg == '\0') { -@@ -1594,14 +1615,19 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1600,14 +1621,19 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) case MM_USERKEY: valid_data = monitor_valid_userblob(ssh, data, datalen); auth_method = "publickey"; @@ -1243,7 +1245,7 @@ index 43c10a4ec..fbc357825 100644 break; } if (!valid_data) -@@ -1613,8 +1639,6 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1619,8 +1645,6 @@ mm_answer_keyverify(struct ssh *ssh, int sock, struct sshbuf *m) SSH_FP_DEFAULT)) == NULL) fatal_f("sshkey_fingerprint failed"); @@ -1252,7 +1254,7 @@ index 43c10a4ec..fbc357825 100644 debug3_f("%s %s signature using %s %s%s%s", auth_method, sshkey_type(key), sigalg == NULL ? "default" : sigalg, (ret == 0) ? "verified" : "unverified", -@@ -1702,13 +1726,19 @@ mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw) +@@ -1708,13 +1732,19 @@ mm_record_login(struct ssh *ssh, Session *s, struct passwd *pw) } static void @@ -1273,7 +1275,7 @@ index 43c10a4ec..fbc357825 100644 session_unused(s->self); } -@@ -1775,7 +1805,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1781,7 +1811,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) error: if (s != NULL) @@ -1282,7 +1284,7 @@ index 43c10a4ec..fbc357825 100644 if ((r = sshbuf_put_u32(m, 0)) != 0) fatal_fr(r, "assemble 0"); mm_request_send(sock, MONITOR_ANS_PTY, m); -@@ -1794,7 +1824,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -1800,7 +1830,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, int sock, struct sshbuf *m) if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) fatal_fr(r, "parse tty"); if ((s = session_by_tty(tty)) != NULL) @@ -1291,7 +1293,7 @@ index 43c10a4ec..fbc357825 100644 sshbuf_reset(m); free(tty); return (0); -@@ -1816,6 +1846,8 @@ mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req) +@@ -1822,6 +1852,8 @@ mm_answer_term(struct ssh *ssh, int sock, struct sshbuf *req) sshpam_cleanup(); #endif @@ -1300,16 +1302,15 @@ index 43c10a4ec..fbc357825 100644 while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); -@@ -1862,12 +1894,47 @@ mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m) +@@ -1868,12 +1900,46 @@ mm_answer_audit_command(struct ssh *ssh, int socket, struct sshbuf *m) { char *cmd; int r; + Session *s; - debug3("%s entering", __func__); + debug3_f("entering"); if ((r = sshbuf_get_cstring(m, &cmd, NULL)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ + fatal_fr(r, "buffer error"); /* sanity check command, if so how? */ - audit_run_command(cmd); + s = session_new(); @@ -1349,7 +1350,7 @@ index 43c10a4ec..fbc357825 100644 free(cmd); return (0); } -@@ -1940,6 +2007,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1946,6 +2012,7 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) void mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { @@ -1357,7 +1358,7 @@ index 43c10a4ec..fbc357825 100644 debug3_f("Waiting for new keys"); if ((child_state = sshbuf_new()) == NULL) -@@ -1947,6 +2015,19 @@ mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -1953,6 +2020,19 @@ mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, child_state); debug3_f("GOT new keys"); @@ -1377,7 +1378,7 @@ index 43c10a4ec..fbc357825 100644 } -@@ -2234,3 +2315,102 @@ mm_answer_gss_updatecreds(struct ssh *ssh, int socket, struct sshbuf *m) { +@@ -2240,3 +2320,102 @@ mm_answer_gss_updatecreds(struct ssh *ssh, int socket, struct sshbuf *m) { #endif /* GSSAPI */ @@ -1500,10 +1501,10 @@ index d4d631ddc..2c64f07dc 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 b6e3b3f39..1a079c15d 100644 +index 08dc29e12..fb44ae733 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c -@@ -567,7 +567,7 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, +@@ -578,7 +578,7 @@ mm_key_allowed(enum mm_keytype type, const char *user, const char *host, */ int @@ -1512,7 +1513,7 @@ index b6e3b3f39..1a079c15d 100644 const u_char *data, size_t datalen, const char *sigalg, u_int compat, struct sshkey_sig_details **sig_detailsp) { -@@ -583,7 +583,8 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, +@@ -594,7 +594,8 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, *sig_detailsp = NULL; if ((m = sshbuf_new()) == NULL) fatal_f("sshbuf_new failed"); @@ -1522,7 +1523,7 @@ index b6e3b3f39..1a079c15d 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) -@@ -616,6 +617,22 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, +@@ -627,6 +628,22 @@ mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, return 0; } @@ -1545,7 +1546,7 @@ index b6e3b3f39..1a079c15d 100644 void mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { -@@ -1032,11 +1049,12 @@ mm_audit_event(struct ssh *ssh, ssh_audit_event_t event) +@@ -1043,11 +1060,12 @@ mm_audit_event(struct ssh *ssh, ssh_audit_event_t event) sshbuf_free(m); } @@ -1558,10 +1559,10 @@ index b6e3b3f39..1a079c15d 100644 int r; + int handle; - debug3("%s entering command %s", __func__, command); + debug3_f("entering command %s", command); -@@ -1046,6 +1064,30 @@ mm_audit_run_command(const char *command) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); +@@ -1057,6 +1075,30 @@ mm_audit_run_command(const char *command) + fatal_fr(r, "buffer error"); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUDIT_COMMAND, m); @@ -1591,7 +1592,7 @@ index b6e3b3f39..1a079c15d 100644 sshbuf_free(m); } #endif /* SSH_AUDIT_EVENTS */ -@@ -1294,3 +1336,83 @@ server_get_connection_info(struct ssh *ssh, int populate, int use_dns) +@@ -1305,3 +1347,83 @@ server_get_connection_info(struct ssh *ssh, int populate, int use_dns) return &ci; } @@ -1676,10 +1677,10 @@ index b6e3b3f39..1a079c15d 100644 +} +#endif /* SSH_AUDIT_EVENTS */ diff --git a/monitor_wrap.h b/monitor_wrap.h -index 672dce525..661ed63be 100644 +index 12c489c33..1bcbfd305 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h -@@ -58,7 +58,9 @@ int mm_user_key_allowed(struct ssh *ssh, struct passwd *, struct sshkey *, int, +@@ -62,7 +62,9 @@ int mm_user_key_allowed(struct ssh *ssh, struct passwd *, struct sshkey *, int, struct sshauthopt **); int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, const char *, struct sshkey *); @@ -1690,7 +1691,7 @@ index 672dce525..661ed63be 100644 const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m); -@@ -85,7 +87,12 @@ void mm_sshpam_free_ctx(void *); +@@ -89,7 +91,12 @@ void mm_sshpam_free_ctx(void *); #ifdef SSH_AUDIT_EVENTS #include "audit.h" void mm_audit_event(struct ssh *, ssh_audit_event_t); @@ -1705,10 +1706,10 @@ index 672dce525..661ed63be 100644 struct Session; diff --git a/packet.c b/packet.c -index 9dea2cfc5..344b5f54e 100644 +index 5dd8269c2..bc22b8625 100644 --- a/packet.c +++ b/packet.c -@@ -81,6 +81,7 @@ +@@ -77,6 +77,7 @@ #endif #include "xmalloc.h" @@ -1716,7 +1717,7 @@ index 9dea2cfc5..344b5f54e 100644 #include "compat.h" #include "ssh2.h" #include "cipher.h" -@@ -506,6 +507,13 @@ ssh_packet_get_connection_out(struct ssh *ssh) +@@ -513,6 +514,13 @@ ssh_packet_get_connection_out(struct ssh *ssh) return ssh->state->connection_out; } @@ -1730,10 +1731,10 @@ index 9dea2cfc5..344b5f54e 100644 /* * Returns the IP-address of the remote host as a string. The returned * string must not be freed. -@@ -675,22 +683,19 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) - { +@@ -683,22 +691,19 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) struct session_state *state = ssh->state; u_int mode; + struct packet *p; + u_int had_keys = packet_state_has_keys(state); if (!state->initialized) @@ -1755,10 +1756,10 @@ index 9dea2cfc5..344b5f54e 100644 + state->outgoing_packet = NULL; sshbuf_free(state->incoming_packet); + state->incoming_packet = NULL; - for (mode = 0; mode < MODE_MAX; mode++) { - kex_free_newkeys(state->newkeys[mode]); /* current keys */ - state->newkeys[mode] = NULL; -@@ -726,8 +731,18 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) + while ((p = TAILQ_FIRST(&state->outgoing))) { + sshbuf_free(p->payload); + TAILQ_REMOVE(&state->outgoing, p, next); +@@ -739,8 +744,18 @@ ssh_packet_close_internal(struct ssh *ssh, int do_close) #endif /* WITH_ZLIB */ cipher_free(state->send_context); cipher_free(state->receive_context); @@ -1777,7 +1778,7 @@ index 9dea2cfc5..344b5f54e 100644 free(ssh->local_ipaddr); ssh->local_ipaddr = NULL; free(ssh->remote_ipaddr); -@@ -984,6 +999,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode) +@@ -1004,6 +1019,7 @@ ssh_set_newkeys(struct ssh *ssh, int mode) (unsigned long long)state->p_send.bytes, (unsigned long long)state->p_send.blocks); kex_free_newkeys(state->newkeys[mode]); @@ -1785,7 +1786,7 @@ index 9dea2cfc5..344b5f54e 100644 state->newkeys[mode] = NULL; } /* note that both bytes and the seqnr are not reset */ -@@ -2325,6 +2341,72 @@ ssh_packet_get_output(struct ssh *ssh) +@@ -2345,6 +2361,72 @@ ssh_packet_get_output(struct ssh *ssh) return (void *)ssh->state->output; } @@ -1859,7 +1860,7 @@ index 9dea2cfc5..344b5f54e 100644 static int ssh_packet_set_postauth(struct ssh *ssh) diff --git a/packet.h b/packet.h -index 49bb87f07..44a39a9e9 100644 +index 072f27425..e087d4c8a 100644 --- a/packet.h +++ b/packet.h @@ -223,4 +223,5 @@ const u_char *sshpkt_ptr(struct ssh *, size_t *lenp); @@ -1869,19 +1870,18 @@ index 49bb87f07..44a39a9e9 100644 +void packet_destroy_all(struct ssh *, int, int); #endif /* PACKET_H */ diff --git a/session.c b/session.c -index d7f05848e..e204a06dd 100644 +index d034f5c65..107edcf91 100644 --- a/session.c +++ b/session.c -@@ -145,7 +145,7 @@ extern char *__progname; +@@ -139,6 +139,7 @@ static int session_pty_req(struct ssh *, Session *); + extern ServerOptions options; + extern char *__progname; extern int debug_flag; - extern u_int utmp_len; - extern int startup_pipe; --extern void destroy_sensitive_data(void); +extern void destroy_sensitive_data(struct ssh *); extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; extern char *tun_fwd_ifnames; /* serverloop.c */ -@@ -653,6 +653,14 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) +@@ -617,6 +618,14 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) /* Parent. Close the slave side of the pseudo tty. */ close(ttyfd); @@ -1895,8 +1895,8 @@ index d7f05848e..e204a06dd 100644 + /* Enter interactive session. */ s->ptymaster = ptymaster; - ssh_packet_set_interactive(ssh, 1, -@@ -745,15 +753,19 @@ do_exec(struct ssh *ssh, Session *s, const char *command) + session_set_fds(ssh, s, ptyfd, fdout, -1, 1, 1); +@@ -707,15 +716,19 @@ do_exec(struct ssh *ssh, Session *s, const char *command) s->self); #ifdef SSH_AUDIT_EVENTS @@ -1918,7 +1918,7 @@ index d7f05848e..e204a06dd 100644 #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); -@@ -1533,7 +1545,11 @@ do_child(struct ssh *ssh, Session *s, const char *command) +@@ -1495,7 +1508,11 @@ do_child(struct ssh *ssh, Session *s, const char *command) sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); /* remove keys from memory */ @@ -1930,7 +1930,7 @@ index d7f05848e..e204a06dd 100644 /* Force a password change */ if (s->authctxt->force_pwchange) { -@@ -1748,6 +1764,9 @@ session_unused(int id) +@@ -1710,6 +1727,9 @@ session_unused(int id) sessions[id].ttyfd = -1; sessions[id].ptymaster = -1; sessions[id].x11_chanids = NULL; @@ -1940,7 +1940,7 @@ index d7f05848e..e204a06dd 100644 sessions[id].next_unused = sessions_first_unused; sessions_first_unused = id; } -@@ -1826,6 +1845,19 @@ session_open(Authctxt *authctxt, int chanid) +@@ -1788,6 +1808,19 @@ session_open(Authctxt *authctxt, int chanid) return 1; } @@ -1960,7 +1960,7 @@ index d7f05848e..e204a06dd 100644 Session * session_by_tty(char *tty) { -@@ -2443,6 +2475,32 @@ session_exit_message(struct ssh *ssh, Session *s, int status) +@@ -2405,6 +2438,32 @@ session_exit_message(struct ssh *ssh, Session *s, int status) chan_write_failed(ssh, c); } @@ -1993,7 +1993,7 @@ index d7f05848e..e204a06dd 100644 void session_close(struct ssh *ssh, Session *s) { -@@ -2456,6 +2514,10 @@ session_close(struct ssh *ssh, Session *s) +@@ -2418,6 +2477,10 @@ session_close(struct ssh *ssh, Session *s) if (s->ttyfd != -1) session_pty_cleanup(s); @@ -2004,7 +2004,7 @@ index d7f05848e..e204a06dd 100644 free(s->term); free(s->display); free(s->x11_chanids); -@@ -2532,14 +2594,14 @@ session_close_by_channel(struct ssh *ssh, int id, int force, void *arg) +@@ -2494,14 +2557,14 @@ session_close_by_channel(struct ssh *ssh, int id, int force, void *arg) } void @@ -2021,7 +2021,7 @@ index d7f05848e..e204a06dd 100644 else session_close(ssh, s); } -@@ -2666,6 +2728,15 @@ do_authenticated2(struct ssh *ssh, Authctxt *authctxt) +@@ -2627,6 +2690,15 @@ do_authenticated2(struct ssh *ssh, Authctxt *authctxt) server_loop2(ssh, authctxt); } @@ -2037,7 +2037,7 @@ index d7f05848e..e204a06dd 100644 void do_cleanup(struct ssh *ssh, Authctxt *authctxt) { -@@ -2729,7 +2800,7 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) +@@ -2690,7 +2762,7 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) * or if running in monitor. */ if (mm_is_monitor()) @@ -2078,10 +2078,10 @@ index 344a1ddf9..a41c6efcd 100644 void session_close(struct ssh *, Session *); void do_setusercontext(struct passwd *); diff --git a/sshd-session.c b/sshd-session.c -index e86acf704..5eae9aed7 100644 +index d6bece941..e49e4fb51 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -194,8 +194,8 @@ struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); +@@ -188,8 +188,8 @@ struct include_list includes = TAILQ_HEAD_INITIALIZER(includes); struct sshbuf *loginmsg; /* Prototypes for various functions defined later in this file. */ @@ -2092,7 +2092,7 @@ index e86acf704..5eae9aed7 100644 /* XXX reduce to stub once postauth split */ int -@@ -208,6 +208,41 @@ mm_is_monitor(void) +@@ -202,6 +202,35 @@ mm_is_monitor(void) return (pmonitor && pmonitor->m_pid > 0); } @@ -2108,12 +2108,6 @@ index e86acf704..5eae9aed7 100644 + RSA_get0_key(rsa, NULL, NULL, &d); + return d != NULL; + } -+ case KEY_DSA_CERT: -+ case KEY_DSA: { -+ const BIGNUM *priv_key; -+ DSA_get0_key(k->dsa, NULL, &priv_key); -+ return priv_key != NULL; -+ } +#ifdef OPENSSL_HAS_ECC + case KEY_ECDSA_CERT: + case KEY_ECDSA: { @@ -2134,7 +2128,7 @@ index e86acf704..5eae9aed7 100644 /* * Signal handler for the alarm after the login grace period has expired. * As usual, this may only take signal-safe actions, even though it is -@@ -236,18 +271,40 @@ grace_alarm_handler(int sig) +@@ -230,18 +259,40 @@ grace_alarm_handler(int sig) _exit(EXIT_LOGIN_GRACE); } @@ -2178,7 +2172,7 @@ index e86acf704..5eae9aed7 100644 sshkey_free(sensitive_data.host_certificates[i]); sensitive_data.host_certificates[i] = NULL; } -@@ -256,20 +313,38 @@ destroy_sensitive_data(void) +@@ -250,20 +301,38 @@ destroy_sensitive_data(void) /* Demote private to public keys for network child */ void @@ -2218,7 +2212,7 @@ index e86acf704..5eae9aed7 100644 } /* Certs do not need demotion */ } -@@ -463,7 +538,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) +@@ -441,7 +510,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt) set_log_handler(mm_log_handler, pmonitor); /* Demote the private keys to public keys. */ @@ -2227,7 +2221,7 @@ index e86acf704..5eae9aed7 100644 reseed_prngs(); -@@ -1387,6 +1462,9 @@ main(int ac, char **av) +@@ -1365,6 +1434,9 @@ main(int ac, char **av) do_authenticated(ssh, authctxt); /* The connection has been terminated. */ @@ -2237,7 +2231,7 @@ index e86acf704..5eae9aed7 100644 ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); -@@ -1432,6 +1510,14 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, +@@ -1410,6 +1482,14 @@ sshd_hostkey_sign(struct ssh *ssh, struct sshkey *privkey, void cleanup_exit(int i) { @@ -2252,7 +2246,7 @@ index e86acf704..5eae9aed7 100644 extern int auth_attempted; /* monitor.c */ if (the_active_state != NULL && the_authctxt != NULL) { -@@ -1448,7 +1534,9 @@ cleanup_exit(int i) +@@ -1426,7 +1506,9 @@ cleanup_exit(int i) } #ifdef SSH_AUDIT_EVENTS /* done after do_cleanup so it can cancel the PAM auth 'thread' */ @@ -2264,10 +2258,10 @@ index e86acf704..5eae9aed7 100644 #endif /* Override default fatal exit value when auth was attempted */ diff --git a/sshd.c b/sshd.c -index c9ea8e385..8a99f0b29 100644 +index 3ab81e268..ed7faf96d 100644 --- a/sshd.c +++ b/sshd.c -@@ -217,6 +217,15 @@ close_listen_socks(void) +@@ -213,6 +213,15 @@ close_listen_socks(void) num_listen_socks = 0; } @@ -2283,7 +2277,7 @@ index c9ea8e385..8a99f0b29 100644 /* Allocate and initialise the children array */ static void child_alloc(void) -@@ -959,6 +968,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, +@@ -958,6 +967,7 @@ server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s, if (received_sigterm) { logit("Received signal %d; terminating.", (int) received_sigterm); diff --git a/0038-openssh-7.1p2-audit-race-condition.patch b/0036-openssh-7.1p2-audit-race-condition.patch similarity index 86% rename from 0038-openssh-7.1p2-audit-race-condition.patch rename to 0036-openssh-7.1p2-audit-race-condition.patch index f7d64ba..863f700 100644 --- a/0038-openssh-7.1p2-audit-race-condition.patch +++ b/0036-openssh-7.1p2-audit-race-condition.patch @@ -1,7 +1,7 @@ -From 4c8dfc9481ad2ed6dced8fd91b939de64e0b539b Mon Sep 17 00:00:00 2001 +From ffa3fdb2ad2c7afc91993d9301e35d2e9a83ea47 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 38/53] openssh-7.1p2-audit-race-condition +Subject: [PATCH 36/53] openssh-7.1p2-audit-race-condition --- monitor_wrap.c | 46 +++++++++++++++++++++++++++++++++++++ @@ -10,10 +10,10 @@ Subject: [PATCH 38/53] openssh-7.1p2-audit-race-condition 3 files changed, 102 insertions(+), 7 deletions(-) diff --git a/monitor_wrap.c b/monitor_wrap.c -index 1a079c15d..768a59f95 100644 +index fb44ae733..17a6c9786 100644 --- a/monitor_wrap.c +++ b/monitor_wrap.c -@@ -1415,4 +1415,50 @@ mm_audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_ +@@ -1426,4 +1426,50 @@ mm_audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_ mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_SERVER_KEY_FREE, m); sshbuf_free(m); } @@ -65,10 +65,10 @@ index 1a079c15d..768a59f95 100644 +} #endif /* SSH_AUDIT_EVENTS */ diff --git a/monitor_wrap.h b/monitor_wrap.h -index 661ed63be..e957ba6ea 100644 +index 1bcbfd305..2b814dbd1 100644 --- a/monitor_wrap.h +++ b/monitor_wrap.h -@@ -93,6 +93,8 @@ void mm_audit_unsupported_body(struct ssh *, int); +@@ -97,6 +97,8 @@ void mm_audit_unsupported_body(struct ssh *, int); void mm_audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t); void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t); void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); @@ -78,10 +78,10 @@ index 661ed63be..e957ba6ea 100644 struct Session; diff --git a/session.c b/session.c -index e204a06dd..ef7f43899 100644 +index 107edcf91..80282dfd8 100644 --- a/session.c +++ b/session.c -@@ -167,6 +167,10 @@ static Session *sessions = NULL; +@@ -161,6 +161,10 @@ static Session *sessions = NULL; login_cap_t *lc; #endif @@ -92,7 +92,7 @@ index e204a06dd..ef7f43899 100644 static int is_child = 0; static int in_chroot = 0; static int have_dev_log = 1; -@@ -390,6 +394,8 @@ xauth_valid_string(const char *s) +@@ -358,6 +362,8 @@ xauth_valid_string(const char *s) return 1; } @@ -101,7 +101,7 @@ index e204a06dd..ef7f43899 100644 #define USE_PIPES 1 /* * This is called to fork and execute a command when we have no tty. This -@@ -513,6 +519,8 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) +@@ -481,6 +487,8 @@ do_exec_no_pty(struct ssh *ssh, Session *s, const char *command) close(err[0]); #endif @@ -110,7 +110,7 @@ index e204a06dd..ef7f43899 100644 /* Do processing for the child (exec command etc). */ do_child(ssh, s, command); /* NOTREACHED */ -@@ -630,6 +638,9 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) +@@ -595,6 +603,9 @@ do_exec_pty(struct ssh *ssh, Session *s, const char *command) /* Close the extra descriptor for the pseudo tty. */ close(ttyfd); @@ -120,7 +120,7 @@ index e204a06dd..ef7f43899 100644 /* record login, etc. similar to login(1) */ #ifndef HAVE_OSF_SIA do_login(ssh, s, command); -@@ -766,6 +777,8 @@ do_exec(struct ssh *ssh, Session *s, const char *command) +@@ -729,6 +740,8 @@ do_exec(struct ssh *ssh, Session *s, const char *command) } if (s->command != NULL && s->ptyfd == -1) s->command_handle = mm_audit_run_command(ssh, s->command); @@ -129,7 +129,7 @@ index e204a06dd..ef7f43899 100644 #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); -@@ -781,6 +794,20 @@ do_exec(struct ssh *ssh, Session *s, const char *command) +@@ -744,6 +757,20 @@ do_exec(struct ssh *ssh, Session *s, const char *command) */ sshbuf_reset(loginmsg); @@ -150,7 +150,7 @@ index e204a06dd..ef7f43899 100644 return ret; } -@@ -1527,6 +1554,33 @@ child_close_fds(struct ssh *ssh) +@@ -1490,6 +1517,33 @@ child_close_fds(struct ssh *ssh) log_redirect_stderr_to(NULL); } @@ -184,7 +184,7 @@ index e204a06dd..ef7f43899 100644 /* * Performs common processing for the child, such as setting up the * environment, closing extra file descriptors, setting the user and group -@@ -1544,13 +1598,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) +@@ -1507,13 +1561,6 @@ do_child(struct ssh *ssh, Session *s, const char *command) sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); diff --git a/0039-openssh-9.0p1-audit-log.patch b/0037-openssh-9.0p1-audit-log.patch similarity index 92% rename from 0039-openssh-9.0p1-audit-log.patch rename to 0037-openssh-9.0p1-audit-log.patch index b72fbea..c58a5fe 100644 --- a/0039-openssh-9.0p1-audit-log.patch +++ b/0037-openssh-9.0p1-audit-log.patch @@ -1,7 +1,7 @@ -From fef6d48d6886001d384cef33e5ae6e5c278a7127 Mon Sep 17 00:00:00 2001 +From ef05b1fceddc64cfc7eb40daac60a137634d0a9f Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 39/53] openssh-9.0p1-audit-log +Subject: [PATCH 37/53] openssh-9.0p1-audit-log --- audit-bsm.c | 2 +- @@ -11,7 +11,7 @@ Subject: [PATCH 39/53] openssh-9.0p1-audit-log 4 files changed, 81 insertions(+), 17 deletions(-) diff --git a/audit-bsm.c b/audit-bsm.c -index a49abb929..c6f565532 100644 +index a6292cb8f..0f2ef8235 100644 --- a/audit-bsm.c +++ b/audit-bsm.c @@ -405,7 +405,7 @@ audit_session_close(struct logininfo *li) @@ -24,7 +24,7 @@ index a49abb929..c6f565532 100644 /* not implemented */ } diff --git a/audit-linux.c b/audit-linux.c -index d484b82b4..dcfde3a92 100644 +index 4d3e9d41e..d2bc0b526 100644 --- a/audit-linux.c +++ b/audit-linux.c @@ -52,7 +52,7 @@ extern u_int utmp_len; @@ -36,8 +36,8 @@ index d484b82b4..dcfde3a92 100644 const char *ip, const char *ttyn, int success, int event) { int audit_fd, rc, saved_errno; -@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const char *username, - } +@@ -68,7 +68,7 @@ linux_audit_user_logxxx(int uid, const char *username, + hostname = NULL; rc = audit_log_acct_message(audit_fd, event, NULL, "login", username ? username : "(unknown)", - username == NULL ? uid : -1, NULL, ip, ttyn, success); @@ -45,7 +45,7 @@ index d484b82b4..dcfde3a92 100644 saved_errno = errno; close(audit_fd); -@@ -137,10 +137,12 @@ fatal_report: +@@ -139,10 +139,12 @@ fatal_report: } int @@ -59,7 +59,7 @@ index d484b82b4..dcfde3a92 100644 audit_fd = audit_open(); if (audit_fd < 0) { -@@ -150,14 +152,44 @@ audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) +@@ -152,14 +154,44 @@ audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) else return 0; /* Must prevent login */ } @@ -107,7 +107,7 @@ index d484b82b4..dcfde3a92 100644 out: saved_errno = errno; audit_close(audit_fd); -@@ -179,26 +211,34 @@ audit_connection_from(const char *host, int port) +@@ -181,26 +213,34 @@ audit_connection_from(const char *host, int port) int audit_run_command(struct ssh *ssh, const char *command) { @@ -142,7 +142,7 @@ index d484b82b4..dcfde3a92 100644 } void -@@ -211,31 +251,41 @@ void +@@ -213,31 +253,41 @@ void audit_session_open(struct logininfo *li) { if (!user_login_count++) @@ -189,7 +189,7 @@ index d484b82b4..dcfde3a92 100644 ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); break; case SSH_AUTH_FAIL_PASSWD: -@@ -255,9 +305,11 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) +@@ -257,9 +307,11 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) if (user_login_count) { while (user_login_count--) linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, @@ -201,7 +201,7 @@ index d484b82b4..dcfde3a92 100644 ssh_remote_ipaddr(ssh), "ssh", 1, AUDIT_USER_LOGOUT); } -@@ -266,12 +318,14 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) +@@ -268,12 +320,14 @@ audit_event(struct ssh *ssh, ssh_audit_event_t event) case SSH_CONNECTION_ABANDON: case SSH_INVALID_USER: linux_audit_user_logxxx(-1, audit_username(), @@ -209,7 +209,7 @@ index d484b82b4..dcfde3a92 100644 ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN); break; default: - debug("%s: unhandled event %d", __func__, event); + debug_f("unhandled event %d", event); break; } + free(audit_hostname); diff --git a/0040-openssh-7.7p1-fips.patch b/0038-openssh-7.7p1-fips.patch similarity index 89% rename from 0040-openssh-7.7p1-fips.patch rename to 0038-openssh-7.7p1-fips.patch index 36e9f48..18ebed3 100644 --- a/0040-openssh-7.7p1-fips.patch +++ b/0038-openssh-7.7p1-fips.patch @@ -1,7 +1,7 @@ -From 8b15e752713a43b5f745f1aff908a621ae64a958 Mon Sep 17 00:00:00 2001 +From d7dd45f9e19a71269828bc5f8567613a02f6feef Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 28 Aug 2025 14:01:38 +0200 -Subject: [PATCH 40/53] openssh-7.7p1-fips +Subject: [PATCH 38/53] openssh-7.7p1-fips --- dh.c | 41 ++++++++++++++++++++++ @@ -13,10 +13,10 @@ Subject: [PATCH 40/53] openssh-7.7p1-fips myproposal.h | 33 ++++++++++++++++++ readconf.c | 16 ++++++--- sandbox-seccomp-filter.c | 3 ++ - servconf.c | 16 ++++++--- + servconf.c | 18 +++++++--- ssh-ed25519.c | 9 +++++ ssh-gss.h | 5 +++ - ssh-keygen.c | 22 ++++++++++-- + ssh-keygen.c | 20 +++++++++-- ssh-rsa.c | 3 ++ ssh.c | 5 +++ sshconnect2.c | 9 ++++- @@ -101,7 +101,7 @@ index c6326a39d..e51e292b8 100644 u_int dh_estimate(int); void dh_set_moduli_file(const char *); diff --git a/kex-names.c b/kex-names.c -index 6c0b7c2b3..cd3902ad2 100644 +index 31e395aa2..1360a4095 100644 --- a/kex-names.c +++ b/kex-names.c @@ -33,6 +33,7 @@ @@ -112,7 +112,7 @@ index 6c0b7c2b3..cd3902ad2 100644 #include #endif -@@ -206,7 +207,10 @@ kex_names_valid(const char *names) +@@ -208,7 +209,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (kex_alg_by_name(p) == NULL) { @@ -125,10 +125,10 @@ index 6c0b7c2b3..cd3902ad2 100644 return 0; } diff --git a/kex.c b/kex.c -index 62f607d6f..71fbe5cbe 100644 +index 44f350ce8..da2a537ce 100644 --- a/kex.c +++ b/kex.c -@@ -40,6 +40,7 @@ +@@ -38,6 +38,7 @@ #ifdef WITH_OPENSSL #include #include @@ -136,7 +136,7 @@ index 62f607d6f..71fbe5cbe 100644 # ifdef HAVE_EVP_KDF_CTX_NEW # include # include -@@ -109,7 +110,7 @@ kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX], +@@ -107,7 +108,7 @@ kex_proposal_populate_entries(struct ssh *ssh, char *prop[PROPOSAL_MAX], /* Append EXT_INFO signalling to KexAlgorithms */ if (kexalgos == NULL) @@ -146,7 +146,7 @@ index 62f607d6f..71fbe5cbe 100644 "ext-info-s,kex-strict-s-v00@openssh.com" : "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL) diff --git a/kexgen.c b/kexgen.c -index 15df591ca..eecdceba2 100644 +index 58edc79ad..9a970adf1 100644 --- a/kexgen.c +++ b/kexgen.c @@ -31,6 +31,7 @@ @@ -159,7 +159,7 @@ index 15df591ca..eecdceba2 100644 #include "kex.h" @@ -115,13 +116,28 @@ kex_gen_client(struct ssh *ssh) break; - #endif + #endif /* WITH_OPENSSL */ case KEX_C25519_SHA256: - r = kex_c25519_keypair(kex); + if (FIPS_mode()) { @@ -191,7 +191,7 @@ index 15df591ca..eecdceba2 100644 r = SSH_ERR_INVALID_ARGUMENT; @@ -189,15 +205,30 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) break; - #endif + #endif /* WITH_OPENSSL */ case KEX_C25519_SHA256: - r = kex_c25519_dec(kex, server_blob, &shared_secret); + if (FIPS_mode()) { @@ -227,7 +227,7 @@ index 15df591ca..eecdceba2 100644 r = SSH_ERR_INVALID_ARGUMENT; @@ -312,16 +343,31 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) break; - #endif + #endif /* WITH_OPENSSL */ case KEX_C25519_SHA256: - r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, - &shared_secret); @@ -264,7 +264,7 @@ index 15df591ca..eecdceba2 100644 default: r = SSH_ERR_INVALID_ARGUMENT; diff --git a/kexgexc.c b/kexgexc.c -index e99e0cf21..4c3feae09 100644 +index 097d83f30..ccbb9b580 100644 --- a/kexgexc.c +++ b/kexgexc.c @@ -28,6 +28,7 @@ @@ -274,7 +274,7 @@ index e99e0cf21..4c3feae09 100644 +#include #include - #include + #include "openbsd-compat/openssl-compat.h" @@ -115,6 +116,10 @@ input_kex_dh_gex_group(int type, u_int32_t seq, struct ssh *ssh) r = SSH_ERR_ALLOC_FAIL; goto out; @@ -338,10 +338,10 @@ index 8fe9276c2..3e0ec6826 100644 #define SSH_ALLOWED_CA_SIGALGS \ "ssh-ed25519," \ diff --git a/readconf.c b/readconf.c -index f340bf501..ea9d293c3 100644 +index 3f67f4de4..b6ad47b49 100644 --- a/readconf.c +++ b/readconf.c -@@ -43,6 +43,7 @@ +@@ -39,6 +39,7 @@ #include #include #include @@ -349,7 +349,7 @@ index f340bf501..ea9d293c3 100644 #ifdef USE_SYSTEM_GLOB # include #else -@@ -3043,11 +3044,16 @@ fill_default_options(Options * options) +@@ -3078,11 +3079,16 @@ fill_default_options(Options * options) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); /* remove unsupported algos from default lists */ @@ -372,10 +372,10 @@ index f340bf501..ea9d293c3 100644 do { \ if ((r = kex_assemble_names(&options->what, \ diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index 1fabf99d0..ccb61586e 100644 +index e0f2d4289..c52f64897 100644 --- a/sandbox-seccomp-filter.c +++ b/sandbox-seccomp-filter.c -@@ -230,6 +230,9 @@ static const struct sock_filter preauth_insns[] = { +@@ -258,6 +258,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_open SC_DENY(__NR_open, EACCES), #endif @@ -386,18 +386,21 @@ index 1fabf99d0..ccb61586e 100644 SC_DENY(__NR_openat, EACCES), #endif diff --git a/servconf.c b/servconf.c -index 84891544b..8b708cbf4 100644 +index ac84b74d9..f78615c28 100644 --- a/servconf.c +++ b/servconf.c -@@ -37,6 +37,7 @@ +@@ -37,7 +37,10 @@ #include #include #include +#include - #ifdef HAVE_UTIL_H ++#ifdef HAVE_UTIL_H #include - #endif -@@ -247,11 +248,16 @@ assemble_algorithms(ServerOptions *o) ++#endif + #ifdef USE_SYSTEM_GLOB + # include + #else +@@ -244,11 +247,16 @@ assemble_algorithms(ServerOptions *o) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); /* remove unsupported algos from default lists */ @@ -420,7 +423,7 @@ index 84891544b..8b708cbf4 100644 do { \ if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ diff --git a/ssh-ed25519.c b/ssh-ed25519.c -index 22d8db026..41942f4e5 100644 +index c8caa2221..4bcd9ef81 100644 --- a/ssh-ed25519.c +++ b/ssh-ed25519.c @@ -24,6 +24,7 @@ @@ -431,7 +434,7 @@ index 22d8db026..41942f4e5 100644 #include "log.h" #include "sshbuf.h" -@@ -164,6 +165,10 @@ ssh_ed25519_sign(struct sshkey *key, +@@ -163,6 +164,10 @@ ssh_ed25519_sign(struct sshkey *key, key->ed25519_sk == NULL || datalen >= INT_MAX - crypto_sign_ed25519_BYTES) return SSH_ERR_INVALID_ARGUMENT; @@ -442,7 +445,7 @@ index 22d8db026..41942f4e5 100644 smlen = slen = datalen + crypto_sign_ed25519_BYTES; if ((sig = malloc(slen)) == NULL) return SSH_ERR_ALLOC_FAIL; -@@ -221,6 +226,10 @@ ssh_ed25519_verify(const struct sshkey *key, +@@ -244,6 +249,10 @@ ssh_ed25519_verify(const struct sshkey *key, dlen >= INT_MAX - crypto_sign_ed25519_BYTES || sig == NULL || siglen == 0) return SSH_ERR_INVALID_ARGUMENT; @@ -470,39 +473,37 @@ index a894e23c9..329dc9da0 100644 typedef struct { diff --git a/ssh-keygen.c b/ssh-keygen.c -index 16cff9473..792aafde0 100644 +index 3c582a83a..afa279097 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c -@@ -20,6 +20,7 @@ - - #ifdef WITH_OPENSSL +@@ -22,6 +22,7 @@ + #include "openbsd-compat/openssl-compat.h" + #include #include +#include #include - #include "openbsd-compat/openssl-compat.h" #endif + @@ -68,6 +69,7 @@ - #include "cipher.h" + #endif #define DEFAULT_KEY_TYPE_NAME "ed25519" +#define FIPS_DEFAULT_KEY_TYPE_NAME "rsa" /* - * Default number of bits in the RSA, DSA and ECDSA keys. These value can be -@@ -202,6 +204,12 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) + * Default number of bits in the RSA and ECDSA keys. These value can be +@@ -195,6 +197,10 @@ type_bits_valid(int type, const char *name, u_int32_t *bitsp) #endif } #ifdef WITH_OPENSSL + if (FIPS_mode()) { -+ if (type == KEY_DSA) -+ fatal("DSA keys are not allowed in FIPS mode"); + if (type == KEY_ED25519 || type == KEY_ED25519_SK) + fatal("ED25519 keys are not allowed in FIPS mode"); + } switch (type) { - case KEY_DSA: - if (*bitsp != 1024) -@@ -259,7 +267,7 @@ ask_filename(struct passwd *pw, const char *prompt) + case KEY_RSA: + if (*bitsp < SSH_RSA_MINIMUM_MODULUS_SIZE) +@@ -248,7 +254,7 @@ ask_filename(struct passwd *pw, const char *prompt) char *name = NULL; if (key_type_name == NULL) @@ -510,15 +511,15 @@ index 16cff9473..792aafde0 100644 + name = FIPS_mode() ? _PATH_SSH_CLIENT_ID_RSA : _PATH_SSH_CLIENT_ID_ED25519; else { switch (sshkey_type_from_shortname(key_type_name)) { - #ifdef WITH_DSA -@@ -1144,9 +1152,17 @@ do_gen_all_hostkeys(struct passwd *pw) + #ifdef OPENSSL_HAS_ECC +@@ -1057,9 +1063,17 @@ do_gen_all_hostkeys(struct passwd *pw) first = 1; printf("%s: generating new host keys: ", __progname); } + type = sshkey_type_from_shortname(key_types[i].key_type); + + /* Skip the keys that are not supported in FIPS mode */ -+ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) { ++ if (FIPS_mode() && type == KEY_ED25519) { + logit("Skipping %s key in FIPS mode", + key_types[i].key_type_display); + goto next; @@ -530,7 +531,7 @@ index 16cff9473..792aafde0 100644 if ((fd = mkstemp(prv_tmp)) == -1) { error("Could not save your private key in %s: %s", prv_tmp, strerror(errno)); -@@ -3849,7 +3865,7 @@ main(int argc, char **argv) +@@ -3757,7 +3771,7 @@ main(int argc, char **argv) } if (key_type_name == NULL) @@ -540,11 +541,11 @@ index 16cff9473..792aafde0 100644 type = sshkey_type_from_shortname(key_type_name); type_bits_valid(type, key_type_name, &bits); diff --git a/ssh-rsa.c b/ssh-rsa.c -index 3ad1fddc4..6c2f771a3 100644 +index fe1518984..9428df8d1 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c -@@ -23,6 +23,7 @@ - +@@ -25,6 +25,7 @@ + #include #include #include +#include @@ -561,10 +562,10 @@ index 3ad1fddc4..6c2f771a3 100644 goto out; } diff --git a/ssh.c b/ssh.c -index 98b103c9e..abc8b8439 100644 +index 8d27f6379..7d6ba516e 100644 --- a/ssh.c +++ b/ssh.c -@@ -78,6 +78,7 @@ +@@ -74,6 +74,7 @@ #include #include #endif @@ -572,7 +573,7 @@ index 98b103c9e..abc8b8439 100644 #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" -@@ -1642,6 +1643,10 @@ main(int ac, char **av) +@@ -1664,6 +1665,10 @@ main(int ac, char **av) exit(0); } @@ -584,7 +585,7 @@ index 98b103c9e..abc8b8439 100644 if (options.sk_provider != NULL && *options.sk_provider == '$' && strlen(options.sk_provider) > 1) { diff --git a/sshconnect2.c b/sshconnect2.c -index 0af15bcc1..3e02f485d 100644 +index b253f991b..fffa66c8d 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -45,6 +45,8 @@ @@ -618,18 +619,18 @@ index 0af15bcc1..3e02f485d 100644 debug("Offering GSSAPI proposal: %s", gss); xasprintf(&myproposal[PROPOSAL_KEX_ALGS], diff --git a/sshd.c b/sshd.c -index 8a99f0b29..5ff0b5ff0 100644 +index ed7faf96d..de2baa5e4 100644 --- a/sshd.c +++ b/sshd.c -@@ -52,6 +52,7 @@ - #endif +@@ -44,6 +44,7 @@ + #include #include #include +#include #include #include #include -@@ -63,6 +64,7 @@ +@@ -55,6 +56,7 @@ #ifdef WITH_OPENSSL #include #include @@ -637,7 +638,7 @@ index 8a99f0b29..5ff0b5ff0 100644 #include "openbsd-compat/openssl-compat.h" #endif -@@ -1611,6 +1613,13 @@ main(int ac, char **av) +@@ -1613,6 +1615,13 @@ main(int ac, char **av) &key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR) do_log2_r(r, ll, "Unable to load host key \"%s\"", options.host_key_files[i]); @@ -651,7 +652,7 @@ index 8a99f0b29..5ff0b5ff0 100644 if (sshkey_is_sk(key) && key->sk_flags & SSH_SK_USER_PRESENCE_REQD) { debug("host key %s requires user presence, ignoring", -@@ -1830,6 +1839,10 @@ main(int ac, char **av) +@@ -1836,6 +1845,10 @@ main(int ac, char **av) /* Reinitialize the log (because of the fork above). */ log_init(__progname, options.log_level, options.log_facility, log_stderr); @@ -663,10 +664,10 @@ index 8a99f0b29..5ff0b5ff0 100644 * Chdir to the root directory so that the current disk can be * unmounted if desired. diff --git a/sshkey.c b/sshkey.c -index 4e41a78c7..ca1cdb642 100644 +index 148fee2b7..394d9b105 100644 --- a/sshkey.c +++ b/sshkey.c -@@ -35,6 +35,7 @@ +@@ -36,6 +36,7 @@ #include #include #include @@ -674,15 +675,15 @@ index 4e41a78c7..ca1cdb642 100644 #endif #include "crypto_api.h" -@@ -59,6 +60,7 @@ +@@ -58,6 +59,7 @@ #define SSHKEY_INTERNAL #include "sshkey.h" #include "match.h" +#include "log.h" #include "ssh-sk.h" + #include "ssh-pkcs11.h" - #ifdef WITH_XMSS -@@ -408,6 +410,18 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) +@@ -386,6 +388,18 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) impl = keyimpls[i]; if (impl->name == NULL || impl->type == KEY_NULL) continue; @@ -701,7 +702,7 @@ index 4e41a78c7..ca1cdb642 100644 if (!include_sigonly && impl->sigonly) continue; if ((certs_only && !impl->cert) || (plain_only && impl->cert)) -@@ -1441,6 +1455,20 @@ sshkey_read(struct sshkey *ret, char **cpp) +@@ -1418,6 +1432,20 @@ sshkey_read(struct sshkey *ret, char **cpp) return SSH_ERR_EC_CURVE_MISMATCH; } @@ -722,7 +723,7 @@ index 4e41a78c7..ca1cdb642 100644 /* Fill in ret from parsed key */ sshkey_free_contents(ret); *ret = *k; -@@ -2275,6 +2303,11 @@ sshkey_sign(struct sshkey *key, +@@ -2251,6 +2279,11 @@ sshkey_sign(struct sshkey *key, *lenp = 0; if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; @@ -734,7 +735,7 @@ index 4e41a78c7..ca1cdb642 100644 if ((impl = sshkey_impl_from_key(key)) == NULL) return SSH_ERR_KEY_TYPE_UNKNOWN; if ((r = sshkey_unshield_private(key)) != 0) -@@ -2311,6 +2344,10 @@ sshkey_verify(const struct sshkey *key, +@@ -2290,6 +2323,10 @@ sshkey_verify(const struct sshkey *key, *detailsp = NULL; if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE) return SSH_ERR_INVALID_ARGUMENT; diff --git a/0041-openssh-8.7p1-ssh-manpage.patch b/0039-openssh-8.7p1-ssh-manpage.patch similarity index 91% rename from 0041-openssh-8.7p1-ssh-manpage.patch rename to 0039-openssh-8.7p1-ssh-manpage.patch index c8e108e..d0e984d 100644 --- a/0041-openssh-8.7p1-ssh-manpage.patch +++ b/0039-openssh-8.7p1-ssh-manpage.patch @@ -1,7 +1,7 @@ -From ed328b6f6d3e88b28934d7d6788f328785be3359 Mon Sep 17 00:00:00 2001 +From 7167a191776dacf7e31cf8a8a2ed89887e49f4ee Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 41/53] openssh-8.7p1-ssh-manpage +Subject: [PATCH 39/53] openssh-8.7p1-ssh-manpage --- ssh.1 | 5 ++++- diff --git a/0042-openssh-8.7p1-negotiate-supported-algs.patch b/0040-openssh-8.7p1-negotiate-supported-algs.patch similarity index 96% rename from 0042-openssh-8.7p1-negotiate-supported-algs.patch rename to 0040-openssh-8.7p1-negotiate-supported-algs.patch index 6f17b9a..29f8213 100644 --- a/0042-openssh-8.7p1-negotiate-supported-algs.patch +++ b/0040-openssh-8.7p1-negotiate-supported-algs.patch @@ -1,7 +1,7 @@ -From 028e2f357f3ed905f512dda984055b7db083a790 Mon Sep 17 00:00:00 2001 +From 53e44bd1f669ecd6a7429e94b55beec8e3c0c529 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 42/53] openssh-8.7p1-negotiate-supported-algs +Subject: [PATCH 40/53] openssh-8.7p1-negotiate-supported-algs --- regress/hostkey-agent.sh | 32 +++++++++++++++++++++++++------- @@ -84,7 +84,7 @@ index 28dcfe170..b9e716dcd 100644 opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` diff --git a/sshconnect2.c b/sshconnect2.c -index 3e02f485d..e7e3da669 100644 +index fffa66c8d..f43c81ad9 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -221,7 +221,7 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, diff --git a/0043-openssh-9.0p1-evp-fips-kex.patch b/0041-openssh-9.0p1-evp-fips-kex.patch similarity index 95% rename from 0043-openssh-9.0p1-evp-fips-kex.patch rename to 0041-openssh-9.0p1-evp-fips-kex.patch index a21e234..24ef8e8 100644 --- a/0043-openssh-9.0p1-evp-fips-kex.patch +++ b/0041-openssh-9.0p1-evp-fips-kex.patch @@ -1,7 +1,7 @@ -From 01f8e0679caa93447159430c1067b29909a7aa94 Mon Sep 17 00:00:00 2001 +From 1c0d3b6e9868ef31b97be1679389e3db2616eccd Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 43/53] openssh-9.0p1-evp-fips-kex +Subject: [PATCH 41/53] openssh-9.0p1-evp-fips-kex --- dh.c | 98 +++++++++++++++++++++++++++++++++----- @@ -140,10 +140,10 @@ index 8c9a29fa7..ea0a0b093 100644 DH * diff --git a/kex.c b/kex.c -index 71fbe5cbe..ce6a7b818 100644 +index da2a537ce..56c80395c 100644 --- a/kex.c +++ b/kex.c -@@ -1614,3 +1614,142 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, +@@ -1613,3 +1613,142 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms, return r; } @@ -287,7 +287,7 @@ index 71fbe5cbe..ce6a7b818 100644 +} +#endif /* WITH_OPENSSL */ diff --git a/kex.h b/kex.h -index 6a55aadf4..48f3bb875 100644 +index cb06e85a3..6daafb159 100644 --- a/kex.h +++ b/kex.h @@ -37,6 +37,9 @@ @@ -300,7 +300,7 @@ index 6a55aadf4..48f3bb875 100644 # ifdef OPENSSL_HAS_ECC # include # else /* OPENSSL_HAS_ECC */ -@@ -311,6 +314,9 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], +@@ -316,6 +319,9 @@ int kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE], const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int) __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); @@ -311,12 +311,12 @@ index 6a55aadf4..48f3bb875 100644 #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) void dump_digest(const char *, const u_char *, int); diff --git a/kexdh.c b/kexdh.c -index 0faab21b0..32e1de514 100644 +index 6d5a7813d..b05277aa1 100644 --- a/kexdh.c +++ b/kexdh.c -@@ -35,6 +35,10 @@ - +@@ -36,6 +36,10 @@ #include "openbsd-compat/openssl-compat.h" + #include #include +#include +#include @@ -325,7 +325,7 @@ index 0faab21b0..32e1de514 100644 #include "sshkey.h" #include "kex.h" -@@ -83,9 +87,12 @@ int +@@ -84,9 +88,12 @@ int kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) { BIGNUM *shared_secret = NULL; @@ -339,7 +339,7 @@ index 0faab21b0..32e1de514 100644 #ifdef DEBUG_KEXDH fprintf(stderr, "dh_pub= "); -@@ -100,24 +107,59 @@ kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) +@@ -101,24 +108,59 @@ kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) r = SSH_ERR_MESSAGE_INCOMPLETE; goto out; } @@ -404,12 +404,12 @@ index 0faab21b0..32e1de514 100644 } diff --git a/kexecdh.c b/kexecdh.c -index efb2e55a6..d92ba54f8 100644 +index 500ec5725..1a1bae35e 100644 --- a/kexecdh.c +++ b/kexecdh.c -@@ -35,17 +35,57 @@ - #include +@@ -36,17 +36,57 @@ + #include #include +#include +#include @@ -465,7 +465,7 @@ index efb2e55a6..d92ba54f8 100644 int kex_ecdh_keypair(struct kex *kex) { -@@ -55,11 +95,7 @@ kex_ecdh_keypair(struct kex *kex) +@@ -56,11 +96,7 @@ kex_ecdh_keypair(struct kex *kex) struct sshbuf *buf = NULL; int r; @@ -478,7 +478,7 @@ index efb2e55a6..d92ba54f8 100644 r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } -@@ -101,11 +137,7 @@ kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob, +@@ -102,11 +138,7 @@ kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob, *server_blobp = NULL; *shared_secretp = NULL; @@ -491,7 +491,7 @@ index efb2e55a6..d92ba54f8 100644 r = SSH_ERR_LIBCRYPTO_ERROR; goto out; } -@@ -140,11 +172,21 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, +@@ -141,11 +173,21 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, { struct sshbuf *buf = NULL; BIGNUM *shared_secret = NULL; @@ -516,7 +516,7 @@ index efb2e55a6..d92ba54f8 100644 *shared_secretp = NULL; if ((buf = sshbuf_new()) == NULL) { -@@ -153,45 +195,82 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, +@@ -154,45 +196,82 @@ kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob, } if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0) goto out; diff --git a/0044-openssh-8.7p1-nohostsha1proof.patch b/0042-openssh-8.7p1-nohostsha1proof.patch similarity index 84% rename from 0044-openssh-8.7p1-nohostsha1proof.patch rename to 0042-openssh-8.7p1-nohostsha1proof.patch index 8da1b2b..681d051 100644 --- a/0044-openssh-8.7p1-nohostsha1proof.patch +++ b/0042-openssh-8.7p1-nohostsha1proof.patch @@ -1,21 +1,21 @@ -From 80160fc4e11c894ca0bbf5fe51254933190cfb90 Mon Sep 17 00:00:00 2001 +From 1cd47036353899fe066f5241d3d70778f103c0e0 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 44/53] openssh-8.7p1-nohostsha1proof +Subject: [PATCH 42/53] openssh-8.7p1-nohostsha1proof --- - compat.c | 6 +++++ + compat.c | 6 ++++++ compat.h | 2 +- - monitor.c | 27 ++++++++++++++++------ + monitor.c | 27 +++++++++++++++++------ regress/unittests/kex/test_kex.c | 3 ++- regress/unittests/sshkey/test_file.c | 3 ++- regress/unittests/sshkey/test_fuzz.c | 3 ++- - regress/unittests/sshkey/test_sshkey.c | 32 +++++++++++++++++--------- - serverloop.c | 6 ++++- + regress/unittests/sshkey/test_sshkey.c | 30 ++++++++++++++++---------- + serverloop.c | 6 +++++- ssh-rsa.c | 3 ++- sshconnect2.c | 8 +++++++ - sshd-session.c | 21 +++++++++++++++++ - 11 files changed, 90 insertions(+), 24 deletions(-) + sshd-session.c | 21 ++++++++++++++++++ + 11 files changed, 88 insertions(+), 24 deletions(-) diff --git a/compat.c b/compat.c index b59f0bfc0..4e611dc39 100644 @@ -65,10 +65,10 @@ index 1a19060fc..2e6db5bf9 100644 /* #define unused 0x00000020 */ #define SSH_BUG_DEBUG 0x00000040 diff --git a/monitor.c b/monitor.c -index fbc357825..19cb058ee 100644 +index b2f501790..6c83739ee 100644 --- a/monitor.c +++ b/monitor.c -@@ -747,11 +747,12 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -754,11 +754,12 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) struct sshkey *pubkey, *key; struct sshbuf *sigbuf = NULL; u_char *p = NULL, *signature = NULL; @@ -85,7 +85,7 @@ index fbc357825..19cb058ee 100644 debug3_f("entering"); -@@ -809,18 +810,30 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) +@@ -816,18 +817,30 @@ mm_answer_sign(struct ssh *ssh, int sock, struct sshbuf *m) } if ((key = get_hostkey_by_index(keyid)) != NULL) { @@ -120,13 +120,13 @@ index fbc357825..19cb058ee 100644 sshbuf_reset(m); diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c -index caf8f57f7..09016aead 100644 +index 16c2f2dff..f4700deeb 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c -@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype, int bits) - memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); - if (kex != NULL) - kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; +@@ -110,7 +110,8 @@ do_kex_with_key(char *kex, char *cipher, char *mac, + kex_params.proposal[PROPOSAL_MAC_ALGS_CTOS] = mac; + kex_params.proposal[PROPOSAL_MAC_ALGS_STOC] = mac; + } - keyname = strdup(sshkey_ssh_name(private)); + keyname = (strcmp(sshkey_ssh_name(private), "ssh-rsa")) ? + strdup(sshkey_ssh_name(private)) : strdup("rsa-sha2-256"); @@ -134,10 +134,10 @@ index caf8f57f7..09016aead 100644 kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname; ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0); diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c -index 3babe604d..cc80fe97c 100644 +index e412b75d8..5b06bc905 100644 --- a/regress/unittests/sshkey/test_file.c +++ b/regress/unittests/sshkey/test_file.c -@@ -109,6 +109,7 @@ sshkey_file_tests(void) +@@ -106,6 +106,7 @@ sshkey_file_tests(void) sshkey_free(k2); TEST_DONE(); @@ -145,7 +145,7 @@ index 3babe604d..cc80fe97c 100644 TEST_START("load RSA cert with SHA1 signature"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha1"), &k2), 0); ASSERT_PTR_NE(k2, NULL); -@@ -116,7 +117,7 @@ sshkey_file_tests(void) +@@ -113,7 +114,7 @@ sshkey_file_tests(void) ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa"); sshkey_free(k2); @@ -155,10 +155,10 @@ index 3babe604d..cc80fe97c 100644 TEST_START("load RSA cert with SHA512 signature"); ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1_sha512"), &k2), 0); diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c -index 0aff7c9bf..951122e1a 100644 +index d0f47d7cf..ba4d506d5 100644 --- a/regress/unittests/sshkey/test_fuzz.c +++ b/regress/unittests/sshkey/test_fuzz.c -@@ -338,13 +338,14 @@ sshkey_fuzz_tests(void) +@@ -273,13 +273,14 @@ sshkey_fuzz_tests(void) TEST_DONE(); #ifdef WITH_OPENSSL @@ -175,10 +175,10 @@ index 0aff7c9bf..951122e1a 100644 TEST_START("fuzz RSA SHA256 sig"); buf = load_file("rsa_1"); diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c -index 5bf4b65cc..6d0a35bbf 100644 +index d0c46a90b..7b5e51b83 100644 --- a/regress/unittests/sshkey/test_sshkey.c +++ b/regress/unittests/sshkey/test_sshkey.c -@@ -61,6 +61,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type, +@@ -59,6 +59,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type, u_char *sigblob; size_t siglen; @@ -188,7 +188,7 @@ index 5bf4b65cc..6d0a35bbf 100644 ca_buf = sshbuf_new(); ASSERT_PTR_NE(ca_buf, NULL); ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0); -@@ -102,8 +105,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type, +@@ -100,8 +103,9 @@ build_cert(struct sshbuf *b, struct sshkey *k, const char *type, ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */ ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */ ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen, @@ -200,14 +200,12 @@ index 5bf4b65cc..6d0a35bbf 100644 free(sigblob); sshbuf_free(ca_buf); -@@ -120,16 +124,22 @@ signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg, +@@ -118,16 +122,20 @@ signature_test(struct sshkey *k, struct sshkey *bad, const char *sig_alg, { size_t len; u_char *sig; -+ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp in RHEL, permitted in Fedora */ ++ /* ssh-rsa implies SHA1, forbidden in DEFAULT crypto policies */ + int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0) : 0; -+ if (k && (sshkey_type_plain(k->type) == KEY_DSA || sshkey_type_plain(k->type) == KEY_DSA_CERT)) -+ expected = sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0); ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, - NULL, NULL, 0), 0); @@ -231,7 +229,7 @@ index 5bf4b65cc..6d0a35bbf 100644 free(sig); } -@@ -526,7 +536,7 @@ sshkey_tests(void) +@@ -552,7 +560,7 @@ sshkey_tests(void) ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, NULL), 0); k3 = get_private("rsa_1"); @@ -241,10 +239,10 @@ index 5bf4b65cc..6d0a35bbf 100644 SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); ASSERT_PTR_EQ(k4, NULL); diff --git a/serverloop.c b/serverloop.c -index 40ddfb042..9c5b15678 100644 +index 5d3b194d1..55411a6b4 100644 --- a/serverloop.c +++ b/serverloop.c -@@ -80,6 +80,7 @@ +@@ -76,6 +76,7 @@ #include "auth-options.h" #include "serverloop.h" #include "ssherr.h" @@ -252,7 +250,7 @@ index 40ddfb042..9c5b15678 100644 extern ServerOptions options; -@@ -699,7 +700,10 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) +@@ -721,7 +722,10 @@ server_input_hostkeys_prove(struct ssh *ssh, struct sshbuf **respp) else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) sigalg = "rsa-sha2-256"; } @@ -265,10 +263,10 @@ index 40ddfb042..9c5b15678 100644 sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); if ((r = sshbuf_put_cstring(sigbuf, diff --git a/ssh-rsa.c b/ssh-rsa.c -index 6c2f771a3..8dd4ab01e 100644 +index 9428df8d1..7843f3e26 100644 --- a/ssh-rsa.c +++ b/ssh-rsa.c -@@ -509,7 +509,8 @@ ssh_rsa_verify(const struct sshkey *key, +@@ -533,7 +533,8 @@ ssh_rsa_verify(const struct sshkey *key, ret = SSH_ERR_INVALID_ARGUMENT; goto out; } @@ -279,7 +277,7 @@ index 6c2f771a3..8dd4ab01e 100644 goto out; } diff --git a/sshconnect2.c b/sshconnect2.c -index e7e3da669..5beae1c10 100644 +index f43c81ad9..2d98fc3da 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -1434,6 +1434,14 @@ identity_sign(struct identity *id, u_char **sigp, size_t *lenp, @@ -298,10 +296,10 @@ index e7e3da669..5beae1c10 100644 } diff --git a/sshd-session.c b/sshd-session.c -index 5eae9aed7..7aa767020 100644 +index e49e4fb51..a558bbc33 100644 --- a/sshd-session.c +++ b/sshd-session.c -@@ -1316,6 +1316,27 @@ main(int ac, char **av) +@@ -1288,6 +1288,27 @@ main(int ac, char **av) check_ip_options(ssh); diff --git a/0046-openssh-9.9p1-separate-keysign.patch b/0043-openssh-9.9p1-separate-keysign.patch similarity index 77% rename from 0046-openssh-9.9p1-separate-keysign.patch rename to 0043-openssh-9.9p1-separate-keysign.patch index 4180959..60a6d4f 100644 --- a/0046-openssh-9.9p1-separate-keysign.patch +++ b/0043-openssh-9.9p1-separate-keysign.patch @@ -1,14 +1,14 @@ -From 4ab4e72b3c16635cde9c03d2d95f3948cb21d445 Mon Sep 17 00:00:00 2001 +From 1799ea7ad21a579b864a536709d732f4a8e533dc Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 46/53] openssh-9.9p1-separate-keysign +Subject: [PATCH 43/53] openssh-9.9p1-separate-keysign --- ssh_config.5 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ssh_config.5 b/ssh_config.5 -index a43b2a276..9d5da2a68 100644 +index 8ac5e1633..a06fbfa11 100644 --- a/ssh_config.5 +++ b/ssh_config.5 @@ -797,7 +797,7 @@ or diff --git a/0047-openssh-9.9p1-openssl-mlkem.patch b/0044-openssh-9.9p1-openssl-mlkem.patch similarity index 91% rename from 0047-openssh-9.9p1-openssl-mlkem.patch rename to 0044-openssh-9.9p1-openssl-mlkem.patch index bc0b886..3e72647 100644 --- a/0047-openssh-9.9p1-openssl-mlkem.patch +++ b/0044-openssh-9.9p1-openssl-mlkem.patch @@ -1,19 +1,19 @@ -From 793361ec77a36ebf008b595cf5c14ef9df8f22ff Mon Sep 17 00:00:00 2001 +From 21202362f4ddaeb630d873fb426039004ac82338 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 47/53] openssh-9.9p1-openssl-mlkem +Subject: [PATCH 44/53] openssh-9.9p1-openssl-mlkem --- - kex-names.c | 20 +++ + kex-names.c | 23 +++- kexmlkem768x25519.c | 291 ++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 311 insertions(+) + 2 files changed, 313 insertions(+), 1 deletion(-) diff --git a/kex-names.c b/kex-names.c -index cd3902ad2..36a953ab2 100644 +index 1360a4095..9c96e5cb0 100644 --- a/kex-names.c +++ b/kex-names.c -@@ -108,6 +108,19 @@ static const struct kexalg gss_kexalgs[] = { - { NULL, 0, -1, -1}, +@@ -109,6 +109,19 @@ static const struct kexalg gss_kexalgs[] = { + { NULL, 0, -1, -1, 0}, }; +static int is_mlkem768_available() @@ -32,17 +32,21 @@ index cd3902ad2..36a953ab2 100644 static char * kex_alg_list_internal(char sep, const struct kexalg *algs) { -@@ -116,6 +129,9 @@ kex_alg_list_internal(char sep, const struct kexalg *algs) +@@ -116,8 +129,12 @@ kex_alg_list_internal(char sep, const struct kexalg *algs) const struct kexalg *k; + char sep_str[2] = {sep, '\0'}; - for (k = algs; k->name != NULL; k++) { +- for (k = kexalgs; k->name != NULL; k++) ++ for (k = kexalgs; k->name != NULL; k++) { + if (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0 + && !is_mlkem768_available()) + continue; - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(k->name); -@@ -147,6 +163,10 @@ kex_alg_by_name(const char *name) + xextendf(&ret, sep_str, "%s", k->name); ++ } + + return ret; + } +@@ -139,6 +156,10 @@ kex_alg_by_name(const char *name) { const struct kexalg *k; @@ -54,10 +58,10 @@ index cd3902ad2..36a953ab2 100644 if (strcmp(k->name, name) == 0) return k; diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c -index 2b5d39608..670049dcd 100644 +index 2585d1db3..ab6167221 100644 --- a/kexmlkem768x25519.c +++ b/kexmlkem768x25519.c -@@ -48,10 +48,127 @@ +@@ -44,10 +44,127 @@ #ifdef USE_MLKEM768X25519 #include "libcrux_mlkem768_sha3.h" @@ -185,7 +189,7 @@ index 2b5d39608..670049dcd 100644 struct sshbuf *buf = NULL; u_char rnd[LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN], *cp = NULL; size_t need; -@@ -86,6 +203,36 @@ kex_kem_mlkem768x25519_keypair(struct kex *kex) +@@ -82,6 +199,36 @@ kex_kem_mlkem768x25519_keypair(struct kex *kex) explicit_bzero(rnd, sizeof(rnd)); sshbuf_free(buf); return r; @@ -222,7 +226,7 @@ index 2b5d39608..670049dcd 100644 } int -@@ -93,6 +240,7 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, +@@ -89,6 +236,7 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, const struct sshbuf *client_blob, struct sshbuf **server_blobp, struct sshbuf **shared_secretp) { @@ -230,7 +234,7 @@ index 2b5d39608..670049dcd 100644 struct sshbuf *server_blob = NULL; struct sshbuf *buf = NULL; const u_char *client_pub; -@@ -185,12 +333,97 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, +@@ -181,12 +329,97 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, sshbuf_free(server_blob); sshbuf_free(buf); return r; @@ -328,7 +332,7 @@ index 2b5d39608..670049dcd 100644 struct sshbuf *buf = NULL; u_char mlkem_key[crypto_kem_mlkem768_BYTES]; const u_char *ciphertext, *server_pub; -@@ -258,6 +491,64 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, +@@ -254,6 +487,64 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, explicit_bzero(mlkem_key, sizeof(mlkem_key)); sshbuf_free(buf); return r; diff --git a/0045-openssh-9.6p1-pam-rhost.patch b/0045-openssh-9.6p1-pam-rhost.patch deleted file mode 100644 index 690e475..0000000 --- a/0045-openssh-9.6p1-pam-rhost.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 9d41ec0c0d8de6637677c9ab7605c9e1104e5d28 Mon Sep 17 00:00:00 2001 -From: Dmitry Belyavskiy -Date: Thu, 15 May 2025 13:43:29 +0200 -Subject: [PATCH 45/53] openssh-9.6p1-pam-rhost - ---- - auth-pam.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/auth-pam.c b/auth-pam.c -index a042c3c8e..a321e0d3e 100644 ---- a/auth-pam.c -+++ b/auth-pam.c -@@ -741,7 +741,7 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt) - sshpam_laddr = get_local_ipaddr( - ssh_packet_get_connection_in(ssh)); - } -- if (sshpam_rhost != NULL) { -+ if (sshpam_rhost != NULL && strcmp(sshpam_rhost, "UNKNOWN") != 0) { - debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost); - sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST, - sshpam_rhost); --- -2.52.0 - diff --git a/0048-openssh-9.9p2-error_processing.patch b/0045-openssh-9.9p2-error_processing.patch similarity index 69% rename from 0048-openssh-9.9p2-error_processing.patch rename to 0045-openssh-9.9p2-error_processing.patch index cc4c825..48aa76a 100644 --- a/0048-openssh-9.9p2-error_processing.patch +++ b/0045-openssh-9.9p2-error_processing.patch @@ -1,17 +1,17 @@ -From 444e38f66ef7454f262beed18734b86279fea88f Mon Sep 17 00:00:00 2001 +From edbbdc306c1710dae777ef315a0d2c5f43134d33 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Fri, 16 May 2025 14:53:54 +0200 -Subject: [PATCH 48/53] openssh-9.9p2-error_processing +Subject: [PATCH 45/53] openssh-9.9p2-error_processing --- ssh-agent.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ssh-agent.c b/ssh-agent.c -index 798bf9b60..dfb6ac725 100644 +index df241379c..dc246066d 100644 --- a/ssh-agent.c +++ b/ssh-agent.c -@@ -1377,6 +1377,8 @@ process_add_identity(SocketEntry *e) +@@ -1346,6 +1346,8 @@ process_add_identity(SocketEntry *e) if ((r = sshkey_private_deserialize(e->request, &k)) != 0 || k == NULL || (r = sshbuf_get_cstring(e->request, &comment, NULL)) != 0) { diff --git a/0049-Provide-better-error-for-non-supported-private-keys.patch b/0046-Provide-better-error-for-non-supported-private-keys.patch similarity index 68% rename from 0049-Provide-better-error-for-non-supported-private-keys.patch rename to 0046-Provide-better-error-for-non-supported-private-keys.patch index 183d9f3..dd30967 100644 --- a/0049-Provide-better-error-for-non-supported-private-keys.patch +++ b/0046-Provide-better-error-for-non-supported-private-keys.patch @@ -1,7 +1,7 @@ -From df9a81d4c07e12c1b2a7dffe5ed9affc228a9842 Mon Sep 17 00:00:00 2001 +From 0772377e00b13f5afaa1b146ce32d0218e9f0d24 Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Wed, 16 Apr 2025 15:11:59 +0200 -Subject: [PATCH 49/53] Provide better error for non-supported private keys +Subject: [PATCH 46/53] Provide better error for non-supported private keys Signed-off-by: Zoltan Fridrich --- @@ -9,10 +9,10 @@ Signed-off-by: Zoltan Fridrich 1 file changed, 3 insertions(+) diff --git a/sshkey.c b/sshkey.c -index ca1cdb642..aada474e0 100644 +index 394d9b105..eba55ef92 100644 --- a/sshkey.c +++ b/sshkey.c -@@ -3582,6 +3582,9 @@ translate_libcrypto_error(unsigned long pem_err) +@@ -3539,6 +3539,9 @@ translate_libcrypto_error(unsigned long pem_err) return SSH_ERR_LIBCRYPTO_ERROR; } case ERR_LIB_ASN1: diff --git a/0050-Ignore-bad-hostkeys-in-known_hosts-file.patch b/0047-Ignore-bad-hostkeys-in-known_hosts-file.patch similarity index 88% rename from 0050-Ignore-bad-hostkeys-in-known_hosts-file.patch rename to 0047-Ignore-bad-hostkeys-in-known_hosts-file.patch index e2d6178..3bfab92 100644 --- a/0050-Ignore-bad-hostkeys-in-known_hosts-file.patch +++ b/0047-Ignore-bad-hostkeys-in-known_hosts-file.patch @@ -1,7 +1,7 @@ -From afcce638f76cfa43d152d4b45e8b986b9de5fab8 Mon Sep 17 00:00:00 2001 +From d458a65ccac2283563c0fc0962519bb5a9bbd315 Mon Sep 17 00:00:00 2001 From: Zoltan Fridrich Date: Mon, 5 May 2025 11:52:25 +0200 -Subject: [PATCH 50/53] Ignore bad hostkeys in known_hosts file +Subject: [PATCH 47/53] Ignore bad hostkeys in known_hosts file Signed-off-by: Zoltan Fridrich --- @@ -11,7 +11,7 @@ Signed-off-by: Zoltan Fridrich 3 files changed, 18 insertions(+) diff --git a/hostfile.c b/hostfile.c -index c5669c703..5c402f501 100644 +index 4cec57da5..652d15762 100644 --- a/hostfile.c +++ b/hostfile.c @@ -63,6 +63,14 @@ @@ -62,10 +62,10 @@ index a24a4e329..0e9b1a19a 100644 #endif diff --git a/ssh.c b/ssh.c -index abc8b8439..33787a8d4 100644 +index 7d6ba516e..320ac6834 100644 --- a/ssh.c +++ b/ssh.c -@@ -110,6 +110,7 @@ +@@ -106,6 +106,7 @@ #include "ssherr.h" #include "myproposal.h" #include "utf8.h" @@ -73,7 +73,7 @@ index abc8b8439..33787a8d4 100644 #ifdef ENABLE_PKCS11 #include "ssh-pkcs11.h" -@@ -1397,6 +1398,7 @@ main(int ac, char **av) +@@ -1409,6 +1410,7 @@ main(int ac, char **av) options.update_hostkeys = 0; } } diff --git a/0051-support-authentication-indicators-in-GSSAPI.patch b/0048-support-authentication-indicators-in-GSSAPI.patch similarity index 95% rename from 0051-support-authentication-indicators-in-GSSAPI.patch rename to 0048-support-authentication-indicators-in-GSSAPI.patch index 646ce48..664a006 100644 --- a/0051-support-authentication-indicators-in-GSSAPI.patch +++ b/0048-support-authentication-indicators-in-GSSAPI.patch @@ -1,7 +1,7 @@ -From 06c50491651d0a916c99126228bc5b2f573fa72f Mon Sep 17 00:00:00 2001 +From 1cf5e40e14d707de2318747758b012fc7245cb7b Mon Sep 17 00:00:00 2001 From: Alexander Bokovoy Date: Mon, 10 Jun 2024 23:00:03 +0300 -Subject: [PATCH 51/53] support authentication indicators in GSSAPI +Subject: [PATCH 48/53] support authentication indicators in GSSAPI RFC 6680 defines a set of GSSAPI extensions to handle attributes associated with the GSSAPI names. MIT Kerberos and FreeIPA use @@ -29,10 +29,10 @@ Signed-off-by: Alexander Bokovoy 7 files changed, 228 insertions(+), 8 deletions(-) diff --git a/configure.ac b/configure.ac -index d92a85809..2cbe20bf3 100644 +index 805be4b5e..9d3b19925 100644 --- a/configure.ac +++ b/configure.ac -@@ -5004,6 +5004,7 @@ AC_ARG_WITH([kerberos5], +@@ -5050,6 +5050,7 @@ AC_ARG_WITH([kerberos5], AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h]) AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h]) AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h]) @@ -143,7 +143,7 @@ index 03188d9b3..2c786ef14 100644 return retval; } diff --git a/gss-serv.c b/gss-serv.c -index 9d5435eda..5c0491cf1 100644 +index d2bc03486..be80e17ca 100644 --- a/gss-serv.c +++ b/gss-serv.c @@ -54,7 +54,7 @@ extern ServerOptions options; @@ -285,10 +285,10 @@ index 9d5435eda..5c0491cf1 100644 sizeof(ssh_gssapi_client)); return 0; diff --git a/servconf.c b/servconf.c -index 8b708cbf4..ecf5c66d4 100644 +index f78615c28..e53e8ea30 100644 --- a/servconf.c +++ b/servconf.c -@@ -147,6 +147,7 @@ initialize_server_options(ServerOptions *options) +@@ -146,6 +146,7 @@ initialize_server_options(ServerOptions *options) options->gss_strict_acceptor = -1; options->gss_store_rekey = -1; options->gss_kex_algorithms = NULL; @@ -296,7 +296,7 @@ index 8b708cbf4..ecf5c66d4 100644 options->use_kuserok = -1; options->enable_k5users = -1; options->password_authentication = -1; -@@ -598,7 +599,7 @@ typedef enum { +@@ -591,7 +592,7 @@ typedef enum { sPerSourcePenalties, sPerSourcePenaltyExemptList, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor, @@ -305,7 +305,7 @@ index 8b708cbf4..ecf5c66d4 100644 sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -694,6 +695,7 @@ static struct { +@@ -687,6 +688,7 @@ static struct { { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL }, @@ -313,7 +313,7 @@ index 8b708cbf4..ecf5c66d4 100644 #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, -@@ -703,6 +705,7 @@ static struct { +@@ -696,6 +698,7 @@ static struct { { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL }, { "gssapienablek5users", sUnsupported, SSHCFG_ALL }, @@ -321,7 +321,7 @@ index 8b708cbf4..ecf5c66d4 100644 #endif { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, -@@ -1730,6 +1733,15 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1722,6 +1725,15 @@ process_server_config_line_depth(ServerOptions *options, char *line, options->gss_kex_algorithms = xstrdup(arg); break; @@ -337,7 +337,7 @@ index 8b708cbf4..ecf5c66d4 100644 case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -3350,6 +3362,7 @@ dump_config(ServerOptions *o) +@@ -3344,6 +3356,7 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms); @@ -346,10 +346,10 @@ index 8b708cbf4..ecf5c66d4 100644 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, diff --git a/servconf.h b/servconf.h -index 7c7e5d434..7c41df417 100644 +index c08cf6a7a..c7cec5ece 100644 --- a/servconf.h +++ b/servconf.h -@@ -181,6 +181,7 @@ typedef struct { +@@ -179,6 +179,7 @@ typedef struct { char **allow_groups; u_int num_deny_groups; char **deny_groups; @@ -357,7 +357,7 @@ index 7c7e5d434..7c41df417 100644 u_int num_subsystems; char **subsystem_name; -@@ -310,6 +311,7 @@ TAILQ_HEAD(include_list, include_item); +@@ -308,6 +309,7 @@ TAILQ_HEAD(include_list, include_item); M_CP_STROPT(routing_domain); \ M_CP_STROPT(permit_user_env_allowlist); \ M_CP_STROPT(pam_service_name); \ @@ -391,7 +391,7 @@ index 329dc9da0..1506719a9 100644 typedef struct ssh_gssapi_mech_struct { diff --git a/sshd_config.5 b/sshd_config.5 -index 583a01cdb..90ab87edd 100644 +index c172d5aab..676d6d4d2 100644 --- a/sshd_config.5 +++ b/sshd_config.5 @@ -785,6 +785,50 @@ gss-nistp256-sha256- diff --git a/0052-NIST-curves-hybrid-KEX-implementation.patch b/0049-NIST-curves-hybrid-KEX-implementation.patch similarity index 73% rename from 0052-NIST-curves-hybrid-KEX-implementation.patch rename to 0049-NIST-curves-hybrid-KEX-implementation.patch index 8edc3ed..9ce23be 100644 --- a/0052-NIST-curves-hybrid-KEX-implementation.patch +++ b/0049-NIST-curves-hybrid-KEX-implementation.patch @@ -1,28 +1,29 @@ -From d064766faf7b874e9e3596b85d1d7b374c76cba4 Mon Sep 17 00:00:00 2001 +From 3642efdf9be4d377cfd802d6a33cb083f0d846b8 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy Date: Mon, 20 Oct 2025 16:07:31 +0200 -Subject: [PATCH 52/53] NIST curves hybrid KEX implementation +Subject: [PATCH 49/53] NIST curves hybrid KEX implementation --- crypto_api.h | 4 + - kex-names.c | 12 +- + kex-names.c | 78 +++- kex.c | 1 + kex.h | 19 + - kexgen.c | 54 +++ - kexmlkem768x25519.c | 598 +++++++++++++++++++++++++++++-- + kexgen.c | 56 ++- + kexmlkem768x25519.c | 678 +++++++++++++++++++++++++++++-- monitor.c | 2 + + myproposal.h | 4 + regress/unittests/kex/test_kex.c | 4 + ssh-keyscan.c | 2 + ssh_api.c | 4 + sshconnect2.c | 2 + sshd-auth.c | 2 + - 12 files changed, 681 insertions(+), 23 deletions(-) + 13 files changed, 819 insertions(+), 37 deletions(-) diff --git a/crypto_api.h b/crypto_api.h -index 8bbc3a08a..6940bbf0e 100644 +index 693b67bbc..ec3d2f277 100644 --- a/crypto_api.h +++ b/crypto_api.h -@@ -58,4 +58,8 @@ int crypto_kem_sntrup761_keypair(unsigned char *pk, unsigned char *sk); +@@ -56,4 +56,8 @@ int crypto_kem_sntrup761_keypair(unsigned char *pk, unsigned char *sk); #define crypto_kem_mlkem768_CIPHERTEXTBYTES 1088 #define crypto_kem_mlkem768_BYTES 32 @@ -32,47 +33,128 @@ index 8bbc3a08a..6940bbf0e 100644 + #endif /* crypto_api_h */ diff --git a/kex-names.c b/kex-names.c -index 36a953ab2..a728e0b38 100644 +index 9c96e5cb0..ceecd9312 100644 --- a/kex-names.c +++ b/kex-names.c -@@ -90,6 +90,10 @@ static const struct kexalg kexalgs[] = { +@@ -91,6 +91,10 @@ static const struct kexalg kexalgs[] = { #ifdef USE_MLKEM768X25519 { KEX_MLKEM768X25519_SHA256, KEX_KEM_MLKEM768X25519_SHA256, 0, - SSH_DIGEST_SHA256 }, + SSH_DIGEST_SHA256, KEX_IS_PQ }, + { KEX_MLKEM768NISTP256_SHA256, KEX_KEM_MLKEM768NISTP256_SHA256, 0, -+ SSH_DIGEST_SHA256 }, ++ SSH_DIGEST_SHA256, KEX_IS_PQ }, + { KEX_MLKEM1024NISTP384_SHA384, KEX_KEM_MLKEM1024NISTP384_SHA384, 0, -+ SSH_DIGEST_SHA384 }, ++ SSH_DIGEST_SHA384, KEX_IS_PQ }, #endif #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ - { NULL, 0, -1, -1}, -@@ -129,7 +133,9 @@ kex_alg_list_internal(char sep, const struct kexalg *algs) - const struct kexalg *k; + { NULL, 0, -1, -1, 0 }, +@@ -109,13 +113,30 @@ static const struct kexalg gss_kexalgs[] = { + { NULL, 0, -1, -1, 0}, + }; - for (k = algs; k->name != NULL; k++) { ++/* ++ * 0 - unavailable ++ * 1 - available in non-FIPS mode ++ * 2 - available in FIPS mode ++ */ + static int is_mlkem768_available() + { + static int is_fetched = -1; + + if (is_fetched == -1) { +- EVP_KEM *mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", NULL); +- is_fetched = mlkem768 != NULL ? 1 : 0; ++ EVP_KEM *mlkem768 = NULL; ++ ++ if (FIPS_mode() == 1) { ++ mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", NULL); ++ is_fetched = mlkem768 != NULL ? 2 : 0; ++ ++ if (is_fetched == 0) { ++ mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", "provider=default,-fips"); ++ is_fetched = mlkem768 != NULL ? 1 : 0; ++ } ++ } else { ++ mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", NULL); ++ is_fetched = mlkem768 != NULL ? 1 : 0; ++ } + EVP_KEM_free(mlkem768); + } + +@@ -128,11 +149,32 @@ kex_alg_list_internal(char sep, const struct kexalg *algs) + char *ret = NULL; + const struct kexalg *k; + char sep_str[2] = {sep, '\0'}; ++ int x25519mlkem_available = 0, nistmlkem_available = 0; + +- for (k = kexalgs; k->name != NULL; k++) { - if (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0 -+ if ( (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0 -+ || strcmp(k->name, KEX_MLKEM768NISTP256_SHA256) == 0 -+ || strcmp(k->name, KEX_MLKEM1024NISTP384_SHA384) == 0) - && !is_mlkem768_available()) +- && !is_mlkem768_available()) ++ /* ++ * FIPS provider can provide ML-KEMs and then all hybrids are available ++ * Otherwise only NIST hybrids are available ++ * */ ++ if (FIPS_mode()) { ++ if (is_mlkem768_available() == 2) { ++ x25519mlkem_available = 1; ++ nistmlkem_available = 1; ++ } else if (is_mlkem768_available() == 1) { ++ nistmlkem_available = 1; ++ } ++ } else { ++ if (is_mlkem768_available() > 0) { ++ x25519mlkem_available = 1; ++ nistmlkem_available = 1; ++ } ++ } ++ ++ for (k = algs; k->name != NULL; k++) { ++ if ( (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0 && x25519mlkem_available == 0) ++ || (strcmp(k->name, KEX_MLKEM768NISTP256_SHA256) == 0 && nistmlkem_available == 0) ++ || (strcmp(k->name, KEX_MLKEM1024NISTP384_SHA384) == 0 && nistmlkem_available == 0)) continue; - if (ret != NULL) -@@ -163,7 +169,9 @@ kex_alg_by_name(const char *name) ++ + xextendf(&ret, sep_str, "%s", k->name); + } + +@@ -155,10 +197,30 @@ static const struct kexalg * + kex_alg_by_name(const char *name) { const struct kexalg *k; ++ int x25519mlkem_available = 0, nistmlkem_available = 0; - if (strcmp(name, KEX_MLKEM768X25519_SHA256) == 0 -+ if ( (strcmp(name, KEX_MLKEM768X25519_SHA256) == 0 -+ || strcmp(name, KEX_MLKEM768NISTP256_SHA256) == 0 -+ || strcmp(name, KEX_MLKEM1024NISTP384_SHA384) == 0) - && !is_mlkem768_available()) - return NULL; +- && !is_mlkem768_available()) +- return NULL; ++ /* ++ * FIPS provider can provide ML-KEMs and then all hybrids are available ++ * Otherwise only NIST hybrids are available ++ * */ ++ if (FIPS_mode()) { ++ if (is_mlkem768_available() == 2) { ++ x25519mlkem_available = 1; ++ nistmlkem_available = 1; ++ } else if (is_mlkem768_available() == 1) { ++ nistmlkem_available = 1; ++ } ++ } else { ++ if (is_mlkem768_available() > 0) { ++ x25519mlkem_available = 1; ++ nistmlkem_available = 1; ++ } ++ } ++ ++ if ( (strcmp(name, KEX_MLKEM768X25519_SHA256) == 0 && x25519mlkem_available == 0) ++ || (strcmp(name, KEX_MLKEM768NISTP256_SHA256) == 0 && nistmlkem_available == 0) ++ || (strcmp(name, KEX_MLKEM1024NISTP384_SHA384) == 0 && nistmlkem_available == 0)) ++ return NULL; + for (k = kexalgs; k->name != NULL; k++) { + if (strcmp(k->name, name) == 0) diff --git a/kex.c b/kex.c -index ce6a7b818..efaf5749c 100644 +index 56c80395c..7dd16ba2b 100644 --- a/kex.c +++ b/kex.c -@@ -753,6 +753,7 @@ kex_free(struct kex *kex) +@@ -751,6 +751,7 @@ kex_free(struct kex *kex) #ifdef OPENSSL_HAS_ECC EC_KEY_free(kex->ec_client_key); #endif /* OPENSSL_HAS_ECC */ @@ -81,7 +163,7 @@ index ce6a7b818..efaf5749c 100644 for (mode = 0; mode < MODE_MAX; mode++) { kex_free_newkeys(kex->newkeys[mode]); diff --git a/kex.h b/kex.h -index 48f3bb875..50a461ddb 100644 +index 6daafb159..354f312e8 100644 --- a/kex.h +++ b/kex.h @@ -72,6 +72,8 @@ @@ -102,7 +184,7 @@ index 48f3bb875..50a461ddb 100644 #ifdef GSSAPI KEX_GSS_GRP1_SHA1, KEX_GSS_GRP14_SHA1, -@@ -206,6 +210,9 @@ struct kex { +@@ -210,6 +214,9 @@ struct kex { u_char sntrup761_client_key[crypto_kem_sntrup761_SECRETKEYBYTES]; /* KEM */ u_char mlkem768_client_key[crypto_kem_mlkem768_SECRETKEYBYTES]; /* KEM */ struct sshbuf *client_pub; @@ -112,7 +194,7 @@ index 48f3bb875..50a461ddb 100644 }; int kex_name_valid(const char *); -@@ -287,6 +294,18 @@ int kex_kem_mlkem768x25519_enc(struct kex *, const struct sshbuf *, +@@ -292,6 +299,18 @@ int kex_kem_mlkem768x25519_enc(struct kex *, const struct sshbuf *, int kex_kem_mlkem768x25519_dec(struct kex *, const struct sshbuf *, struct sshbuf **); @@ -132,58 +214,68 @@ index 48f3bb875..50a461ddb 100644 int kex_dh_compute_key(struct kex *, BIGNUM *, struct sshbuf *); diff --git a/kexgen.c b/kexgen.c -index eecdceba2..6e910f84f 100644 +index 9a970adf1..79faa0b3e 100644 --- a/kexgen.c +++ b/kexgen.c -@@ -139,6 +139,22 @@ kex_gen_client(struct ssh *ssh) +@@ -133,12 +133,24 @@ kex_gen_client(struct ssh *ssh) + break; + case KEX_KEM_MLKEM768X25519_SHA256: + if (FIPS_mode()) { +- logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); +- r = SSH_ERR_INVALID_ARGUMENT; ++ EVP_KEM *mlkem = EVP_KEM_fetch(NULL, "mlkem768", NULL); ++ if (mlkem == NULL) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ EVP_KEM_free(mlkem); ++ r = kex_kem_mlkem768x25519_keypair(kex); ++ } + } else { r = kex_kem_mlkem768x25519_keypair(kex); } break; + case KEX_KEM_MLKEM768NISTP256_SHA256: -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem768nistp256 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { + r = kex_kem_mlkem768nistp256_keypair(kex); -+ } + break; + case KEX_KEM_MLKEM1024NISTP384_SHA384: -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem1024nistp384 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { + r = kex_kem_mlkem1024nistp384_keypair(kex); -+ } + break; default: r = SSH_ERR_INVALID_ARGUMENT; break; -@@ -230,6 +246,24 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) +@@ -223,13 +235,28 @@ input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh) + break; + case KEX_KEM_MLKEM768X25519_SHA256: + if (FIPS_mode()) { +- logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); +- r = SSH_ERR_INVALID_ARGUMENT; ++ EVP_KEM *mlkem = EVP_KEM_fetch(NULL, "mlkem768", NULL); ++ if (mlkem == NULL) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ EVP_KEM_free(mlkem); ++ r = kex_kem_mlkem768x25519_dec(kex, server_blob, ++ &shared_secret); ++ } + } else { + r = kex_kem_mlkem768x25519_dec(kex, server_blob, &shared_secret); } break; + case KEX_KEM_MLKEM768NISTP256_SHA256: -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem768nistp256 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { + r = kex_kem_mlkem768nistp256_dec(kex, server_blob, + &shared_secret); -+ } + break; + case KEX_KEM_MLKEM1024NISTP384_SHA384: -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem1024nistp384 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { + r = kex_kem_mlkem1024nistp384_dec(kex, server_blob, + &shared_secret); -+ } + break; default: r = SSH_ERR_INVALID_ARGUMENT; break; -@@ -283,6 +317,8 @@ out: +@@ -283,6 +310,8 @@ out: sizeof(kex->sntrup761_client_key)); explicit_bzero(kex->mlkem768_client_key, sizeof(kex->mlkem768_client_key)); @@ -192,38 +284,54 @@ index eecdceba2..6e910f84f 100644 sshbuf_free(server_host_key_blob); free(signature); sshbuf_free(tmp); -@@ -369,6 +405,24 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) +@@ -362,13 +391,28 @@ input_kex_gen_init(int type, u_int32_t seq, struct ssh *ssh) + break; + case KEX_KEM_MLKEM768X25519_SHA256: + if (FIPS_mode()) { +- logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); +- r = SSH_ERR_INVALID_ARGUMENT; ++ EVP_KEM *mlkem = EVP_KEM_fetch(NULL, "mlkem768", NULL); ++ if (mlkem == NULL) { ++ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode"); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ } else { ++ EVP_KEM_free(mlkem); ++ r = kex_kem_mlkem768x25519_enc(kex, client_pubkey, ++ &server_pubkey, &shared_secret); ++ } + } else { + r = kex_kem_mlkem768x25519_enc(kex, client_pubkey, &server_pubkey, &shared_secret); } break; + case KEX_KEM_MLKEM768NISTP256_SHA256: -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem768nistp256 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { + r = kex_kem_mlkem768nistp256_enc(kex, client_pubkey, + &server_pubkey, &shared_secret); -+ } + break; + case KEX_KEM_MLKEM1024NISTP384_SHA384: -+ if (FIPS_mode()) { -+ logit_f("Key exchange type mlkem1024nistp384 is not allowed in FIPS mode"); -+ r = SSH_ERR_INVALID_ARGUMENT; -+ } else { + r = kex_kem_mlkem1024nistp384_enc(kex, client_pubkey, + &server_pubkey, &shared_secret); -+ } + break; default: r = SSH_ERR_INVALID_ARGUMENT; break; diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c -index 670049dcd..463d18771 100644 +index ab6167221..c56d67ff4 100644 --- a/kexmlkem768x25519.c +++ b/kexmlkem768x25519.c -@@ -53,14 +53,15 @@ +@@ -44,19 +44,33 @@ + #ifdef USE_MLKEM768X25519 + + #include "libcrux_mlkem768_sha3.h" ++#include ++#include + #include + #include ++#include #include ++#define FIPS_FALLBACK_PROPQ "provider=default,-fips" ++ static int -mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) +mlkem_keypair_gen(const char *algname, unsigned char *pubkeybuf, size_t pubkey_size, @@ -234,13 +342,21 @@ index 670049dcd..463d18771 100644 int ret = SSH_ERR_INTERNAL_ERROR; - size_t pubkey_size = crypto_kem_mlkem768_PUBLICKEYBYTES, privkey_size = crypto_kem_mlkem768_SECRETKEYBYTES; + size_t got_pub_size = pubkey_size, got_priv_size = privkey_size; ++ ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, algname, NULL); ++ ++ if (ctx == NULL && FIPS_mode()) { ++ /* We have filtered x25519 + ML-KEM in FIPS mode earlier ++ * so if we are in FIPS mode and ML-KEM is not available with default propq, ++ * we can fetch it from the default provider */ ++ ctx = EVP_PKEY_CTX_new_from_name(NULL, algname, FIPS_FALLBACK_PROPQ); ++ } - ctx = EVP_PKEY_CTX_new_from_name(NULL, "mlkem768", NULL); -+ ctx = EVP_PKEY_CTX_new_from_name(NULL, algname, NULL); if (ctx == NULL) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto err; -@@ -72,17 +73,23 @@ mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) +@@ -68,17 +82,23 @@ mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) goto err; } @@ -248,27 +364,27 @@ index 670049dcd..463d18771 100644 - || EVP_PKEY_get_raw_private_key(pkey, privkeybuf, &privkey_size) <= 0) { + if (EVP_PKEY_get_raw_public_key(pkey, NULL, &got_pub_size) <= 0 + || EVP_PKEY_get_raw_private_key(pkey, NULL, &got_priv_size) <= 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto err; -+ } -+ -+ if (privkey_size != got_priv_size || pubkey_size != got_pub_size) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto err; } - if (privkey_size != crypto_kem_mlkem768_SECRETKEYBYTES - || pubkey_size != crypto_kem_mlkem768_PUBLICKEYBYTES) { -+ if (EVP_PKEY_get_raw_public_key(pkey, pubkeybuf, &got_pub_size) <= 0 -+ || EVP_PKEY_get_raw_private_key(pkey, privkeybuf, &got_priv_size) <= 0) { ++ if (privkey_size != got_priv_size || pubkey_size != got_pub_size) { ret = SSH_ERR_LIBCRYPTO_ERROR; goto err; } ++ ++ if (EVP_PKEY_get_raw_public_key(pkey, pubkeybuf, &got_pub_size) <= 0 ++ || EVP_PKEY_get_raw_private_key(pkey, privkeybuf, &got_priv_size) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto err; ++ } + ret = 0; err: -@@ -94,16 +101,40 @@ mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) +@@ -90,27 +110,57 @@ mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf) } static int @@ -295,6 +411,7 @@ index 670049dcd..463d18771 100644 - size_t outlen = crypto_kem_mlkem768_CIPHERTEXTBYTES, - secretlen = crypto_kem_mlkem768_BYTES; + size_t outlen, expected_outlen, publen, secretlen = crypto_kem_mlkem768_BYTES; ++ int fips_fallback = 0; + + if (strcmp(mlkem_alg, "mlkem768") == 0) { + outlen = crypto_kem_mlkem768_CIPHERTEXTBYTES; @@ -311,11 +428,18 @@ index 670049dcd..463d18771 100644 + + pkey = EVP_PKEY_new_raw_public_key_ex(NULL, mlkem_alg, NULL, + pubkeybuf, publen); ++ if (pkey == NULL && FIPS_mode()) { ++ pkey = EVP_PKEY_new_raw_public_key_ex(NULL, mlkem_alg, FIPS_FALLBACK_PROPQ, ++ pubkeybuf, publen); ++ fips_fallback = 1; ++ } if (pkey == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto err; -@@ -112,9 +143,9 @@ mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) - ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + } + +- ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); ++ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, fips_fallback ? FIPS_FALLBACK_PROPQ : NULL); if (ctx == NULL || EVP_PKEY_encapsulate_init(ctx, NULL) <= 0 - || EVP_PKEY_encapsulate(ctx, out, &outlen, secret, &secretlen) <= 0 @@ -326,7 +450,7 @@ index 670049dcd..463d18771 100644 r = SSH_ERR_LIBCRYPTO_ERROR; goto err; } -@@ -130,16 +161,30 @@ mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) +@@ -126,25 +176,45 @@ mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out) } static int @@ -354,16 +478,24 @@ index 670049dcd..463d18771 100644 - size_t wrappedlen = crypto_kem_mlkem768_CIPHERTEXTBYTES, - secretlen = crypto_kem_mlkem768_BYTES; + size_t secretlen = crypto_kem_mlkem768_BYTES; ++ int fips_fallback = 0; - pkey = EVP_PKEY_new_raw_private_key_ex(NULL, "mlkem768", NULL, - privkeybuf, crypto_kem_mlkem768_SECRETKEYBYTES); + pkey = EVP_PKEY_new_raw_private_key_ex(NULL, algname, + NULL, privkeybuf, privkey_len); ++ if (pkey == NULL && FIPS_mode()) { ++ pkey = EVP_PKEY_new_raw_private_key_ex(NULL, algname, ++ FIPS_FALLBACK_PROPQ, privkeybuf, privkey_len); ++ fips_fallback = 1; ++ } if (pkey == NULL) { r = SSH_ERR_LIBCRYPTO_ERROR; goto err; -@@ -148,7 +193,7 @@ mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *s - ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); + } + +- ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL); ++ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, fips_fallback ? FIPS_FALLBACK_PROPQ : NULL); if (ctx == NULL || EVP_PKEY_decapsulate_init(ctx, NULL) <= 0 - || EVP_PKEY_decapsulate(ctx, secret, &secretlen, wrapped, wrappedlen) <= 0 @@ -371,7 +503,7 @@ index 670049dcd..463d18771 100644 || secretlen != crypto_kem_mlkem768_BYTES) { r = SSH_ERR_LIBCRYPTO_ERROR; goto err; -@@ -165,6 +210,20 @@ mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *s +@@ -161,6 +231,20 @@ mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *s return r; } @@ -392,7 +524,7 @@ index 670049dcd..463d18771 100644 int kex_kem_mlkem768x25519_keypair(struct kex *kex) { -@@ -341,7 +400,7 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, +@@ -337,7 +421,7 @@ kex_kem_mlkem768x25519_enc(struct kex *kex, u_char hash[SSH_DIGEST_MAX_LENGTH]; size_t need; int r = SSH_ERR_INTERNAL_ERROR; @@ -401,7 +533,7 @@ index 670049dcd..463d18771 100644 *server_blobp = NULL; *shared_secretp = NULL; -@@ -550,6 +609,468 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, +@@ -546,6 +630,519 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, return r; #endif } @@ -540,6 +672,48 @@ index 670049dcd..463d18771 100644 + return pkey; +} + ++static size_t decompress_pub_key(void *pub, size_t compressed_len, size_t decompressed_len) ++{ ++ EC_GROUP *group = NULL; ++ EC_POINT *point = NULL; ++ BN_CTX *ctx = NULL; ++ size_t len = 0; ++ int group_nid = NID_undef; ++ ++ switch (compressed_len) { ++ case NIST_P256_COMPRESSED_LEN: ++ group_nid = NID_X9_62_prime256v1; ++ break; ++ case NIST_P384_COMPRESSED_LEN: ++ group_nid = NID_secp384r1; ++ break; ++ default: ++ return 0; ++ break; ++ } ++ ++ ctx = BN_CTX_new(); ++ group = EC_GROUP_new_by_curve_name(group_nid); ++ if (ctx == NULL || group == NULL) ++ goto err; ++ ++ point = EC_POINT_new(group); ++ if (point == NULL) ++ goto err; ++ ++ if (!EC_POINT_oct2point(group, point, pub, compressed_len, ctx)) ++ goto err; ++ ++ len = EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, pub, decompressed_len, ctx); ++ ++err: ++ EC_POINT_free(point); ++ EC_GROUP_free(group); ++ BN_CTX_free(ctx); ++ ++ return len; ++} ++ +static int +get_uncompressed_ec_pubkey(EVP_PKEY *pkey, unsigned char *buf, size_t buf_len) +{ @@ -553,16 +727,25 @@ index 670049dcd..463d18771 100644 + + if (EVP_PKEY_set_params(pkey, params) <= 0 + || EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, -+ NULL, 0, &required_len) <= 0) { ++ buf, buf_len, &required_len) <= 0) { + return SSH_ERR_LIBCRYPTO_ERROR; + } + -+ if (required_len != buf_len) -+ return SSH_ERR_INTERNAL_ERROR; -+ -+ if (EVP_PKEY_get_octet_string_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, -+ buf, required_len, &out_len) <= 0) { -+ return SSH_ERR_LIBCRYPTO_ERROR; ++ if (required_len != buf_len) { ++ /* Red Hat certified FIPS provider ignores OSSL_PKEY_PARAM_EC_POINT_CONVERSION_FORMAT ++ * We may have to perform the conversion manually */ ++ if (len2curve_name(required_len) == len2curve_name(buf_len)) { ++ out_len = decompress_pub_key(buf, required_len, buf_len); ++ if (out_len != buf_len) { ++ debug_f("Error decompressing the compressed public key"); ++ return SSH_ERR_LIBCRYPTO_ERROR; ++ } else { ++ return 0; ++ } ++ } else { ++ debug_f("Unexpected length of uncompressed public key: expected %d, got %d", buf_len, required_len); ++ return SSH_ERR_LIBCRYPTO_ERROR; ++ } + } + + return 0; @@ -870,7 +1053,7 @@ index 670049dcd..463d18771 100644 #else /* USE_MLKEM768X25519 */ int kex_kem_mlkem768x25519_keypair(struct kex *kex) -@@ -571,4 +1092,39 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, +@@ -567,4 +1164,39 @@ kex_kem_mlkem768x25519_dec(struct kex *kex, { return SSH_ERR_SIGN_ALG_UNSUPPORTED; } @@ -911,10 +1094,10 @@ index 670049dcd..463d18771 100644 + #endif /* USE_MLKEM768X25519 */ diff --git a/monitor.c b/monitor.c -index 19cb058ee..4fe270e86 100644 +index 6c83739ee..2f154a3d7 100644 --- a/monitor.c +++ b/monitor.c -@@ -2009,6 +2009,8 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) +@@ -2014,6 +2014,8 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; @@ -923,11 +1106,33 @@ index 19cb058ee..4fe270e86 100644 kex->load_host_public_key=&get_hostkey_public_by_type; kex->load_host_private_key=&get_hostkey_private_by_type; kex->host_key_index=&get_hostkey_index; +diff --git a/myproposal.h b/myproposal.h +index 3e0ec6826..007347fc3 100644 +--- a/myproposal.h ++++ b/myproposal.h +@@ -26,6 +26,8 @@ + + #define KEX_SERVER_KEX \ + "mlkem768x25519-sha256," \ ++ "mlkem768nistp256-sha256," \ ++ "mlkem1024nistp384-sha384," \ + "sntrup761x25519-sha512," \ + "sntrup761x25519-sha512@openssh.com," \ + "curve25519-sha256," \ +@@ -97,6 +99,8 @@ + "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \ + "aes128-gcm@openssh.com,aes256-gcm@openssh.com" + #define KEX_DEFAULT_KEX_FIPS \ ++ "mlkem768nistp256-sha256," \ ++ "mlkem1024nistp384-sha384," \ + "ecdh-sha2-nistp256," \ + "ecdh-sha2-nistp384," \ + "ecdh-sha2-nistp521," \ diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c -index 09016aead..2baf9a7a0 100644 +index f4700deeb..99a8e3b46 100644 --- a/regress/unittests/kex/test_kex.c +++ b/regress/unittests/kex/test_kex.c -@@ -155,6 +155,8 @@ do_kex_with_key(char *kex, int keytype, int bits) +@@ -171,6 +171,8 @@ do_kex_with_key(char *kex, char *cipher, char *mac, server2->kex->kex[KEX_C25519_SHA256] = kex_gen_server; server2->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; server2->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; @@ -936,20 +1141,20 @@ index 09016aead..2baf9a7a0 100644 server2->kex->load_host_public_key = server->kex->load_host_public_key; server2->kex->load_host_private_key = server->kex->load_host_private_key; server2->kex->sign = server->kex->sign; -@@ -211,6 +213,8 @@ kex_tests(void) - do_kex("diffie-hellman-group1-sha1"); +@@ -248,6 +250,8 @@ kex_tests(void) + } # ifdef USE_MLKEM768X25519 do_kex("mlkem768x25519-sha256"); + do_kex("mlkem768nistp256-sha256"); + do_kex("mlkem1024nistp384-sha384"); # endif /* USE_MLKEM768X25519 */ # ifdef USE_SNTRUP761X25519 - do_kex("sntrup761x25519-sha512@openssh.com"); + do_kex("sntrup761x25519-sha512"); diff --git a/ssh-keyscan.c b/ssh-keyscan.c -index 9f76ad225..8660088b7 100644 +index 11618ae8a..2f4037972 100644 --- a/ssh-keyscan.c +++ b/ssh-keyscan.c -@@ -304,6 +304,8 @@ keygrab_ssh2(con *c) +@@ -290,6 +290,8 @@ keygrab_ssh2(con *c) c->c_ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; c->c_ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; c->c_ssh->kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_client; @@ -981,7 +1186,7 @@ index 7bdcee148..d20b03a00 100644 } *sshp = ssh; diff --git a/sshconnect2.c b/sshconnect2.c -index 5beae1c10..6d9f1238b 100644 +index 2d98fc3da..88e27955a 100644 --- a/sshconnect2.c +++ b/sshconnect2.c @@ -347,6 +347,8 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port, @@ -994,10 +1199,10 @@ index 5beae1c10..6d9f1238b 100644 #if defined(GSSAPI) && defined(WITH_OPENSSL) diff --git a/sshd-auth.c b/sshd-auth.c -index de61be5ac..6b5e20eef 100644 +index f3c38a7d1..698ef83f3 100644 --- a/sshd-auth.c +++ b/sshd-auth.c -@@ -914,6 +914,8 @@ do_ssh2_kex(struct ssh *ssh) +@@ -893,6 +893,8 @@ do_ssh2_kex(struct ssh *ssh) kex->kex[KEX_C25519_SHA256] = kex_gen_server; kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_server; kex->kex[KEX_KEM_MLKEM768X25519_SHA256] = kex_gen_server; diff --git a/0050-Provide-a-way-to-disable-GSSAPIDelegateCredentials-s.patch b/0050-Provide-a-way-to-disable-GSSAPIDelegateCredentials-s.patch new file mode 100644 index 0000000..85c4140 --- /dev/null +++ b/0050-Provide-a-way-to-disable-GSSAPIDelegateCredentials-s.patch @@ -0,0 +1,139 @@ +From 71190d3d862113d97708a42b4a7daa7aa3c4e0ec Mon Sep 17 00:00:00 2001 +From: Dmitry Belyavskiy +Date: Fri, 5 Dec 2025 14:55:38 +0100 +Subject: [PATCH 50/53] Provide a way to disable GSSAPIDelegateCredentials + server-side + +--- + gss-serv.c | 5 +++++ + servconf.c | 13 ++++++++++++- + servconf.h | 1 + + sshd_config.0 | 3 +++ + sshd_config.5 | 3 +++ + 5 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/gss-serv.c b/gss-serv.c +index be80e17ca..165484db0 100644 +--- a/gss-serv.c ++++ b/gss-serv.c +@@ -509,6 +509,11 @@ ssh_gssapi_cleanup_creds(void) + int + ssh_gssapi_storecreds(void) + { ++ if (options.gss_deleg_creds == 0) { ++ debug_f("delegate credential is disabled, doing nothing"); ++ return 0; ++ } ++ + if (gssapi_client.mech && gssapi_client.mech->storecreds) { + return (*gssapi_client.mech->storecreds)(&gssapi_client); + } else +diff --git a/servconf.c b/servconf.c +index e53e8ea30..fb1d150cd 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -143,6 +143,7 @@ initialize_server_options(ServerOptions *options) + options->gss_authentication=-1; + options->gss_keyex = -1; + options->gss_cleanup_creds = -1; ++ options->gss_deleg_creds = -1; + options->gss_strict_acceptor = -1; + options->gss_store_rekey = -1; + options->gss_kex_algorithms = NULL; +@@ -396,6 +397,8 @@ fill_default_server_options(ServerOptions *options) + options->gss_keyex = 0; + if (options->gss_cleanup_creds == -1) + options->gss_cleanup_creds = 1; ++ if (options->gss_deleg_creds == -1) ++ options->gss_deleg_creds = 1; + if (options->gss_strict_acceptor == -1) + options->gss_strict_acceptor = 1; + if (options->gss_store_rekey == -1) +@@ -591,7 +594,8 @@ typedef enum { + sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize, + sPerSourcePenalties, sPerSourcePenaltyExemptList, + sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, +- sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor, ++ sGssAuthentication, sGssCleanupCreds, sGssDelegateCreds, ++ sGssEnablek5users, sGssStrictAcceptor, + sGssKeyEx, sGssIndicators, sGssKexAlgorithms, sGssStoreRekey, + sAcceptEnv, sSetEnv, sPermitTunnel, + sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, +@@ -683,6 +687,7 @@ static struct { + { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, + { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, + { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapidelegatecredentials", sGssDelegateCreds, SSHCFG_GLOBAL }, + { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, +@@ -693,6 +698,7 @@ static struct { + { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, + { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, + { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapidelegatecredentials", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, +@@ -1705,6 +1711,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, + intptr = &options->gss_cleanup_creds; + goto parse_flag; + ++ case sGssDelegateCreds: ++ intptr = &options->gss_deleg_creds; ++ goto parse_flag; ++ + case sGssStrictAcceptor: + intptr = &options->gss_strict_acceptor; + goto parse_flag; +@@ -3352,6 +3362,7 @@ dump_config(ServerOptions *o) + #ifdef GSSAPI + dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); + dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); ++ dump_cfg_fmtint(sGssDelegateCreds, o->gss_deleg_creds); + dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); + dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); + dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); +diff --git a/servconf.h b/servconf.h +index c7cec5ece..9b1a73b8d 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -156,6 +156,7 @@ typedef struct { + int gss_authentication; /* If true, permit GSSAPI authentication */ + int gss_keyex; /* If true, permit GSSAPI key exchange */ + int gss_cleanup_creds; /* If true, destroy cred cache on logout */ ++ int gss_deleg_creds; /* If true, accept delegated GSS credentials */ + int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ + int gss_store_rekey; + char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */ +diff --git a/sshd_config.0 b/sshd_config.0 +index 8c5217c0b..cda9c9182 100644 +--- a/sshd_config.0 ++++ b/sshd_config.0 +@@ -453,6 +453,9 @@ DESCRIPTION + Specifies whether to automatically destroy the user's credentials + cache on logout. The default is yes. + ++ GSSAPIDelegateCredentials ++ Accept delegated credentials on the server side. The default is yes. ++ + GSSAPIStrictAcceptorCheck + Determines whether to be strict about the identity of the GSSAPI + acceptor a client authenticates against. If set to yes then the +diff --git a/sshd_config.5 b/sshd_config.5 +index 676d6d4d2..4ae4bebee 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -733,6 +733,9 @@ Specifies whether to automatically destroy the user's credentials cache + on logout. + The default is + .Cm yes . ++.It Cm GSSAPIDelegateCredentials ++Accept delegated credentials on the server side. The default is ++.CM yes . + .It Cm GSSAPIEnablek5users + Specifies whether to look at .k5users file for GSSAPI authentication + access control. Further details are described in +-- +2.52.0 + diff --git a/0023-openssh-7.3p1-x11-max-displays.patch b/0051-openssh-7.3p1-x11-max-displays.patch similarity index 82% rename from 0023-openssh-7.3p1-x11-max-displays.patch rename to 0051-openssh-7.3p1-x11-max-displays.patch index 09aa917..422107c 100644 --- a/0023-openssh-7.3p1-x11-max-displays.patch +++ b/0051-openssh-7.3p1-x11-max-displays.patch @@ -1,7 +1,7 @@ -From f727dd5c28358d7dcd132fca006a8cebce054d40 Mon Sep 17 00:00:00 2001 +From 763c65f6f349a7bab344a58991246891700e4fa0 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy -Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 23/53] openssh-7.3p1-x11-max-displays +Date: Fri, 12 Dec 2025 15:35:14 +0100 +Subject: [PATCH 51/53] openssh-7.3p1-x11-max-displays --- channels.c | 9 ++++++--- @@ -13,10 +13,10 @@ Subject: [PATCH 23/53] openssh-7.3p1-x11-max-displays 6 files changed, 30 insertions(+), 7 deletions(-) diff --git a/channels.c b/channels.c -index d46531ce0..7438c1a58 100644 +index 26ed9945f..c26380e25 100644 --- a/channels.c +++ b/channels.c -@@ -4996,7 +4996,7 @@ rdynamic_connect_finish(struct ssh *ssh, Channel *c) +@@ -5067,7 +5067,7 @@ rdynamic_connect_finish(struct ssh *ssh, Channel *c) */ int x11_create_display_inet(struct ssh *ssh, int x11_display_offset, @@ -25,7 +25,7 @@ index d46531ce0..7438c1a58 100644 u_int *display_numberp, int **chanids) { Channel *nc = NULL; -@@ -5009,8 +5009,11 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, +@@ -5080,8 +5080,11 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, x11_display_offset > UINT16_MAX - X11_BASE_PORT - MAX_DISPLAYS) return -1; @@ -33,25 +33,25 @@ index d46531ce0..7438c1a58 100644 + x11_max_displays = x11_max_displays + x11_display_offset; + for (display_number = x11_display_offset; -- display_number < MAX_DISPLAYS; +- display_number < x11_display_offset + MAX_DISPLAYS; + display_number < x11_max_displays; display_number++) { port = X11_BASE_PORT + display_number; memset(&hints, 0, sizeof(hints)); -@@ -5065,7 +5068,7 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, +@@ -5146,7 +5149,7 @@ x11_create_display_inet(struct ssh *ssh, int x11_display_offset, if (num_socks > 0) break; } -- if (display_number >= MAX_DISPLAYS) { +- if (display_number >= x11_display_offset + MAX_DISPLAYS) { + if (display_number >= x11_max_displays || port < X11_BASE_PORT ) { error("Failed to allocate internet-domain X11 display socket."); return -1; } diff --git a/channels.h b/channels.h -index 134528d59..8a09a8202 100644 +index 7456541f8..754bd98ee 100644 --- a/channels.h +++ b/channels.h -@@ -379,7 +379,7 @@ int permitopen_port(const char *); +@@ -389,7 +389,7 @@ int permitopen_port(const char *); void channel_set_x11_refuse_time(struct ssh *, time_t); int x11_connect_display(struct ssh *); @@ -61,10 +61,10 @@ index 134528d59..8a09a8202 100644 const char *, const char *, const char *, int); int x11_channel_used_recently(struct ssh *ssh); diff --git a/servconf.c b/servconf.c -index 105e301d9..15c99b303 100644 +index fb1d150cd..956205f6d 100644 --- a/servconf.c +++ b/servconf.c -@@ -117,6 +117,7 @@ initialize_server_options(ServerOptions *options) +@@ -118,6 +118,7 @@ initialize_server_options(ServerOptions *options) options->print_lastlog = -1; options->x11_forwarding = -1; options->x11_display_offset = -1; @@ -72,7 +72,7 @@ index 105e301d9..15c99b303 100644 options->x11_use_localhost = -1; options->permit_tty = -1; options->permit_user_rc = -1; -@@ -353,6 +354,8 @@ fill_default_server_options(ServerOptions *options) +@@ -357,6 +358,8 @@ fill_default_server_options(ServerOptions *options) options->x11_forwarding = 0; if (options->x11_display_offset == -1) options->x11_display_offset = 10; @@ -81,7 +81,7 @@ index 105e301d9..15c99b303 100644 if (options->x11_use_localhost == -1) options->x11_use_localhost = 1; if (options->xauth_location == NULL) -@@ -576,7 +579,7 @@ typedef enum { +@@ -582,7 +585,7 @@ typedef enum { sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, sPrintMotd, sPrintLastLog, sIgnoreRhosts, @@ -90,7 +90,7 @@ index 105e301d9..15c99b303 100644 sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive, sPermitUserEnvironment, sAllowTcpForwarding, sCompression, sRekeyLimit, sAllowUsers, sDenyUsers, sAllowGroups, sDenyGroups, -@@ -714,6 +717,7 @@ static struct { +@@ -725,6 +728,7 @@ static struct { { "ignoreuserknownhosts", sIgnoreUserKnownHosts, SSHCFG_GLOBAL }, { "x11forwarding", sX11Forwarding, SSHCFG_ALL }, { "x11displayoffset", sX11DisplayOffset, SSHCFG_ALL }, @@ -98,7 +98,7 @@ index 105e301d9..15c99b303 100644 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, -@@ -1750,6 +1754,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -1775,6 +1779,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, *intptr = value; break; @@ -109,7 +109,7 @@ index 105e301d9..15c99b303 100644 case sX11UseLocalhost: intptr = &options->x11_use_localhost; goto parse_flag; -@@ -3004,6 +3012,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) +@@ -3037,6 +3045,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) M_CP_INTOPT(fwd_opts.streamlocal_bind_unlink); M_CP_INTOPT(x11_display_offset); M_CP_INTOPT(x11_forwarding); @@ -117,7 +117,7 @@ index 105e301d9..15c99b303 100644 M_CP_INTOPT(x11_use_localhost); M_CP_INTOPT(permit_tty); M_CP_INTOPT(permit_user_rc); -@@ -3299,6 +3308,7 @@ dump_config(ServerOptions *o) +@@ -3332,6 +3341,7 @@ dump_config(ServerOptions *o) #endif dump_cfg_int(sLoginGraceTime, o->login_grace_time); dump_cfg_int(sX11DisplayOffset, o->x11_display_offset); @@ -126,7 +126,7 @@ index 105e301d9..15c99b303 100644 dump_cfg_int(sMaxSessions, o->max_sessions); dump_cfg_int(sClientAliveInterval, o->client_alive_interval); diff --git a/servconf.h b/servconf.h -index c08cf6a7a..7c7e5d434 100644 +index 9b1a73b8d..6bfdf6305 100644 --- a/servconf.h +++ b/servconf.h @@ -38,6 +38,7 @@ @@ -146,10 +146,10 @@ index c08cf6a7a..7c7e5d434 100644 char *xauth_location; /* Location of xauth program */ int permit_tty; /* If false, deny pty allocation */ diff --git a/session.c b/session.c -index dab771d3f..d7f05848e 100644 +index 80282dfd8..e53d044a0 100644 --- a/session.c +++ b/session.c -@@ -2609,8 +2609,9 @@ session_setup_x11fwd(struct ssh *ssh, Session *s) +@@ -2681,8 +2681,9 @@ session_setup_x11fwd(struct ssh *ssh, Session *s) return 0; } if (x11_create_display_inet(ssh, options.x11_display_offset, @@ -162,10 +162,10 @@ index dab771d3f..d7f05848e 100644 return 0; } diff --git a/sshd_config.5 b/sshd_config.5 -index fe246fc21..26fcdc840 100644 +index 4ae4bebee..3dbce55fc 100644 --- a/sshd_config.5 +++ b/sshd_config.5 -@@ -1391,6 +1391,7 @@ Available keywords are +@@ -1403,6 +1403,7 @@ Available keywords are .Cm TrustedUserCAKeys , .Cm UnusedConnectionTimeout , .Cm X11DisplayOffset , @@ -173,7 +173,7 @@ index fe246fc21..26fcdc840 100644 .Cm X11Forwarding and .Cm X11UseLocalhost . -@@ -2111,6 +2112,12 @@ Specifies the first display number available for +@@ -2112,6 +2113,12 @@ Specifies the first display number available for X11 forwarding. This prevents sshd from interfering with real X11 servers. The default is 10. diff --git a/0026-openssh-8.0p1-pkcs11-uri.patch b/0052-openssh-10.2p1-pkcs11-uri.patch similarity index 86% rename from 0026-openssh-8.0p1-pkcs11-uri.patch rename to 0052-openssh-10.2p1-pkcs11-uri.patch index 3a7a603..b486fee 100644 --- a/0026-openssh-8.0p1-pkcs11-uri.patch +++ b/0052-openssh-10.2p1-pkcs11-uri.patch @@ -1,45 +1,59 @@ -From 14abcc0887a8435549154137a43e68359f9d64eb Mon Sep 17 00:00:00 2001 +From f32f2a8a37e8585c1259fea2a970319d229e2cc7 Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy -Date: Thu, 15 May 2025 13:43:28 +0200 -Subject: [PATCH 26/53] openssh-8.0p1-pkcs11-uri +Date: Mon, 15 Dec 2025 14:24:07 +0100 +Subject: [PATCH 52/53] openssh-10.2p1-pkcs11-uri --- - Makefile.in | 20 +- + Makefile.in | 24 +- configure.ac | 37 ++ - regress/Makefile | 8 +- - regress/pkcs11.sh | 349 +++++++++++++++ + regress/Makefile | 4 +- + regress/pkcs11.sh | 349 ++++++++++++++ regress/unittests/Makefile | 2 +- - regress/unittests/pkcs11/tests.c | 346 ++++++++++++++ + regress/unittests/pkcs11/tests.c | 353 ++++++++++++++ ssh-add.c | 48 +- - ssh-agent.c | 103 ++++- + ssh-agent.c | 104 ++++- ssh-keygen.c | 7 +- - ssh-pkcs11-client.c | 3 + + ssh-pkcs11-client.c | 17 + ssh-pkcs11-uri.c | 437 ++++++++++++++++++ ssh-pkcs11-uri.h | 43 ++ - ssh-pkcs11.c | 745 +++++++++++++++++++++++-------- + ssh-pkcs11.c | 760 ++++++++++++++++++++++--------- ssh-pkcs11.h | 4 + ssh.c | 104 ++++- ssh_config.5 | 15 + - 16 files changed, 2024 insertions(+), 247 deletions(-) + 16 files changed, 2039 insertions(+), 269 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 78f659487..6c417ef7c 100644 +index 20d134c02..f8cbd545d 100644 --- a/Makefile.in +++ b/Makefile.in -@@ -110,7 +110,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 \ -@@ -339,6 +339,8 @@ clean: regressclean +@@ -112,7 +112,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ + sshbuf-io.o misc-agent.o auditstub.o + +-P11OBJS= ssh-pkcs11-client.o ++P11OBJS= ssh-pkcs11-client.o ssh-pkcs11-uri.o + + SKOBJS= ssh-sk-client.o + +@@ -161,11 +161,11 @@ SSHADD_OBJS= ssh-add.o $(P11OBJS) $(SKOBJS) + + SSHAGENT_OBJS= ssh-agent.o $(P11OBJS) $(SKOBJS) + +-SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o ssh-pkcs11.o $(SKOBJS) ++SSHKEYGEN_OBJS= ssh-keygen.o sshsig.o ssh-pkcs11.o ssh-pkcs11-uri.o $(SKOBJS) + + SSHKEYSIGN_OBJS=ssh-keysign.o readconf.o uidswap.o $(P11OBJS) $(SKOBJS) + +-P11HELPER_OBJS= ssh-pkcs11-helper.o ssh-pkcs11.o $(SKOBJS) ++P11HELPER_OBJS= ssh-pkcs11-helper.o ssh-pkcs11.o ssh-pkcs11-uri.o $(SKOBJS) + + SKHELPER_OBJS= ssh-sk-helper.o ssh-sk.o sk-usbhid.o + +@@ -331,6 +331,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) @@ -48,7 +62,7 @@ index 78f659487..6c417ef7c 100644 rm -f regress/misc/sk-dummy/*.o rm -f regress/misc/sk-dummy/*.lo rm -f regress/misc/ssh-verify-attestation/ssh-verify-attestation$(EXEEXT) -@@ -377,6 +379,8 @@ distclean: regressclean +@@ -369,6 +371,8 @@ distclean: regressclean rm -f regress/unittests/sshsig/test_sshsig rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8 @@ -57,7 +71,7 @@ index 78f659487..6c417ef7c 100644 rm -f regress/misc/sk-dummy/*.o rm -f regress/misc/sk-dummy/*.lo rm -f regress/misc/sk-dummy/sk-dummy.so -@@ -558,6 +562,7 @@ regress-prep: +@@ -549,6 +553,7 @@ regress-prep: $(MKDIR_P) `pwd`/regress/unittests/sshkey $(MKDIR_P) `pwd`/regress/unittests/sshsig $(MKDIR_P) `pwd`/regress/unittests/utf8 @@ -65,7 +79,7 @@ index 78f659487..6c417ef7c 100644 $(MKDIR_P) `pwd`/regress/misc/sk-dummy $(MKDIR_P) `pwd`/regress/misc/ssh-verify-attestation [ -f `pwd`/regress/Makefile ] || \ -@@ -731,6 +736,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \ +@@ -724,6 +729,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) @@ -73,16 +87,16 @@ index 78f659487..6c417ef7c 100644 + regress/unittests/pkcs11/tests.o + +regress/unittests/pkcs11/test_pkcs11$(EXEEXT): \ -+ ${UNITTESTS_TEST_PKCS11_OBJS} \ ++ ${UNITTESTS_TEST_PKCS11_OBJS} ssh-pkcs11-uri.o \ + 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) ++ ssh-pkcs11-uri.o -lssh -lopenbsd-compat -lcrypto $(LIBS) -lm + # These all need to be compiled -fPIC, so they are treated differently. SK_DUMMY_OBJS=\ regress/misc/sk-dummy/sk-dummy.lo \ -@@ -776,7 +791,8 @@ regress-unit-binaries: regress-prep $(REGRESSLIBS) \ +@@ -769,7 +784,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) \ @@ -93,10 +107,10 @@ index 78f659487..6c417ef7c 100644 tests: file-tests t-exec interop-tests extra-tests unit echo all tests passed diff --git a/configure.ac b/configure.ac -index 13c70a983..d9bd2f516 100644 +index 9d3b19925..e33462027 100644 --- a/configure.ac +++ b/configure.ac -@@ -2172,12 +2172,14 @@ AC_LINK_IFELSE( +@@ -2246,12 +2246,14 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) @@ -111,7 +125,7 @@ index 13c70a983..d9bd2f516 100644 fi ] ) -@@ -2207,6 +2209,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) +@@ -2281,6 +2283,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_FUNCS([dlopen]) AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) @@ -152,7 +166,7 @@ index 13c70a983..d9bd2f516 100644 # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5820,6 +5856,7 @@ echo " BSD Auth support: $BSD_AUTH_MSG" +@@ -5904,6 +5940,7 @@ echo " BSD Auth support: $BSD_AUTH_MSG" echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" echo " PKCS#11 support: $enable_pkcs11" @@ -161,10 +175,10 @@ index 13c70a983..d9bd2f516 100644 echo "" diff --git a/regress/Makefile b/regress/Makefile -index 7e7f95b58..f36de51e8 100644 +index ece093a2b..a851549f6 100644 --- a/regress/Makefile +++ b/regress/Makefile -@@ -137,7 +137,8 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ +@@ -139,7 +139,8 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ modpipe netcat no_identity_config \ pidfile putty.rsa2 ready regress.log remote_pid \ @@ -174,18 +188,14 @@ index 7e7f95b58..f36de51e8 100644 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 \ -@@ -297,8 +298,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 ; \ +@@ -288,6 +289,7 @@ unit unit-bench: + test "x${UNITTEST_VERBOSE}" = "x" || ARGS="$$ARGS -v"; \ + test "x${UNITTEST_BENCH_DETAIL}" = "x" || ARGS="$$ARGS -B"; \ + test "x${UNITTEST_BENCH_ONLY}" = "x" || ARGS="$$ARGS -O ${UNITTEST_BENCH_ONLY}"; \ ++ $$V ${.OBJDIR}/unittests/pkcs11/test_pkcs11 ; \ + $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf $${ARGS}; \ + $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ + -d ${.CURDIR}/unittests/sshkey/testdata $${ARGS}; \ diff --git a/regress/pkcs11.sh b/regress/pkcs11.sh new file mode 100644 index 000000000..a91aee94f @@ -555,10 +565,10 @@ index e370900e4..d6c89c129 100644 .include diff --git a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c new file mode 100644 -index 000000000..7d4fa4992 +index 000000000..89ba45c4e --- /dev/null +++ b/regress/unittests/pkcs11/tests.c -@@ -0,0 +1,346 @@ +@@ -0,0 +1,353 @@ +/* + * Copyright (c) 2017 Red Hat + * @@ -905,20 +915,27 @@ index 000000000..7d4fa4992 + test_parse_invalid(); + test_generate_valid(); +} ++ ++void ++benchmarks(void) ++{ ++ printf("no benchmarks\n"); ++} ++ diff --git a/ssh-add.c b/ssh-add.c -index 0035cb84a..b0f47f4de 100644 +index 2d5bec89c..aae82a794 100644 --- a/ssh-add.c +++ b/ssh-add.c -@@ -69,6 +69,7 @@ +@@ -70,6 +70,7 @@ #include "ssh-sk.h" #include "sk-api.h" #include "hostfile.h" +#include "ssh-pkcs11-uri.h" - /* argv0 */ - extern char *__progname; -@@ -242,6 +243,38 @@ delete_all(int agent_fd, int qflag) - return ret; + #define CERT_EXPIRY_GRACE (5*60) + +@@ -257,6 +258,38 @@ check_cert_lifetime(const struct sshkey *cert, int cert_lifetime) + return MINIMUM(cert_lifetime, (int)n); } +#ifdef ENABLE_PKCS11 @@ -955,8 +972,8 @@ index 0035cb84a..b0f47f4de 100644 + static int add_file(int agent_fd, const char *filename, int key_only, int cert_only, - int qflag, const char *skprovider, -@@ -462,15 +495,14 @@ static int + int qflag, int Nflag, const char *skprovider, +@@ -447,15 +480,14 @@ static int update_card(int agent_fd, int add, const char *id, int qflag, int key_only, int cert_only, struct dest_constraint **dest_constraints, size_t ndest_constraints, @@ -974,8 +991,8 @@ index 0035cb84a..b0f47f4de 100644 if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", RP_ALLOW_STDIN)) == NULL) return -1; -@@ -658,6 +690,14 @@ do_file(int agent_fd, int deleting, int key_only, int cert_only, - char *file, int qflag, const char *skprovider, +@@ -637,6 +669,14 @@ do_file(int agent_fd, int deleting, int key_only, int cert_only, + char *file, int qflag, int Nflag, const char *skprovider, struct dest_constraint **dest_constraints, size_t ndest_constraints) { +#ifdef ENABLE_PKCS11 @@ -989,20 +1006,20 @@ index 0035cb84a..b0f47f4de 100644 if (deleting) { if (delete_file(agent_fd, file, key_only, cert_only, qflag) == -1) -@@ -1001,7 +1041,7 @@ main(int argc, char **argv) +@@ -1009,7 +1049,7 @@ main(int argc, char **argv) if (update_card(agent_fd, !deleting, pkcs11provider, qflag, key_only, cert_only, dest_constraints, ndest_constraints, - certs, ncerts) == -1) + certs, ncerts, NULL) == -1) ret = 1; - goto done; - } + for (n = 0; n < ncerts; n++) + sshkey_free(certs[n]); diff --git a/ssh-agent.c b/ssh-agent.c -index c27c5a956..798bf9b60 100644 +index dc246066d..c3e94e2b1 100644 --- a/ssh-agent.c +++ b/ssh-agent.c -@@ -1569,10 +1569,74 @@ add_p11_identity(struct sshkey *key, char *comment, const char *provider, +@@ -1540,10 +1540,75 @@ add_p11_identity(struct sshkey *key, char *comment, const char *provider, idtab->nentries++; } @@ -1030,6 +1047,7 @@ index c27c5a956..798bf9b60 100644 + + if (pkcs11_uri_parse(provider, uri) != 0) { + error("Failed to parse PKCS#11 URI"); ++ pkcs11_uri_cleanup(uri); + return NULL; + } + /* validate also provider from URI */ @@ -1078,7 +1096,7 @@ index c27c5a956..798bf9b60 100644 char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds = 0; -@@ -1601,25 +1665,18 @@ process_add_smartcard_key(SocketEntry *e) +@@ -1572,25 +1637,18 @@ process_add_smartcard_key(SocketEntry *e) "providers is disabled", provider); goto send; } @@ -1109,7 +1127,7 @@ index c27c5a956..798bf9b60 100644 } for (j = 0; j < ncerts; j++) { if (!sshkey_is_cert(certs[j])) -@@ -1629,13 +1686,13 @@ process_add_smartcard_key(SocketEntry *e) +@@ -1600,13 +1658,13 @@ process_add_smartcard_key(SocketEntry *e) if (pkcs11_make_cert(keys[i], certs[j], &k) != 0) continue; add_p11_identity(k, xstrdup(comments[i]), @@ -1125,7 +1143,7 @@ index c27c5a956..798bf9b60 100644 dest_constraints, ndest_constraints); keys[i] = NULL; /* transferred */ comments[i] = NULL; /* transferred */ -@@ -1648,6 +1705,7 @@ process_add_smartcard_key(SocketEntry *e) +@@ -1619,6 +1677,7 @@ process_add_smartcard_key(SocketEntry *e) send: free(pin); free(provider); @@ -1133,7 +1151,7 @@ index c27c5a956..798bf9b60 100644 free(keys); free(comments); free_dest_constraints(dest_constraints, ndest_constraints); -@@ -1660,7 +1718,7 @@ send: +@@ -1631,7 +1690,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { @@ -1142,7 +1160,7 @@ index c27c5a956..798bf9b60 100644 int r, success = 0; Identity *id, *nxt; -@@ -1672,30 +1730,29 @@ process_remove_smartcard_key(SocketEntry *e) +@@ -1643,30 +1702,29 @@ process_remove_smartcard_key(SocketEntry *e) } free(pin); @@ -1180,10 +1198,10 @@ index c27c5a956..798bf9b60 100644 } #endif /* ENABLE_PKCS11 */ diff --git a/ssh-keygen.c b/ssh-keygen.c -index 89c3ed287..16cff9473 100644 +index afa279097..7af08fcdf 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c -@@ -906,8 +906,11 @@ do_download(struct passwd *pw) +@@ -831,8 +831,11 @@ do_download(struct passwd *pw) free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ @@ -1198,10 +1216,30 @@ index 89c3ed287..16cff9473 100644 free(comments[i]); sshkey_free(keys[i]); diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c -index b8d1700f0..64df695e1 100644 +index 85afb62ac..7b7eaf533 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c -@@ -635,6 +635,8 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, +@@ -378,6 +378,19 @@ pkcs11_start_helper(const char *path) + return helper; + } + ++int ++pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin, struct sshkey ***keyp, char ***labelsp) ++{ ++ int nkeys = 0; ++ char *provider_uri = pkcs11_uri_get(uri); ++ ++ debug_f("called, provider_uri = %s", provider_uri); ++ ++ nkeys = pkcs11_add_provider(provider_uri, pin, keyp, labelsp); ++ ++ return nkeys; ++} ++ + int + pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, + char ***labelsp) +@@ -389,6 +403,8 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, struct sshbuf *msg; struct helper *helper; @@ -1210,14 +1248,14 @@ index b8d1700f0..64df695e1 100644 if ((helper = helper_by_provider(name)) == NULL && (helper = pkcs11_start_helper(name)) == NULL) return -1; -@@ -655,6 +657,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, +@@ -413,6 +429,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 || + if ((r = sshkey_froms(msg, &k)) != 0 || diff --git a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c new file mode 100644 index 000000000..8bd97e9e2 @@ -1711,18 +1749,26 @@ index 000000000..29e9f7327 +char *pkcs11_uri_get(struct pkcs11_uri *uri); + diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c -index 31b9360f0..b96f5b890 100644 +index c88179473..1a443824d 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c -@@ -38,6 +38,7 @@ +@@ -39,6 +39,7 @@ #include #include #include +#include + #endif #define CRYPTOKI_COMPAT - #include "pkcs11.h" -@@ -55,8 +56,8 @@ struct pkcs11_slotinfo { +@@ -51,6 +52,7 @@ + #include "misc.h" + #include "sshbuf.h" + #include "ssh-pkcs11.h" ++#include "ssh-pkcs11-uri.h" + #include "digest.h" + #include "xmalloc.h" + #include "crypto_api.h" +@@ -61,8 +63,8 @@ struct pkcs11_slotinfo { int logged_in; }; @@ -1733,7 +1779,7 @@ index 31b9360f0..b96f5b890 100644 void *handle; CK_FUNCTION_LIST *function_list; CK_INFO info; -@@ -65,6 +66,13 @@ struct pkcs11_provider { +@@ -71,6 +73,13 @@ struct pkcs11_provider { struct pkcs11_slotinfo *slotinfo; int valid; int refcount; @@ -1747,15 +1793,15 @@ index 31b9360f0..b96f5b890 100644 TAILQ_ENTRY(pkcs11_provider) next; }; -@@ -75,6 +83,7 @@ struct pkcs11_key { +@@ -82,6 +91,7 @@ struct pkcs11_key { CK_ULONG slotidx; char *keyid; int keyid_len; + char *label; + TAILQ_ENTRY(pkcs11_key) next; }; - int pkcs11_interactive = 0; -@@ -106,26 +115,61 @@ pkcs11_init(int interactive) +@@ -108,26 +118,61 @@ ossl_error(const char *msg) * this is called when a provider gets unregistered. */ static void @@ -1828,7 +1874,7 @@ index 31b9360f0..b96f5b890 100644 } /* -@@ -137,11 +181,9 @@ pkcs11_provider_unref(struct pkcs11_provider *p) +@@ -139,15 +184,27 @@ pkcs11_provider_unref(struct pkcs11_provider *p) { debug_f("provider \"%s\" refcount %d", p->name, p->refcount); if (--p->refcount <= 0) { @@ -1842,9 +1888,6 @@ index 31b9360f0..b96f5b890 100644 free(p); } } -@@ -159,6 +201,20 @@ pkcs11_terminate(void) - } - } +/* lookup provider by module path */ +static struct pkcs11_module * @@ -1863,7 +1906,7 @@ index 31b9360f0..b96f5b890 100644 /* lookup provider by name */ static struct pkcs11_provider * pkcs11_provider_lookup(char *provider_id) -@@ -173,19 +229,55 @@ pkcs11_provider_lookup(char *provider_id) +@@ -162,19 +219,55 @@ pkcs11_provider_lookup(char *provider_id) return (NULL); } @@ -1921,10 +1964,113 @@ index 31b9360f0..b96f5b890 100644 + return rv; } - static RSA_METHOD *rsa_method; -@@ -195,6 +287,60 @@ static EC_KEY_METHOD *ec_key_method; - static int ec_key_idx = 0; - #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + /* release a wrapped object */ +@@ -186,6 +279,7 @@ pkcs11_k11_free(struct pkcs11_key *k11) + if (k11->provider) + pkcs11_provider_unref(k11->provider); + free(k11->keyid); ++ free(k11->label); + sshbuf_free(k11->keyblob); + free(k11); + } +@@ -201,8 +295,8 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, + CK_RV rv; + int ret = -1; + +- f = p->function_list; +- session = p->slotinfo[slotidx].session; ++ f = p->module->function_list; ++ session = p->module->slotinfo[slotidx].session; + if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { + error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); + return (-1); +@@ -239,14 +333,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, + if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) + verbose("Deferring PIN entry to reader keypad."); + else { +- snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", ++ snprintf(prompt, sizeof(prompt), "Enter PIN for '%.32s': ", + si->token.label); +- if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) { ++ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF|RP_ALLOW_STDIN)) == NULL) { + debug_f("no pin specified"); + return (-1); /* bail out */ + } + } +- rv = provider->function_list->C_Login(si->session, type, (u_char *)pin, ++ rv = provider->module->function_list->C_Login(si->session, type, (u_char *)pin, + (pin != NULL) ? strlen(pin) : 0); + if (pin != NULL) + freezero(pin, strlen(pin)); +@@ -276,13 +370,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, + static int + pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) + { +- if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) { ++ if (k11 == NULL || k11->provider == NULL || !k11->provider->valid || ++ k11->provider->module == NULL || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + + return pkcs11_login_slot(k11->provider, +- &k11->provider->slotinfo[k11->slotidx], type); ++ &k11->provider->module->slotinfo[k11->slotidx], type); + } + + +@@ -298,13 +393,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, + + *val = 0; + +- if (!k11->provider || !k11->provider->valid) { ++ if (!k11->provider || !k11->provider->valid || ++ !k11->provider->module || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + attr.type = type; + attr.pValue = &flag; +@@ -335,13 +431,14 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) + int always_auth = 0; + int did_login = 0; + +- if (!k11->provider || !k11->provider->valid) { ++ if (!k11->provider || !k11->provider->valid || ++ !k11->provider->module || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { + if (pkcs11_login(k11, CKU_USER) < 0) { +@@ -440,6 +537,12 @@ pkcs11_record_key(struct pkcs11_provider *provider, CK_ULONG slotidx, + k11->keyid = xmalloc(k11->keyid_len); + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + } ++ if (keyid_attrib->ulValueLen > 0 ) { ++ k11->label = xmalloc(keyid_attrib->ulValueLen+1); ++ memcpy(k11->label, keyid_attrib->pValue, keyid_attrib->ulValueLen); ++ k11->label[keyid_attrib->ulValueLen] = 0; ++ } ++ + TAILQ_INSERT_TAIL(&pkcs11_keys, k11, next); + + return 0; +@@ -467,6 +570,42 @@ pkcs11_lookup_key(struct sshkey *key) + return found; + } +/* + * This can't be in the ssh-pkcs11-uri, becase we can not depend on @@ -1935,26 +2081,8 @@ index 31b9360f0..b96f5b890 100644 +{ + char *p = NULL; + struct pkcs11_uri uri; -+ struct pkcs11_key *k11; ++ struct pkcs11_key *k11 = pkcs11_lookup_key(key); + -+ /* sanity - is it a RSA key with associated app_data? */ -+ switch (key->type) { -+ case KEY_RSA: { -+ const RSA *rsa = EVP_PKEY_get0_RSA(key->pkey); -+ k11 = RSA_get_ex_data(rsa, rsa_idx); -+ break; -+ } -+#ifdef HAVE_EC_KEY_METHOD_NEW -+ case KEY_ECDSA: { -+ const EC_KEY * ecdsa = EVP_PKEY_get0_EC_KEY(key->pkey); -+ k11 = EC_KEY_get_ex_data(ecdsa, ec_key_idx); -+ break; -+ } -+#endif -+ default: -+ error("Unknown key type %d", key->type); -+ return -1; -+ } + if (k11 == NULL) { + error("Failed to get ex_data for key type %d", key->type); + return (-1); @@ -1980,176 +2108,53 @@ index 31b9360f0..b96f5b890 100644 + return 0; +} + - /* release a wrapped object */ - static void - pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, -@@ -208,6 +354,7 @@ pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, - if (k11->provider) - pkcs11_provider_unref(k11->provider); - free(k11->keyid); -+ free(k11->label); - free(k11); + #ifdef WITH_OPENSSL + /* + * See: +@@ -571,8 +710,8 @@ pkcs11_sign_rsa(struct sshkey *key, + return SSH_ERR_AGENT_FAILURE; + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + if ((siglen = EVP_PKEY_size(key->pkey)) <= 0) + return SSH_ERR_INVALID_ARGUMENT; +@@ -661,8 +800,8 @@ pkcs11_sign_ecdsa(struct sshkey *key, + debug3_f("sign using provider %s slotidx %lu", + k11->provider->name, (u_long)k11->slotidx); + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + /* Prepare digest to be signed */ + if ((hashalg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) +@@ -746,8 +885,8 @@ pkcs11_sign_ed25519(struct sshkey *key, + debug3_f("sign using provider %s slotidx %lu", + k11->provider->name, (u_long)k11->slotidx); + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + xdata = xmalloc(datalen); + memcpy(xdata, data, datalen); +@@ -775,7 +914,8 @@ pkcs11_sign_ed25519(struct sshkey *key, + return ret; } -@@ -222,8 +369,8 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, - CK_RV rv; - int ret = -1; - -- f = p->function_list; -- session = p->slotinfo[slotidx].session; -+ f = p->module->function_list; -+ session = p->module->slotinfo[slotidx].session; - if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { - error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); - return (-1); -@@ -260,14 +407,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, - if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) - verbose("Deferring PIN entry to reader keypad."); - else { -- snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", -+ snprintf(prompt, sizeof(prompt), "Enter PIN for '%.32s': ", - si->token.label); -- if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) { -+ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF|RP_ALLOW_STDIN)) == NULL) { - debug_f("no pin specified"); - return (-1); /* bail out */ - } - } -- rv = provider->function_list->C_Login(si->session, type, (u_char *)pin, -+ rv = provider->module->function_list->C_Login(si->session, type, (u_char *)pin, - (pin != NULL) ? strlen(pin) : 0); - if (pin != NULL) - freezero(pin, strlen(pin)); -@@ -297,13 +444,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, - static int - pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) - { -- if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) { -+ if (k11 == NULL || k11->provider == NULL || !k11->provider->valid || -+ k11->provider->module == NULL || !k11->provider->module->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - - return pkcs11_login_slot(k11->provider, -- &k11->provider->slotinfo[k11->slotidx], type); -+ &k11->provider->module->slotinfo[k11->slotidx], type); - } - - -@@ -319,13 +467,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, - - *val = 0; - -- if (!k11->provider || !k11->provider->valid) { -+ if (!k11->provider || !k11->provider->valid || -+ !k11->provider->module || !k11->provider->module->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - attr.type = type; - attr.pValue = &flag; -@@ -356,13 +505,14 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) - int always_auth = 0; - int did_login = 0; - -- if (!k11->provider || !k11->provider->valid) { -+ if (!k11->provider || !k11->provider->valid || -+ !k11->provider->module || !k11->provider->module->valid) { - error("no pkcs11 (valid) provider found"); - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { - if (pkcs11_login(k11, CKU_USER) < 0) { -@@ -439,8 +589,8 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, - return (-1); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - tlen = RSA_size(rsa); - - /* XXX handle CKR_BUFFER_TOO_SMALL */ -@@ -484,7 +634,7 @@ pkcs11_rsa_start_wrapper(void) - /* redirect private key operations for rsa key to pkcs11 token */ - static int - pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, -- CK_ATTRIBUTE *keyid_attrib, RSA *rsa) -+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, RSA *rsa) - { - struct pkcs11_key *k11; - -@@ -502,6 +652,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - 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); -+ k11->label[label_attrib->ulValueLen] = 0; -+ } -+ - if (RSA_set_method(rsa, rsa_method) != 1) - fatal_f("RSA_set_method failed"); - if (RSA_set_ex_data(rsa, rsa_idx, k11) != 1) -@@ -534,8 +690,8 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, - return (NULL); - } - -- f = k11->provider->function_list; -- si = &k11->provider->slotinfo[k11->slotidx]; -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; - - siglen = ECDSA_size(ec); - sig = xmalloc(siglen); -@@ -600,7 +756,7 @@ pkcs11_ecdsa_start_wrapper(void) - - static int - pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, -- CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) -+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ec) - { - struct pkcs11_key *k11; - -@@ -617,6 +773,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - 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); -+ k11->label[label_attrib->ulValueLen] = 0; -+ } -+ - if (EC_KEY_set_method(ec, ec_key_method) != 1) - fatal_f("EC_KEY_set_method failed"); - if (EC_KEY_set_ex_data(ec, ec_key_idx, k11) != 1) -@@ -626,7 +788,8 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - } - #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ - -/* remove trailing spaces */ +/* remove trailing spaces. Note, that this does NOT guarantee the buffer + * will be null terminated if there are no trailing spaces! */ static char * rmspace(u_char *buf, size_t len) { -@@ -658,8 +821,8 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, +@@ -807,8 +947,8 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, CK_SESSION_HANDLE session; int login_required, ret; @@ -2160,7 +2165,7 @@ index 31b9360f0..b96f5b890 100644 login_required = si->token.flags & CKF_LOGIN_REQUIRED; -@@ -669,9 +832,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, +@@ -818,9 +958,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, error("pin required"); return (-SSH_PKCS11_ERR_PIN_REQUIRED); } @@ -2172,7 +2177,7 @@ index 31b9360f0..b96f5b890 100644 return (-1); } if (login_required && pin != NULL && strlen(pin) != 0) { -@@ -707,7 +870,8 @@ static struct sshkey * +@@ -857,7 +997,8 @@ static struct sshkey * pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -2182,7 +2187,7 @@ index 31b9360f0..b96f5b890 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -721,14 +885,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -870,14 +1011,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -2203,7 +2208,7 @@ index 31b9360f0..b96f5b890 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -739,19 +904,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -888,19 +1030,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -2227,7 +2232,7 @@ index 31b9360f0..b96f5b890 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -763,8 +928,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -912,8 +1054,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, goto fail; } @@ -2238,7 +2243,7 @@ index 31b9360f0..b96f5b890 100644 if (group == NULL) { ossl_error("d2i_ECPKParameters failed"); goto fail; -@@ -775,13 +940,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -924,13 +1066,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, goto fail; } @@ -2255,25 +2260,7 @@ index 31b9360f0..b96f5b890 100644 if (octet == NULL) { ossl_error("d2i_ASN1_OCTET_STRING failed"); goto fail; -@@ -798,7 +963,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto fail; - } - -- if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) -+ if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], ec)) - goto fail; - - key = sshkey_new(KEY_UNSPEC); -@@ -817,7 +982,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - key->flags |= SSHKEY_FLAG_EXT; - - fail: -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattr; i++) - free(key_attr[i].pValue); - if (ec) - EC_KEY_free(ec); -@@ -834,7 +999,8 @@ static struct sshkey * +@@ -992,7 +1134,8 @@ static struct sshkey * pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -2283,7 +2270,7 @@ index 31b9360f0..b96f5b890 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -845,14 +1011,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1003,14 +1146,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -2304,7 +2291,7 @@ index 31b9360f0..b96f5b890 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return (NULL); -@@ -863,19 +1030,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1021,19 +1165,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -2328,7 +2315,7 @@ index 31b9360f0..b96f5b890 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto fail; -@@ -887,8 +1054,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1045,8 +1189,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, goto fail; } @@ -2339,25 +2326,112 @@ index 31b9360f0..b96f5b890 100644 if (rsa_n == NULL || rsa_e == NULL) { error("BN_bin2bn failed"); goto fail; -@@ -897,7 +1064,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - fatal_f("set key"); - rsa_n = rsa_e = NULL; /* transferred */ - -- if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) -+ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], rsa)) - goto fail; - - key = sshkey_new(KEY_UNSPEC); -@@ -915,7 +1082,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - key->flags |= SSHKEY_FLAG_EXT; - +@@ -1078,7 +1222,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + /* success */ + success = 0; fail: - for (i = 0; i < 3; i++) + for (i = 0; i < nattr; i++) free(key_attr[i].pValue); RSA_free(rsa); + if (success != 0) { +@@ -1093,7 +1237,8 @@ static struct sshkey * + pkcs11_fetch_ed25519_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) + { +- CK_ATTRIBUTE key_attr[3]; ++ CK_ATTRIBUTE key_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -1113,14 +1258,15 @@ pkcs11_fetch_ed25519_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, -@@ -926,7 +1093,8 @@ static int + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; +- key_attr[1].type = CKA_EC_POINT; /* XXX or CKA_VALUE ? */ +- key_attr[2].type = CKA_EC_PARAMS; ++ key_attr[1].type = CKA_LABEL; ++ key_attr[2].type = CKA_EC_POINT; /* XXX or CKA_VALUE ? */ ++ key_attr[3].type = CKA_EC_PARAMS; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); +@@ -1131,28 +1277,28 @@ pkcs11_fetch_ed25519_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * ensure that none of the others are zero length. + * XXX assumes CKA_ID is always first. + */ +- if (key_attr[1].ulValueLen == 0 || +- key_attr[2].ulValueLen == 0) { ++ if (key_attr[2].ulValueLen == 0 || ++ key_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) { ++ for (i = 0; i < nattr; i++) { + if (key_attr[i].ulValueLen > 0) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + } + + /* retrieve ID, public point and curve parameters of EC key */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; + } + + /* Expect one of the supported identifiers in CKA_EC_PARAMS */ +- d = (u_char *)key_attr[2].pValue; +- len = key_attr[2].ulValueLen; ++ d = (u_char *)key_attr[3].pValue; ++ len = key_attr[3].ulValueLen; + if ((len != sizeof(id1) || memcmp(d, id1, sizeof(id1)) != 0) && + (len != sizeof(id2) || memcmp(d, id2, sizeof(id2)) != 0)) { + hex = tohex(d, len); +@@ -1164,16 +1310,16 @@ pkcs11_fetch_ed25519_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * Expect either a raw 32 byte pubkey or an OCTET STRING with + * a 32 byte pubkey in CKA_VALUE + */ +- d = (u_char *)key_attr[1].pValue; +- len = key_attr[1].ulValueLen; ++ d = (u_char *)key_attr[2].pValue; ++ len = key_attr[2].ulValueLen; + if (len == ED25519_PK_SZ + 2 && d[0] == 0x04 && d[1] == ED25519_PK_SZ) { + d += 2; + len -= 2; + } + if (len != ED25519_PK_SZ) { +- hex = tohex(key_attr[1].pValue, key_attr[1].ulValueLen); ++ hex = tohex(key_attr[2].pValue, key_attr[2].ulValueLen); + logit_f("CKA_EC_POINT invalid octet str: %s (len %lu)", +- hex, (u_long)key_attr[1].ulValueLen); ++ hex, (u_long)key_attr[2].ulValueLen); + goto fail; + } + +@@ -1193,7 +1339,7 @@ pkcs11_fetch_ed25519_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + key = NULL; + } + free(hex); +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(key_attr[i].pValue); + return key; + } +@@ -1203,7 +1349,8 @@ static int pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { @@ -2367,7 +2441,7 @@ index 31b9360f0..b96f5b890 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -950,14 +1118,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1229,14 +1376,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, memset(&cert_attr, 0, sizeof(cert_attr)); cert_attr[0].type = CKA_ID; @@ -2388,7 +2462,7 @@ index 31b9360f0..b96f5b890 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); return -1; -@@ -969,18 +1138,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1248,18 +1396,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, * XXX assumes CKA_ID is always first. */ if (cert_attr[1].ulValueLen == 0 || @@ -2411,7 +2485,7 @@ index 31b9360f0..b96f5b890 100644 if (rv != CKR_OK) { error("C_GetAttributeValue failed: %lu", rv); goto out; -@@ -994,8 +1164,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1273,8 +1422,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, subject = xstrdup("invalid subject"); X509_NAME_free(x509_name); @@ -2422,25 +2496,7 @@ index 31b9360f0..b96f5b890 100644 error("d2i_x509 failed"); goto out; } -@@ -1015,7 +1185,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto out; - } - -- if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) -+ if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], rsa)) - goto out; - - key = sshkey_new(KEY_UNSPEC); -@@ -1048,7 +1218,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, - goto out; - } - -- if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) -+ if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], ec)) - goto out; - - key = sshkey_new(KEY_UNSPEC); -@@ -1071,7 +1241,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1384,7 +1533,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, goto out; } out: @@ -2449,7 +2505,7 @@ index 31b9360f0..b96f5b890 100644 free(cert_attr[i].pValue); X509_free(x509); RSA_free(rsa); -@@ -1122,11 +1292,12 @@ note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, +@@ -1427,11 +1576,12 @@ note_key(struct pkcs11_provider *p, CK_ULONG slotidx, const char *context, */ static int pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2464,7 +2520,7 @@ index 31b9360f0..b96f5b890 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1143,10 +1314,23 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1448,10 +1598,23 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2482,16 +2538,16 @@ index 31b9360f0..b96f5b890 100644 + key_attr[nattr].ulValueLen = strlen(uri->object); + nattr++; + } -+ -+ session = p->module->slotinfo[slotidx].session; -+ f = p->module->function_list; - 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, nattr); if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1227,11 +1411,12 @@ fail: +@@ -1533,11 +1696,12 @@ fail: */ static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2506,7 +2562,7 @@ index 31b9360f0..b96f5b890 100644 CK_SESSION_HANDLE session; CK_FUNCTION_LIST *f = NULL; CK_RV rv; -@@ -1247,10 +1432,23 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1553,10 +1717,23 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2533,7 +2589,7 @@ index 31b9360f0..b96f5b890 100644 if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); goto fail; -@@ -1532,16 +1730,10 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, +@@ -1844,16 +2021,10 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, } #endif /* WITH_PKCS11_KEYGEN */ @@ -2552,7 +2608,7 @@ index 31b9360f0..b96f5b890 100644 int ret = -1; struct pkcs11_provider *p = NULL; void *handle = NULL; -@@ -1550,162 +1742,309 @@ pkcs11_register_provider(char *provider_id, char *pin, +@@ -1862,128 +2033,126 @@ pkcs11_register_provider(char *provider_id, char *pin, CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; @@ -2643,13 +2699,6 @@ index 31b9360f0..b96f5b890 100644 error("C_GetInfo for provider %s failed: %lu", - provider_id, rv); + provider_module, rv); -+ goto fail; -+ } -+ rmspace(m->info.manufacturerID, sizeof(m->info.manufacturerID)); -+ if (uri->lib_manuf != NULL && -+ strncmp(uri->lib_manuf, m->info.manufacturerID, 32)) { -+ debug_f("Skipping provider %s not matching library_manufacturer", -+ m->info.manufacturerID); goto fail; } - debug("provider %s: manufacturerID <%.*s> cryptokiVersion %d.%d" @@ -2662,6 +2711,13 @@ index 31b9360f0..b96f5b890 100644 - p->info.libraryVersion.major, - p->info.libraryVersion.minor); - if ((rv = f->C_GetSlotList(CK_TRUE, NULL, &p->nslots)) != CKR_OK) { ++ rmspace(m->info.manufacturerID, sizeof(m->info.manufacturerID)); ++ if (uri->lib_manuf != NULL && ++ strncmp(uri->lib_manuf, m->info.manufacturerID, 32)) { ++ debug_f("Skipping provider %s not matching library_manufacturer", ++ m->info.manufacturerID); ++ goto fail; ++ } + rmspace(m->info.libraryDescription, sizeof(m->info.libraryDescription)); + debug("provider %s: manufacturerID <%.32s> cryptokiVersion %d.%d" + " libraryDescription <%.32s> libraryVersion %d.%d", @@ -2714,7 +2770,6 @@ index 31b9360f0..b96f5b890 100644 - debug2_f("ignoring uninitialised token in " - "provider %s slot %lu", provider_id, (u_long)i); + "failed: %lu", provider_module, (u_long)i, rv); -+ token->flags = 0; continue; } debug("provider %s slot %lu: label <%.*s> " @@ -2725,39 +2780,77 @@ index 31b9360f0..b96f5b890 100644 RMSPACE(token->label), RMSPACE(token->manufacturerID), RMSPACE(token->model), RMSPACE(token->serialNumber), token->flags); -+ } +- /* +- * open session, login with pin and retrieve public +- * keys (if keyp is provided) +- */ +- if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || +- keyp == NULL) +- continue; +- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +-#ifdef WITH_OPENSSL +- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); +-#endif +- if (nkeys == 0 && !p->slotinfo[i].logged_in && +- pkcs11_interactive) { +- /* +- * Some tokens require login before they will +- * expose keys. +- */ +- if (pkcs11_login_slot(p, &p->slotinfo[i], +- CKU_USER) < 0) { +- error("login failed"); +- continue; +- } +- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +-#ifdef WITH_OPENSSL +- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); +-#endif +- } + } + m->module_path = provider_module; + provider_module = NULL; -+ -+ /* now owned by caller */ -+ *providerp = p; -+ -+ TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -+ p->refcount++; /* add to provider list */ -+ + + /* now owned by caller */ + *providerp = p; +@@ -1991,21 +2160,22 @@ pkcs11_register_provider(char *provider_id, char *pin, + TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); + p->refcount++; /* add to provider list */ + +- return (nkeys); + return 0; -+fail: -+ if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) -+ error("C_Finalize for provider %s failed: %lu", + fail: + if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) + error("C_Finalize for provider %s failed: %lu", +- provider_id, rv); + provider_module, rv); + free(provider_module); + if (m) { + free(m->slotlist); + free(m); + } -+ if (p) { -+ free(p->name); -+ free(p); -+ } -+ if (handle) -+ dlclose(handle); -+ return (ret); -+} -+ -+/* + if (p) { + free(p->name); +- free(p->slotlist); +- free(p->slotinfo); + free(p); + } + if (handle) + dlclose(handle); +- if (ret > 0) +- ret = -1; + return (ret); + } + +@@ -2041,18 +2211,161 @@ pkcs11_terminate(void) + } + + /* +- * register a new provider and get number of keys hold by the token, +- * fails if provider already exists + * register a new provider, fails if provider already exists. if + * keyp is provided, fetch keys. -+ */ + */ +static int +pkcs11_register_provider_by_uri(struct pkcs11_uri *uri, char *pin, + struct sshkey ***keyp, char ***labelsp, struct pkcs11_provider **providerp, @@ -2819,37 +2912,28 @@ index 31b9360f0..b96f5b890 100644 + provider_uri, (unsigned long)i, + token->label, token->manufacturerID, token->model, + token->serialNumber, token->flags); - /* -- * open session, login with pin and retrieve public -- * keys (if keyp is provided) ++ /* + * open session if not yet opened, login with pin and + * retrieve public keys (if keyp is provided) - */ -- if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || ++ */ + if ((p->module->slotinfo[i].session != 0 || + (ret = pkcs11_open_session(p, i, pin, user)) != 0) && /* ??? */ - keyp == NULL) - continue; -- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); -- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); -- if (nkeys == 0 && !p->slotinfo[i].logged_in && ++ keyp == NULL) ++ continue; + pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); + pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); + if (nkeys == 0 && !p->module->slotinfo[i].logged_in && - pkcs11_interactive) { - /* - * Some tokens require login before they will - * expose keys. - */ -- if (pkcs11_login_slot(p, &p->slotinfo[i], ++ pkcs11_interactive) { ++ /* ++ * Some tokens require login before they will ++ * expose keys. ++ */ + debug3_f("Trying to login as there were no keys found"); + if (pkcs11_login_slot(p, &p->module->slotinfo[i], - CKU_USER) < 0) { - error("login failed"); - continue; - } -- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); -- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); ++ CKU_USER) < 0) { ++ error("login failed"); ++ continue; ++ } + pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); + pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); + } @@ -2862,41 +2946,25 @@ index 31b9360f0..b96f5b890 100644 + pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); + pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); + uri->object = label; - } - } ++ } ++ } + pin = NULL; /* Will be cleaned up with URI */ - - /* now owned by caller */ - *providerp = p; - -- TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -- p->refcount++; /* add to provider list */ -- ++ ++ /* now owned by caller */ ++ *providerp = p; ++ + free(provider_uri); - return (nkeys); - fail: -- if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) -- error("C_Finalize for provider %s failed: %lu", -- provider_id, rv); - if (p) { -- free(p->name); -- free(p->slotlist); -- free(p->slotinfo); -- free(p); ++ return (nkeys); ++ fail: ++ if (p) { + TAILQ_REMOVE(&pkcs11_providers, p, next); -+ pkcs11_provider_unref(p); - } -- if (handle) -- dlclose(handle); - if (ret > 0) - ret = -1; - return (ret); - } - --/* -- * register a new provider and get number of keys hold by the token, -- * fails if provider already exists -- */ ++ pkcs11_provider_unref(p); ++ } ++ if (ret > 0) ++ ret = -1; ++ return (ret); ++} ++ +static int +pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, + char ***labelsp, struct pkcs11_provider **providerp, CK_ULONG user) @@ -2942,21 +3010,17 @@ index 31b9360f0..b96f5b890 100644 /* no keys found or some other error, de-register provider */ if (nkeys <= 0 && p != NULL) { -@@ -1714,7 +2053,37 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, +@@ -2061,11 +2374,38 @@ 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); -+ + + free(provider_uri); -+ return nkeys; -+} -+ -+/* -+ * register a new provider and get number of keys hold by the token, -+ * fails if provider already exists -+ */ + return (nkeys); + } + +int +pkcs11_add_provider(char *provider_id, char *pin, + struct sshkey ***keyp, char ***labelsp) @@ -2978,33 +3042,40 @@ index 31b9360f0..b96f5b890 100644 + + nkeys = pkcs11_add_provider_by_uri(uri, pin, keyp, labelsp); + pkcs11_uri_cleanup(uri); - - return (nkeys); - } ++ ++ return (nkeys); ++} ++ ++ + int + pkcs11_sign(struct sshkey *key, + u_char **sigp, size_t *lenp, diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h -index 526022319..9ce20c1f9 100644 +index d86c506c1..32f2d0ccf 100644 --- a/ssh-pkcs11.h +++ b/ssh-pkcs11.h -@@ -22,10 +22,14 @@ +@@ -22,12 +22,16 @@ #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 +#include "ssh-pkcs11-uri.h" + + struct sshkey; + 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, + int pkcs11_sign(struct sshkey *, u_char **, size_t *, + const u_char *, size_t, const char *, const char *, + const char *, u_int); diff --git a/ssh.c b/ssh.c -index c23d3b9e3..98b103c9e 100644 +index 320ac6834..14965a4f1 100644 --- a/ssh.c +++ b/ssh.c -@@ -890,6 +890,14 @@ main(int ac, char **av) +@@ -904,6 +904,14 @@ main(int ac, char **av) options.gss_deleg_creds = 1; break; case 'i': @@ -3019,15 +3090,15 @@ index c23d3b9e3..98b103c9e 100644 p = tilde_expand_filename(optarg, getuid()); if (stat(p, &st) == -1) fprintf(stderr, "Warning: Identity file %s " -@@ -1847,6 +1855,7 @@ main(int ac, char **av) +@@ -1872,6 +1880,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); -@@ -2370,6 +2379,45 @@ ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) + if (addrs != NULL) +@@ -2387,6 +2396,45 @@ ssh_session2(struct ssh *ssh, const struct ssh_conn_info *cinfo) options.escape_char : SSH_ESCAPECHAR_NONE, id); } @@ -3073,7 +3144,7 @@ index c23d3b9e3..98b103c9e 100644 /* Loads all IdentityFile and CertificateFile keys */ static void load_public_identity_files(const struct ssh_conn_info *cinfo) -@@ -2384,11 +2432,6 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) +@@ -2401,11 +2449,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]; @@ -3085,7 +3156,7 @@ index c23d3b9e3..98b103c9e 100644 n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); -@@ -2401,33 +2444,46 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) +@@ -2418,33 +2461,46 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 @@ -3152,10 +3223,10 @@ index c23d3b9e3..98b103c9e 100644 free(cp); check_load(sshkey_load_public(filename, &public, NULL), diff --git a/ssh_config.5 b/ssh_config.5 -index 3a8e246c4..8d5d07222 100644 +index a06fbfa11..717b0938a 100644 --- a/ssh_config.5 +++ b/ssh_config.5 -@@ -1263,6 +1263,21 @@ may also be used in conjunction with +@@ -1260,6 +1260,21 @@ may also be used in conjunction with .Cm CertificateFile in order to provide any certificate also needed for authentication with the identity. diff --git a/1000-openssh-6.7p1-coverity.patch b/1000-openssh-6.7p1-coverity.patch index 0cf2c69..40c298e 100644 --- a/1000-openssh-6.7p1-coverity.patch +++ b/1000-openssh-6.7p1-coverity.patch @@ -1,6 +1,6 @@ -From 194961cdbf4f212f9a845dfbf9b02ccbbb67f151 Mon Sep 17 00:00:00 2001 +From aecc5861e1cf7094a32f893ae4bfd8409b77e5cd Mon Sep 17 00:00:00 2001 From: Dmitry Belyavskiy -Date: Thu, 15 May 2025 13:43:29 +0200 +Date: Fri, 12 Dec 2025 14:25:41 +0100 Subject: [PATCH 53/53] openssh-6.7p1-coverity --- @@ -15,12 +15,10 @@ Subject: [PATCH 53/53] openssh-6.7p1-coverity readconf.c | 1 + servconf.c | 5 +++-- serverloop.c | 2 +- - ssh-agent.c | 1 + - ssh-keygen.c | 3 +++ - 13 files changed, 28 insertions(+), 11 deletions(-) + 11 files changed, 24 insertions(+), 11 deletions(-) diff --git a/auth-krb5.c b/auth-krb5.c -index bae153c93..209a32655 100644 +index b9c261a24..a37be93c3 100644 --- a/auth-krb5.c +++ b/auth-krb5.c @@ -427,6 +427,7 @@ ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environm @@ -40,10 +38,10 @@ index bae153c93..209a32655 100644 } /* make sure the KRB5CCNAME is set for non-standard location */ diff --git a/gss-genr.c b/gss-genr.c -index 3034370c7..c357e973a 100644 +index f2d6f59e5..91602e045 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, +@@ -178,8 +178,9 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, enclen = __b64_ntop(digest, ssh_digest_bytes(SSH_DIGEST_MD5), encoded, ssh_digest_bytes(SSH_DIGEST_MD5) * 2); @@ -55,10 +53,10 @@ index 3034370c7..c357e973a 100644 (p = strsep(&cp, ","))) { if (sshbuf_len(buf) != 0 && diff --git a/krl.c b/krl.c -index 0d0f69534..d8517f124 100644 +index bea5b1b98..4dd8a24a9 100644 --- a/krl.c +++ b/krl.c -@@ -1202,6 +1202,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) +@@ -1205,6 +1205,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb); free(rb.blob); @@ -66,7 +64,7 @@ index 0d0f69534..d8517f124 100644 if (erb != NULL) { KRL_DBG(("revoked by key SHA1")); return SSH_ERR_KEY_REVOKED; -@@ -1212,6 +1213,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) +@@ -1215,6 +1216,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha256s, &rb); free(rb.blob); @@ -74,7 +72,7 @@ index 0d0f69534..d8517f124 100644 if (erb != NULL) { KRL_DBG(("revoked by key SHA256")); return SSH_ERR_KEY_REVOKED; -@@ -1223,6 +1225,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) +@@ -1226,6 +1228,7 @@ is_key_revoked(struct ssh_krl *krl, const struct sshkey *key) return r; erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); free(rb.blob); @@ -83,10 +81,10 @@ index 0d0f69534..d8517f124 100644 KRL_DBG(("revoked by explicit key")); return SSH_ERR_KEY_REVOKED; diff --git a/loginrec.c b/loginrec.c -index c4a9bd485..2583612c6 100644 +index 7d1c9dd43..a017e173b 100644 --- a/loginrec.c +++ b/loginrec.c -@@ -683,9 +683,11 @@ construct_utmp(struct logininfo *li, +@@ -677,9 +677,11 @@ construct_utmp(struct logininfo *li, */ /* Use strncpy because we don't necessarily want null termination */ @@ -99,10 +97,10 @@ index c4a9bd485..2583612c6 100644 MIN_SIZEOF(ut->ut_host, li->hostname)); # endif diff --git a/misc.c b/misc.c -index 097229620..cd71c1b2b 100644 +index 2fd14159d..d4c4e4164 100644 --- a/misc.c +++ b/misc.c -@@ -1556,6 +1556,8 @@ sanitise_stdfd(void) +@@ -1573,6 +1573,8 @@ sanitise_stdfd(void) } if (nullfd > STDERR_FILENO) close(nullfd); @@ -111,7 +109,7 @@ index 097229620..cd71c1b2b 100644 } char * -@@ -2749,6 +2751,7 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) +@@ -2773,6 +2775,7 @@ stdfd_devnull(int do_stdin, int do_stdout, int do_stderr) } if (devnull > STDERR_FILENO) close(devnull); @@ -120,10 +118,10 @@ index 097229620..cd71c1b2b 100644 } diff --git a/monitor.c b/monitor.c -index 4fe270e86..75413ce71 100644 +index 2f154a3d7..f959e0124 100644 --- a/monitor.c +++ b/monitor.c -@@ -415,7 +415,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) +@@ -405,7 +405,7 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) mm_get_keystate(ssh, pmonitor); /* Drain any buffered messages from the child */ @@ -131,8 +129,8 @@ index 4fe270e86..75413ce71 100644 + while (pmonitor->m_log_recvfd >= 0 && monitor_read_log(pmonitor) == 0) ; - if (pmonitor->m_recvfd >= 0) -@@ -1813,7 +1813,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) + /* Wait for the child's exit status */ +@@ -1819,7 +1819,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m) s->ptymaster = s->ptyfd; debug3_f("tty %s ptyfd %d", s->tty, s->ttyfd); @@ -186,10 +184,10 @@ index 26bdc3e08..8e2939b95 100644 FD_CLR(notify_pipe[0], readset); } diff --git a/readconf.c b/readconf.c -index ea9d293c3..9680c38c8 100644 +index b6ad47b49..75e1c953c 100644 --- a/readconf.c +++ b/readconf.c -@@ -2164,6 +2164,7 @@ parse_pubkey_algos: +@@ -2170,6 +2170,7 @@ parse_pubkey_algos: } else if (r != 0) { error("%.200s line %d: glob failed for %s.", filename, linenum, arg2); @@ -198,10 +196,10 @@ index ea9d293c3..9680c38c8 100644 } free(arg2); diff --git a/servconf.c b/servconf.c -index ecf5c66d4..aab653244 100644 +index 956205f6d..1093dcbac 100644 --- a/servconf.c +++ b/servconf.c -@@ -2305,8 +2305,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, +@@ -2307,8 +2307,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, if (*activep && *charptr == NULL) { *charptr = tilde_expand_filename(arg, getuid()); /* increase optional counter */ @@ -214,10 +212,10 @@ index ecf5c66d4..aab653244 100644 break; diff --git a/serverloop.c b/serverloop.c -index 9c5b15678..768ee9fa4 100644 +index 55411a6b4..acc721cd1 100644 --- a/serverloop.c +++ b/serverloop.c -@@ -511,7 +511,7 @@ server_request_tun(struct ssh *ssh) +@@ -533,7 +533,7 @@ server_request_tun(struct ssh *ssh) debug_f("invalid tun"); goto done; } @@ -226,32 +224,6 @@ index 9c5b15678..768ee9fa4 100644 if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != (int)tun) goto done; -diff --git a/ssh-agent.c b/ssh-agent.c -index dfb6ac725..a17e681e1 100644 ---- a/ssh-agent.c -+++ b/ssh-agent.c -@@ -1595,6 +1595,7 @@ sanitize_pkcs11_provider(const char *provider) - - if (pkcs11_uri_parse(provider, uri) != 0) { - error("Failed to parse PKCS#11 URI"); -+ pkcs11_uri_cleanup(uri); - return NULL; - } - /* validate also provider from URI */ -diff --git a/ssh-keygen.c b/ssh-keygen.c -index 792aafde0..96b3474d6 100644 ---- a/ssh-keygen.c -+++ b/ssh-keygen.c -@@ -2424,6 +2424,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; -- 2.52.0 diff --git a/openssh.spec b/openssh.spec index 1a684c3..ff38f4b 100644 --- a/openssh.spec +++ b/openssh.spec @@ -38,12 +38,12 @@ # rpm -ba|--rebuild --define "static_openssl 1" %{?static_openssl:%global static_libcrypto 1} -%global openssh_ver 10.0p1 +%global openssh_ver 10.2p1 Summary: An open source implementation of SSH protocol version 2 Name: openssh Version: %{openssh_ver} -Release: 10%{?dist} +Release: 1%{?dist} URL: http://www.openssh.com/portable.html Source0: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz Source1: ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc @@ -73,7 +73,6 @@ Patch0003: 0003-openssh-6.6p1-allow-ip-opts.patch #(drop?) https://bugzilla.mindrot.org/show_bug.cgi?id=1925 Patch0004: 0004-openssh-5.9p1-ipv6man.patch Patch0005: 0005-openssh-5.8p2-sigpipe.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1789 Patch0006: 0006-openssh-7.2p2-x11.patch Patch0007: 0007-openssh-5.1p1-askpass-progress.patch #https://bugzilla.redhat.com/show_bug.cgi?id=198332 @@ -83,11 +82,6 @@ Patch0009: 0009-openssh-8.7p1-redhat.patch # warn users for unsupported UsePAM=no (#757545) Patch0010: 0010-openssh-7.8p1-UsePAM-warning.patch # GSSAPI Key Exchange (RFC 4462 + RFC 8732) -# from https://github.com/openssh-gsskex/openssh-gsskex/tree/fedora/master -# and -# Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures -# upstream MR: -# https://github.com/openssh-gsskex/openssh-gsskex/pull/21 Patch0011: 0011-openssh-9.6p1-gssapi-keyex.patch #http://www.mail-archive.com/kerberos@mit.edu/msg17591.html Patch0012: 0012-openssh-6.6p1-force_krb.patch @@ -113,73 +107,72 @@ Patch0020: 0020-openssh-6.8p1-sshdT-output.patch Patch0021: 0021-openssh-6.7p1-sftp-force-permission.patch # make s390 use /dev/ crypto devices -- ignore closefrom Patch0022: 0022-openssh-7.2p2-s390-closefrom.patch -# Move MAX_DISPLAYS to a configuration option (#1341302) -Patch0023: 0023-openssh-7.3p1-x11-max-displays.patch # Pass inetd flags for SELinux down to openbsd compat level -Patch0024: 0024-openssh-7.6p1-cleanup-selinux.patch +Patch0023: 0023-openssh-7.6p1-cleanup-selinux.patch # Sandbox adjustments for s390 and audit -Patch0025: 0025-openssh-7.5p1-sandbox.patch -# PKCS#11 URIs (upstream #2817, 2nd iteration) -# https://github.com/Jakuje/openssh-portable/commits/jjelen-pkcs11 -# git show > ~/devel/fedora/openssh/openssh-8.0p1-pkcs11-uri.patch -Patch0026: 0026-openssh-8.0p1-pkcs11-uri.patch +Patch0024: 0024-openssh-7.5p1-sandbox.patch # Unbreak scp between two IPv6 hosts (#1620333) -Patch0027: 0027-openssh-7.8p1-scp-ipv6.patch +Patch0025: 0025-openssh-7.8p1-scp-ipv6.patch # Mention crypto-policies in manual pages (#1668325) # clarify rhbz#2068423 on the man page of ssh_config -Patch0028: 0028-openssh-8.0p1-crypto-policies.patch +Patch0026: 0026-openssh-8.0p1-crypto-policies.patch # Use OpenSSL KDF (#1631761) -Patch0029: 0029-openssh-8.0p1-openssl-kdf.patch +Patch0027: 0027-openssh-8.0p1-openssl-kdf.patch # sk-dummy.so built with -fvisibility=hidden does not work -Patch0030: 0030-openssh-8.2p1-visibility.patch +Patch0028: 0028-openssh-8.2p1-visibility.patch # Do not break X11 without IPv6 -Patch0031: 0031-openssh-8.2p1-x11-without-ipv6.patch +Patch0029: 0029-openssh-8.2p1-x11-without-ipv6.patch # sshd provides PAM an incorrect error code (#1879503) -Patch0032: 0032-openssh-8.0p1-preserve-pam-errors.patch +Patch0030: 0030-openssh-8.0p1-preserve-pam-errors.patch # Implement kill switch for SCP protocol -Patch0033: 0033-openssh-8.7p1-scp-kill-switch.patch +Patch0031: 0031-openssh-8.7p1-scp-kill-switch.patch # Workaround for lack of sftp_realpath in older versions of RHEL # https://bugzilla.redhat.com/show_bug.cgi?id=2038854 # https://github.com/openssh/openssh-portable/pull/299 # downstream only -Patch0034: 0034-openssh-8.7p1-recursive-scp.patch +Patch0032: 0032-openssh-8.7p1-recursive-scp.patch # Downstream alias for MinRSABits -Patch0035: 0035-openssh-8.7p1-minrsabits.patch +Patch0033: 0033-openssh-8.7p1-minrsabits.patch # downstream only, IBMCA tentative fix # From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14 -Patch0036: 0036-openssh-8.7p1-ibmca.patch +Patch0034: 0034-openssh-8.7p1-ibmca.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1402 # https://bugzilla.redhat.com/show_bug.cgi?id=1171248 # record pfs= field in CRYPTO_SESSION audit event -Patch0037: 0037-openssh-7.6p1-audit.patch +Patch0035: 0035-openssh-7.6p1-audit.patch # Audit race condition in forked child (#1310684) -Patch0038: 0038-openssh-7.1p2-audit-race-condition.patch +Patch0036: 0036-openssh-7.1p2-audit-race-condition.patch # https://bugzilla.redhat.com/show_bug.cgi?id=2049947 -Patch0039: 0039-openssh-9.0p1-audit-log.patch -Patch0040: 0040-openssh-7.7p1-fips.patch +Patch0037: 0037-openssh-9.0p1-audit-log.patch +Patch0038: 0038-openssh-7.7p1-fips.patch # Add missing options from ssh_config into ssh manpage # upstream bug: # https://bugzilla.mindrot.org/show_bug.cgi?id=3455 -Patch0041: 0041-openssh-8.7p1-ssh-manpage.patch +Patch0039: 0039-openssh-8.7p1-ssh-manpage.patch # Don't propose disallowed algorithms during hostkey negotiation # upstream MR: # https://github.com/openssh/openssh-portable/pull/323 -Patch0042: 0042-openssh-8.7p1-negotiate-supported-algs.patch -Patch0043: 0043-openssh-9.0p1-evp-fips-kex.patch -Patch0044: 0044-openssh-8.7p1-nohostsha1proof.patch -Patch0045: 0045-openssh-9.6p1-pam-rhost.patch -Patch0046: 0046-openssh-9.9p1-separate-keysign.patch -Patch0047: 0047-openssh-9.9p1-openssl-mlkem.patch +Patch0040: 0040-openssh-8.7p1-negotiate-supported-algs.patch +Patch0041: 0041-openssh-9.0p1-evp-fips-kex.patch +Patch0042: 0042-openssh-8.7p1-nohostsha1proof.patch +Patch0043: 0043-openssh-9.9p1-separate-keysign.patch +Patch0044: 0044-openssh-9.9p1-openssl-mlkem.patch # https://www.openwall.com/lists/oss-security/2025/02/22/1 -Patch0048: 0048-openssh-9.9p2-error_processing.patch +Patch0045: 0045-openssh-9.9p2-error_processing.patch # https://github.com/openssh/openssh-portable/pull/564 -Patch0049: 0049-Provide-better-error-for-non-supported-private-keys.patch +Patch0046: 0046-Provide-better-error-for-non-supported-private-keys.patch # https://github.com/openssh/openssh-portable/pull/567 -Patch0050: 0050-Ignore-bad-hostkeys-in-known_hosts-file.patch +Patch0047: 0047-Ignore-bad-hostkeys-in-known_hosts-file.patch # https://github.com/openssh/openssh-portable/pull/500 -Patch0051: 0051-support-authentication-indicators-in-GSSAPI.patch -Patch0052: 0052-NIST-curves-hybrid-KEX-implementation.patch - +Patch0048: 0048-support-authentication-indicators-in-GSSAPI.patch +Patch0049: 0049-NIST-curves-hybrid-KEX-implementation.patch +# landed upstream, to be removed after 10.3 +Patch0050: 0050-Provide-a-way-to-disable-GSSAPIDelegateCredentials-s.patch +# Move MAX_DISPLAYS to a configuration option (#1341302) +Patch0051: 0051-openssh-7.3p1-x11-max-displays.patch +# PKCS#11 URIs (upstream #2817, seriously reworked on rebasing to 10.2) +# https://github.com/Jakuje/openssh-portable/commits/jjelen-pkcs11 +Patch0052: 0052-openssh-10.2p1-pkcs11-uri.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 Patch1000: 1000-openssh-6.7p1-coverity.patch @@ -351,7 +344,6 @@ fi --with-ipaddr-display \ --with-pie=no \ --without-hardening `# The hardening flags are configured by system` \ - --with-systemd \ --with-default-pkcs11-provider=yes \ --with-security-key-builtin=yes \ --with-pam \ @@ -583,6 +575,9 @@ test -f %{sysconfig_anaconda} && \ %attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so %changelog +* Wed Dec 17 2025 Dmitry Belyavskiy - 10.2p1-1 +- Rebase to OpenSSH 10.2p1 + * Wed Dec 10 2025 Pavol Žáčik - 10.0p1-10 - Update gssapi-keyex patch to not abort KEX without hostkey diff --git a/sources b/sources index 10b461b..318e485 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ -SHA512 (openssh-10.0p1.tar.gz) = 2daa1fcf95793b23810142077e68ddfabdf3732b207ef4f033a027f72d733d0e9bcdb6f757e7f3a5934b972de05bfaae3baae381cfc7a400cd8ab4d4e277a0ed -SHA512 (openssh-10.0p1.tar.gz.asc) = 6ab9deb4233ff159e55a18c9fc07d5ff8a41723dad74aa3d803e1476b585f5662aba34f8a7a1f5fe1d248f3ff3cd663f2c2fb8e399c6a4723b6215b0eb423d13 +SHA512 (openssh-10.2p1.tar.gz) = 66f3dd646179e71aaf41c33b6f14a207dc873d71d24f11c130a89dee317ee45398b818e5b94887b5913240964a38630d7bca3e481e0f1eff2e41d9e1cfdbdfc5 +SHA512 (openssh-10.2p1.tar.gz.asc) = f1f71700b1b0b2117aed505488b98b7ebb51ce26e53184b08df0b07aa2c5a1e54dc4d3cbcbe871b5ad849a2a0e22b02af318ff22a68c980ab53b04be03c9bf3c SHA512 (gpgkey-736060BA.gpg) = df44f3fdbcd1d596705348c7f5aed3f738c5f626a55955e0642f7c6c082995cf36a1b1891bb41b8715cb2aff34fef1c877e0eff0d3507dd00a055ba695757a21