From 4c7dfeee1bf2e43395d317a48253cfc13dc9e1cb Mon Sep 17 00:00:00 2001 From: Raven Date: Wed, 28 Feb 2024 17:40:12 +0600 Subject: [PATCH] openssh: sync with latest SRPM --- openssh/openssh-5.8p2-sigpipe.patch | 10 +- openssh/openssh-6.3p1-ctr-evp-fast.patch | 101 -- openssh/openssh-6.6.1p1-log-in-chroot.patch | 4 +- openssh/openssh-6.6p1-allow-ip-opts.patch | 11 +- openssh/openssh-6.6p1-keycat.patch | 4 +- openssh/openssh-6.6p1-keyperm.patch | 31 - openssh/openssh-6.6p1-kuserok.patch | 4 +- openssh/openssh-6.7p1-coverity.patch | 205 --- openssh/openssh-7.3p1-x11-max-displays.patch | 8 +- openssh/openssh-7.4p1-systemd.patch | 2 +- openssh/openssh-7.5p1-sandbox.patch | 2 +- openssh/openssh-7.6p1-audit.patch | 44 +- openssh/openssh-7.7p1-fips.patch | 357 ++++- openssh/openssh-7.7p1-redhat.patch | 32 +- openssh/openssh-7.8p1-UsePAM-warning.patch | 2 +- openssh/openssh-7.8p1-role-mls.patch | 6 +- openssh/openssh-8.0p1-crypto-policies.patch | 229 ++- openssh/openssh-8.0p1-openssl-evp.patch | 720 ---------- openssh/openssh-8.7p1-CVE-2023-25136.patch | 38 - openssh/openssh-8.7p1-evpgenkey.patch | 110 -- openssh/openssh-8.7p1-gssapi-auth.patch | 20 - openssh/openssh-8.7p1-host-based-auth.patch | 151 -- openssh/openssh-8.7p1-ibmca.patch | 7 +- openssh/openssh-8.7p1-mem-leak.patch | 156 --- openssh/openssh-8.7p1-minimize-sha1-use.patch | 207 --- openssh/openssh-8.7p1-minrsabits.patch | 436 +----- ...enssh-8.7p1-negotiate-supported-algs.patch | 146 +- openssh/openssh-8.7p1-nohostsha1proof.patch | 402 ++++++ openssh/openssh-8.7p1-recursive-scp.patch | 69 +- openssh/openssh-8.7p1-scp-clears-file.patch | 304 ---- openssh/openssh-8.7p1-scp-kill-switch.patch | 4 +- .../openssh-8.7p1-sftp-default-protocol.patch | 87 -- .../openssh-8.7p1-sftpscp-dir-create.patch | 135 -- openssh/openssh-8.7p1-ssh-manpage.patch | 2 +- openssh/openssh-8.8p1-skip-some-tests.patch | 41 - openssh/openssh-9.0p1-evp-fips-dh.patch | 292 ++++ openssh/openssh-9.0p1-evp-fips-ecdh.patch | 207 +++ ...patch => openssh-9.3p1-gssapi-keyex.patch} | 156 ++- .../openssh-9.3p1-merged-openssl-evp.patch | 1236 +++++++++++++++++ openssh/openssh-9.3p1-openssl-compat.patch | 40 + ...penssh-9.3p1-upstream-cve-2023-38408.patch | 17 - ...i.patch => openssh-9.3p2-pkcs11-uri.patch} | 606 ++++---- openssh/openssh-server-systemd-sysusers.conf | 2 + openssh/openssh.pam | 20 + openssh/openssh.spec | 521 +++---- openssh/openssh.sshd_config | 8 +- openssh/pam_ssh_agent-configure-c99.patch | 249 ++++ openssh/ssh-agent.service | 9 +- openssh/ssh-agent.socket | 14 + openssh/ssh-host-keys-migration.service | 15 + openssh/ssh-host-keys-migration.sh | 36 + openssh/sshd-keygen | 3 +- openssh/{sshd.pam => sshd.pam.el6} | 0 openssh/sshd.service | 3 + openssh/sshd.sysconfig | 19 +- openssh/sshd@.service | 3 + 56 files changed, 3920 insertions(+), 3623 deletions(-) delete mode 100644 openssh/openssh-6.3p1-ctr-evp-fast.patch delete mode 100644 openssh/openssh-6.6p1-keyperm.patch delete mode 100644 openssh/openssh-8.0p1-openssl-evp.patch delete mode 100644 openssh/openssh-8.7p1-CVE-2023-25136.patch delete mode 100644 openssh/openssh-8.7p1-evpgenkey.patch delete mode 100644 openssh/openssh-8.7p1-gssapi-auth.patch delete mode 100644 openssh/openssh-8.7p1-host-based-auth.patch delete mode 100644 openssh/openssh-8.7p1-mem-leak.patch delete mode 100644 openssh/openssh-8.7p1-minimize-sha1-use.patch create mode 100644 openssh/openssh-8.7p1-nohostsha1proof.patch delete mode 100644 openssh/openssh-8.7p1-scp-clears-file.patch delete mode 100644 openssh/openssh-8.7p1-sftp-default-protocol.patch delete mode 100644 openssh/openssh-8.7p1-sftpscp-dir-create.patch delete mode 100644 openssh/openssh-8.8p1-skip-some-tests.patch create mode 100644 openssh/openssh-9.0p1-evp-fips-dh.patch create mode 100644 openssh/openssh-9.0p1-evp-fips-ecdh.patch rename openssh/{openssh-8.0p1-gssapi-keyex.patch => openssh-9.3p1-gssapi-keyex.patch} (97%) create mode 100644 openssh/openssh-9.3p1-merged-openssl-evp.patch create mode 100644 openssh/openssh-9.3p1-openssl-compat.patch delete mode 100644 openssh/openssh-9.3p1-upstream-cve-2023-38408.patch rename openssh/{openssh-8.0p1-pkcs11-uri.patch => openssh-9.3p2-pkcs11-uri.patch} (88%) create mode 100644 openssh/openssh-server-systemd-sysusers.conf create mode 100644 openssh/openssh.pam create mode 100644 openssh/pam_ssh_agent-configure-c99.patch create mode 100644 openssh/ssh-agent.socket create mode 100644 openssh/ssh-host-keys-migration.service create mode 100644 openssh/ssh-host-keys-migration.sh rename openssh/{sshd.pam => sshd.pam.el6} (100%) diff --git a/openssh/openssh-5.8p2-sigpipe.patch b/openssh/openssh-5.8p2-sigpipe.patch index 56af045..554e346 100644 --- a/openssh/openssh-5.8p2-sigpipe.patch +++ b/openssh/openssh-5.8p2-sigpipe.patch @@ -1,12 +1,14 @@ 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,8 @@ main(int argc, char **argv) +@@ -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_nfdset = howmany(maxfd, NFDBITS); - read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask)); + read_wait = xcalloc(maxfd, sizeof(struct pollfd)); + for (j = 0; j < maxfd; j++) + read_wait[j].fd = -1; diff --git a/openssh/openssh-6.3p1-ctr-evp-fast.patch b/openssh/openssh-6.3p1-ctr-evp-fast.patch deleted file mode 100644 index ddcb7f1..0000000 --- a/openssh/openssh-6.3p1-ctr-evp-fast.patch +++ /dev/null @@ -1,101 +0,0 @@ -diff -up openssh-5.9p1/cipher-ctr.c.ctr-evp openssh-5.9p1/cipher-ctr.c ---- openssh-5.9p1/cipher-ctr.c.ctr-evp 2012-01-11 09:24:06.000000000 +0100 -+++ openssh-5.9p1/cipher-ctr.c 2012-01-11 15:54:04.675956600 +0100 -@@ -38,7 +38,7 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, in - - struct ssh_aes_ctr_ctx - { -- AES_KEY aes_ctx; -+ EVP_CIPHER_CTX ecbctx; - u_char aes_counter[AES_BLOCK_SIZE]; - }; - -@@ -63,21 +63,42 @@ ssh_aes_ctr(EVP_CIPHER_CTX *ctx, u_char - { - struct ssh_aes_ctr_ctx *c; - size_t n = 0; -- u_char buf[AES_BLOCK_SIZE]; -+ u_char ctrbuf[AES_BLOCK_SIZE*256]; -+ u_char buf[AES_BLOCK_SIZE*256]; - - if (len == 0) - return (1); - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) - return (0); - -- while ((len--) > 0) { -+ for (; len > 0; len -= sizeof(u_int)) { -+ u_int r,a,b; -+ - if (n == 0) { -- AES_encrypt(c->aes_counter, buf, &c->aes_ctx); -- ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); -+ int outl, i, buflen; -+ -+ buflen = MIN(len, sizeof(ctrbuf)); -+ -+ for(i = 0; i < buflen; i += AES_BLOCK_SIZE) { -+ memcpy(&ctrbuf[i], c->aes_counter, AES_BLOCK_SIZE); -+ ssh_ctr_inc(c->aes_counter, AES_BLOCK_SIZE); -+ } -+ -+ EVP_EncryptUpdate(&c->ecbctx, buf, &outl, -+ ctrbuf, buflen); - } -- *(dest++) = *(src++) ^ buf[n]; -- n = (n + 1) % AES_BLOCK_SIZE; -+ -+ memcpy(&a, src, sizeof(a)); -+ memcpy(&b, &buf[n], sizeof(b)); -+ r = a ^ b; -+ memcpy(dest, &r, sizeof(r)); -+ src += sizeof(a); -+ dest += sizeof(r); -+ -+ n = (n + sizeof(b)) % sizeof(buf); - } -+ memset(ctrbuf, '\0', sizeof(ctrbuf)); -+ memset(buf, '\0', sizeof(buf)); - return (1); - } - -@@ -91,9 +112,28 @@ ssh_aes_ctr_init(EVP_CIPHER_CTX *ctx, co - c = xmalloc(sizeof(*c)); - EVP_CIPHER_CTX_set_app_data(ctx, c); - } -- if (key != NULL) -- AES_set_encrypt_key(key, EVP_CIPHER_CTX_key_length(ctx) * 8, -- &c->aes_ctx); -+ -+ EVP_CIPHER_CTX_init(&c->ecbctx); -+ -+ if (key != NULL) { -+ const EVP_CIPHER *cipher; -+ switch(EVP_CIPHER_CTX_key_length(ctx)*8) { -+ case 128: -+ cipher = EVP_aes_128_ecb(); -+ break; -+ case 192: -+ cipher = EVP_aes_192_ecb(); -+ break; -+ case 256: -+ cipher = EVP_aes_256_ecb(); -+ break; -+ default: -+ fatal("ssh_aes_ctr_init: wrong aes key length"); -+ } -+ if(!EVP_EncryptInit_ex(&c->ecbctx, cipher, NULL, key, NULL)) -+ fatal("ssh_aes_ctr_init: cannot initialize aes encryption"); -+ EVP_CIPHER_CTX_set_padding(&c->ecbctx, 0); -+ } - if (iv != NULL) - memcpy(c->aes_counter, iv, AES_BLOCK_SIZE); - return (1); -@@ -105,6 +145,7 @@ ssh_aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) - struct ssh_aes_ctr_ctx *c; - - if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) != NULL) { -+ EVP_CIPHER_CTX_cleanup(&c->ecbctx); - memset(c, 0, sizeof(*c)); - free(c); - EVP_CIPHER_CTX_set_app_data(ctx, NULL); diff --git a/openssh/openssh-6.6.1p1-log-in-chroot.patch b/openssh/openssh-6.6.1p1-log-in-chroot.patch index 426c172..941c694 100644 --- a/openssh/openssh-6.6.1p1-log-in-chroot.patch +++ b/openssh/openssh-6.6.1p1-log-in-chroot.patch @@ -207,8 +207,8 @@ diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c -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) { - fd_set *rset, *wset; - int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0; + 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, extern char *__progname; diff --git a/openssh/openssh-6.6p1-allow-ip-opts.patch b/openssh/openssh-6.6p1-allow-ip-opts.patch index 953d613..be8d340 100644 --- a/openssh/openssh-6.6p1-allow-ip-opts.patch +++ b/openssh/openssh-6.6p1-allow-ip-opts.patch @@ -1,7 +1,7 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c --- openssh/sshd.c.ip-opts 2016-07-25 13:58:48.998507834 +0200 +++ openssh/sshd.c 2016-07-25 14:01:28.346469878 +0200 -@@ -1507,12 +1507,29 @@ check_ip_options(struct ssh *ssh) +@@ -1507,12 +1507,32 @@ check_ip_options(struct ssh *ssh) if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts, &option_size) >= 0 && option_size != 0) { @@ -21,11 +21,14 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c + case 130: + case 133: + case 134: -+ i += opts[i + 1]; -+ break; ++ if (i + 1 < option_size && opts[i + 1] >= 2) { ++ i += opts[i + 1]; ++ break; ++ } ++ /* FALLTHROUGH */ + default: + /* Fail, fatally, if we detect either loose or strict -+ * source routing options. */ ++ * or incorrect source routing options. */ + text[0] = '\0'; + for (i = 0; i < option_size; i++) + snprintf(text + i*3, sizeof(text) - i*3, diff --git a/openssh/openssh-6.6p1-keycat.patch b/openssh/openssh-6.6p1-keycat.patch index 2aa14bd..529b508 100644 --- a/openssh/openssh-6.6p1-keycat.patch +++ b/openssh/openssh-6.6p1-keycat.patch @@ -61,13 +61,13 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in ssh-xmss.o \ @@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) - $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) + $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS) +ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o + $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) - $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS) @@ -321,6 +325,7 @@ install-files: $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) diff --git a/openssh/openssh-6.6p1-keyperm.patch b/openssh/openssh-6.6p1-keyperm.patch deleted file mode 100644 index 5e06940..0000000 --- a/openssh/openssh-6.6p1-keyperm.patch +++ /dev/null @@ -1,31 +0,0 @@ -diff -up openssh-8.2p1/authfile.c.keyperm openssh-8.2p1/authfile.c ---- openssh-8.2p1/authfile.c.keyperm 2020-02-14 01:40:54.000000000 +0100 -+++ openssh-8.2p1/authfile.c 2020-02-17 11:55:12.841729758 +0100 -@@ -31,6 +31,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -101,7 +102,19 @@ sshkey_perm_ok(int fd, const char *filen - #ifdef HAVE_CYGWIN - if (check_ntsec(filename)) - #endif -+ - if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { -+ if (st.st_mode & 040) { -+ struct group *gr; -+ -+ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid)) { -+ /* The only additional bit is read -+ * for ssh_keys group, which is fine */ -+ if ((st.st_mode & 077) == 040 ) { -+ return 0; -+ } -+ } -+ } - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); - error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); - error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); diff --git a/openssh/openssh-6.6p1-kuserok.patch b/openssh/openssh-6.6p1-kuserok.patch index f3231f9..eaf4453 100644 --- a/openssh/openssh-6.6p1-kuserok.patch +++ b/openssh/openssh-6.6p1-kuserok.patch @@ -155,8 +155,8 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c * because if they are on a krb5-protected filesystem, user credentials * to access these files aren't available yet. */ - if (krb5_kuserok(krb_context, princ, name) && k5login_exists) { -+ if (ssh_krb5_kuserok(krb_context, princ, name, k5login_exists) -+ && k5login_exists) { ++ 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); diff --git a/openssh/openssh-6.7p1-coverity.patch b/openssh/openssh-6.7p1-coverity.patch index 930de69..494f4c6 100644 --- a/openssh/openssh-6.7p1-coverity.patch +++ b/openssh/openssh-6.7p1-coverity.patch @@ -1,37 +1,3 @@ -diff -up openssh-8.5p1/addr.c.coverity openssh-8.5p1/addr.c ---- openssh-8.5p1/addr.c.coverity 2021-03-02 11:31:47.000000000 +0100 -+++ openssh-8.5p1/addr.c 2021-03-24 12:03:33.782968159 +0100 -@@ -312,8 +312,10 @@ addr_pton(const char *p, struct xaddr *n - if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0) - return -1; - -- if (ai == NULL || ai->ai_addr == NULL) -+ if (ai == NULL || ai->ai_addr == NULL) { -+ freeaddrinfo(ai); - return -1; -+ } - - if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, - n) == -1) { -@@ -336,12 +338,16 @@ addr_sa_pton(const char *h, const char * - if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0) - return -1; - -- if (ai == NULL || ai->ai_addr == NULL) -+ if (ai == NULL || ai->ai_addr == NULL) { -+ freeaddrinfo(ai); - return -1; -+ } - - if (sa != NULL) { -- if (slen < ai->ai_addrlen) -+ if (slen < ai->ai_addrlen) { -+ freeaddrinfo(ai); - return -1; -+ } - memcpy(sa, &ai->ai_addr, ai->ai_addrlen); - } - 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 @@ -62,72 +28,6 @@ diff -up openssh-8.5p1/auth-options.c.coverity openssh-8.5p1/auth-options.c return 0; } -diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c ---- openssh-7.4p1/channels.c.coverity 2016-12-23 16:40:26.881788686 +0100 -+++ openssh-7.4p1/channels.c 2016-12-23 16:42:36.244818763 +0100 -@@ -1875,7 +1875,7 @@ channel_post_connecting(struct ssh *ssh, - debug("channel %d: connection failed: %s", - c->self, strerror(err)); - /* Try next address, if any */ -- if ((sock = connect_next(&c->connect_ctx)) > 0) { -+ if ((sock = connect_next(&c->connect_ctx)) >= 0) { - close(c->sock); - c->sock = c->rfd = c->wfd = sock; - channel_find_maxfd(ssh->chanctxt); -@@ -3804,7 +3804,7 @@ int - channel_request_remote_forwarding(struct ssh *ssh, struct Forward *fwd) - { - int r, success = 0, idx = -1; -- char *host_to_connect, *listen_host, *listen_path; -+ char *host_to_connect = NULL, *listen_host = NULL, *listen_path = NULL; - int port_to_connect, listen_port; - - /* Send the forward request to the remote side. */ -@@ -3832,7 +3832,6 @@ channel_request_remote_forwarding(struct - success = 1; - if (success) { - /* Record that connection to this host/port is permitted. */ -- host_to_connect = listen_host = listen_path = NULL; - port_to_connect = listen_port = 0; - if (fwd->connect_path != NULL) { - host_to_connect = xstrdup(fwd->connect_path); -@@ -3853,6 +3852,9 @@ channel_request_remote_forwarding(struct - host_to_connect, port_to_connect, - listen_host, listen_path, listen_port, NULL); - } -+ free(host_to_connect); -+ free(listen_host); -+ free(listen_path); - return idx; - } - -diff -up openssh-8.5p1/compat.c.coverity openssh-8.5p1/compat.c ---- openssh-8.5p1/compat.c.coverity 2021-03-24 12:03:33.768968062 +0100 -+++ openssh-8.5p1/compat.c 2021-03-24 12:03:33.783968166 +0100 -@@ -191,10 +191,12 @@ compat_kex_proposal(struct ssh *ssh, cha - return p; - debug2_f("original KEX proposal: %s", p); - if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) -+ /* coverity[overwrite_var : FALSE] */ - if ((p = match_filter_denylist(p, - "curve25519-sha256@libssh.org")) == NULL) - fatal("match_filter_denylist failed"); - if ((ssh->compat & SSH_OLD_DHGEX) != 0) { -+ /* coverity[overwrite_var : FALSE] */ - if ((p = match_filter_denylist(p, - "diffie-hellman-group-exchange-sha256," - "diffie-hellman-group-exchange-sha1")) == NULL) -diff -up openssh-8.5p1/dns.c.coverity openssh-8.5p1/dns.c ---- openssh-8.5p1/dns.c.coverity 2021-03-02 11:31:47.000000000 +0100 -+++ openssh-8.5p1/dns.c 2021-03-24 12:03:33.783968166 +0100 -@@ -282,6 +282,7 @@ verify_host_key_dns(const char *hostname - &hostkey_digest, &hostkey_digest_len, hostkey)) { - error("Error calculating key fingerprint."); - freerrset(fingerprints); -+ free(dnskey_digest); - return -1; - } - 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 @@ -243,17 +143,6 @@ diff -up openssh-8.5p1/misc.c.coverity openssh-8.5p1/misc.c return ret; } -diff -up openssh-8.5p1/moduli.c.coverity openssh-8.5p1/moduli.c ---- openssh-8.5p1/moduli.c.coverity 2021-03-02 11:31:47.000000000 +0100 -+++ openssh-8.5p1/moduli.c 2021-03-24 12:03:33.784968173 +0100 -@@ -476,6 +476,7 @@ write_checkpoint(char *cpfile, u_int32_t - else - logit("failed to write to checkpoint file '%s': %s", cpfile, - strerror(errno)); -+ /* coverity[leaked_storage : FALSE] */ - } - - static unsigned long 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 @@ -389,24 +278,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-8.5p1/session.c.coverity openssh-8.5p1/session.c ---- openssh-8.5p1/session.c.coverity 2021-03-24 12:03:33.777968124 +0100 -+++ openssh-8.5p1/session.c 2021-03-24 12:03:33.786968187 +0100 -@@ -1223,12 +1223,14 @@ do_setup_env(struct ssh *ssh, Session *s - /* Environment specified by admin */ - for (i = 0; i < options.num_setenv; i++) { - cp = xstrdup(options.setenv[i]); -+ /* coverity[overwrite_var : FALSE] */ - if ((value = strchr(cp, '=')) == NULL) { - /* shouldn't happen; vars are checked in servconf.c */ - fatal("Invalid config SetEnv: %s", options.setenv[i]); - } - *value++ = '\0'; - child_set_env(&env, &envsize, cp, value); -+ free(cp); - } - - /* SSH_CLIENT deprecated */ diff -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 @@ -419,34 +290,6 @@ diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c } _exit(1); -@@ -762,6 +762,8 @@ process_put(struct sftp_conn *conn, cons - fflag || global_fflag) == -1) - err = -1; - } -+ free(abs_dst); -+ abs_dst = NULL; - } - - out: -@@ -985,6 +987,7 @@ do_globbed_ls(struct sftp_conn *conn, co - if (lflag & LS_LONG_VIEW) { - if (g.gl_statv[i] == NULL) { - error("no stat information for %s", fname); -+ free(fname); - continue; - } - lname = ls_file(fname, g.gl_statv[i], 1, -diff -up openssh-8.5p1/sk-usbhid.c.coverity openssh-8.5p1/sk-usbhid.c ---- openssh-8.5p1/sk-usbhid.c.coverity 2021-03-02 11:31:47.000000000 +0100 -+++ openssh-8.5p1/sk-usbhid.c 2021-03-24 12:03:33.786968187 +0100 -@@ -1256,6 +1256,7 @@ sk_load_resident_keys(const char *pin, s - freezero(rks[i], sizeof(*rks[i])); - } - free(rks); -+ free(device); - return ret; - } - 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 @@ -495,25 +338,6 @@ diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c return 0; } -@@ -1386,6 +1388,9 @@ server_accept_loop(int *sock_in, int *so - explicit_bzero(rnd, sizeof(rnd)); - } - } -+ -+ if (fdset != NULL) -+ free(fdset); - } - - /* -@@ -2474,7 +2479,7 @@ do_ssh2_kex(struct ssh *ssh) - if (options.rekey_limit || options.rekey_interval) - ssh_packet_set_rekey_limits(ssh, options.rekey_limit, - options.rekey_interval); -- -+ /* coverity[leaked_storage : FALSE]*/ - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( - ssh, list_hostkey_types()); - @@ -2519,8 +2524,11 @@ do_ssh2_kex(struct ssh *ssh) if (newstr) @@ -540,32 +364,3 @@ diff -up openssh-8.5p1/ssh-keygen.c.coverity openssh-8.5p1/ssh-keygen.c } else { if (strncasecmp(cp, "key:", 4) == 0) { cp += 4; -@@ -2879,6 +2882,7 @@ do_moduli_screen(const char *out_file, c - } else if (strncmp(opts[i], "start-line=", 11) == 0) { - start_lineno = strtoul(opts[i]+11, NULL, 10); - } else if (strncmp(opts[i], "checkpoint=", 11) == 0) { -+ free(checkpoint); - checkpoint = xstrdup(opts[i]+11); - } else if (strncmp(opts[i], "generator=", 10) == 0) { - generator_wanted = (u_int32_t)strtonum( -@@ -2920,6 +2924,9 @@ do_moduli_screen(const char *out_file, c - #else /* WITH_OPENSSL */ - fatal("Moduli screening is not supported"); - #endif /* WITH_OPENSSL */ -+ free(checkpoint); -+ if (in != stdin) -+ fclose(in); - } - - static char * -diff -up openssh-8.5p1/sshsig.c.coverity openssh-8.5p1/sshsig.c ---- openssh-8.5p1/sshsig.c.coverity 2021-03-02 11:31:47.000000000 +0100 -+++ openssh-8.5p1/sshsig.c 2021-03-24 12:03:33.787968194 +0100 -@@ -515,6 +515,7 @@ hash_file(int fd, const char *hashalg, s - oerrno = errno; - error_f("read: %s", strerror(errno)); - ssh_digest_free(ctx); -+ ctx = NULL; - errno = oerrno; - r = SSH_ERR_SYSTEM_ERROR; - goto out; diff --git a/openssh/openssh-7.3p1-x11-max-displays.patch b/openssh/openssh-7.3p1-x11-max-displays.patch index 5af3e3b..2b702d4 100644 --- a/openssh/openssh-7.3p1-x11-max-displays.patch +++ b/openssh/openssh-7.3p1-x11-max-displays.patch @@ -10,8 +10,8 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c +/* Minimum port number for X11 forwarding */ +#define X11_PORT_MIN 6000 - /* Per-channel callback for pre/post select() actions */ - typedef void chan_fn(struct ssh *, Channel *c, + /* 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) */ int @@ -82,7 +82,7 @@ diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h +++ openssh-7.4p1/channels.h 2016-12-23 15:46:32.139506636 +0100 @@ -293,7 +293,7 @@ int permitopen_port(const char *); - void channel_set_x11_refuse_time(struct ssh *, u_int); + void channel_set_x11_refuse_time(struct ssh *, time_t); int x11_connect_display(struct ssh *); -int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **); +int x11_create_display_inet(struct ssh *, int, int, int, int, u_int *, int **); @@ -191,8 +191,8 @@ diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5 --- openssh-7.4p1/sshd_config.5.x11max 2016-12-23 15:46:32.134506635 +0100 +++ openssh-7.4p1/sshd_config.5 2016-12-23 15:46:32.141506636 +0100 @@ -1133,6 +1133,7 @@ Available keywords are - .Cm StreamLocalBindUnlink , .Cm TrustedUserCAKeys , + .Cm UnusedConnectionTimeout , .Cm X11DisplayOffset , +.Cm X11MaxDisplays , .Cm X11Forwarding diff --git a/openssh/openssh-7.4p1-systemd.patch b/openssh/openssh-7.4p1-systemd.patch index 4f9e58a..1242aac 100644 --- a/openssh/openssh-7.4p1-systemd.patch +++ b/openssh/openssh-7.4p1-systemd.patch @@ -9,8 +9,8 @@ index 2ffc369..162ce92 100644 --- a/configure.ac +++ b/configure.ac @@ -4265,6 +4265,30 @@ AC_ARG_WITH([kerberos5], - AC_SUBST([GSSLIBS]) AC_SUBST([K5LIBS]) + AC_SUBST([CHANNELLIBS]) +# Check whether user wants systemd support +SYSTEMD_MSG="no" diff --git a/openssh/openssh-7.5p1-sandbox.patch b/openssh/openssh-7.5p1-sandbox.patch index 7217c64..90640a0 100644 --- a/openssh/openssh-7.5p1-sandbox.patch +++ b/openssh/openssh-7.5p1-sandbox.patch @@ -21,7 +21,7 @@ index ca75cc7..6e7de31 100644 + SC_ALLOW(__NR_flock), +#endif #ifdef __NR_futex - SC_ALLOW(__NR_futex), + SC_FUTEX(__NR_futex), #endif @@ -178,6 +181,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_gettimeofday diff --git a/openssh/openssh-7.6p1-audit.patch b/openssh/openssh-7.6p1-audit.patch index 4473518..748c4b6 100644 --- a/openssh/openssh-7.6p1-audit.patch +++ b/openssh/openssh-7.6p1-audit.patch @@ -729,7 +729,7 @@ 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 - } else { + authctxt->valid = 0; /* Invalid user, fake password information */ authctxt->pw = fakepw(); -#ifdef SSH_AUDIT_EVENTS @@ -802,8 +802,8 @@ diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c +} + static int - match_principals_option(const char *principal_list, struct sshkey_cert *cert) - { + 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 @@ -820,15 +820,6 @@ diff -up openssh-8.6p1/auth.c.audit openssh-8.6p1/auth.c 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 -@@ -193,6 +193,8 @@ struct passwd * getpwnamallow(struct ssh - - char *expand_authorized_keys(const char *, struct passwd *pw); - char *authorized_principals_file(struct passwd *); -+int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); - - FILE *auth_openkeyfile(const char *, struct passwd *, int); - FILE *auth_openprincipals(const char *, struct passwd *, int); @@ -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 *, @@ -838,6 +829,15 @@ diff -up openssh-8.6p1/auth.h.audit openssh-8.6p1/auth.h /* Key / cert options linkage to auth layer */ const struct sshauthopt *auth_options(struct ssh *); +@@ -239,6 +241,8 @@ struct passwd * getpwnamallow(struct ssh + char *, const char *, const char *, const char *, struct sshauthopt **); + int auth_check_authkeys_file(struct passwd *, FILE *, char *, + struct sshkey *, const char *, const char *, struct sshauthopt **); ++int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); + FILE *auth_openkeyfile(const char *, struct passwd *, int); + FILE *auth_openprincipals(const char *, struct passwd *, int); + diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c --- openssh-8.6p1/cipher.c.audit 2021-04-16 05:55:25.000000000 +0200 +++ openssh-8.6p1/cipher.c 2021-04-19 16:47:35.755062122 +0200 @@ -910,9 +910,9 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c --- openssh-8.6p1/kex.c.audit 2021-04-19 16:47:35.743062030 +0200 +++ openssh-8.6p1/kex.c 2021-04-19 16:47:35.755062122 +0200 @@ -65,6 +65,7 @@ - #include "ssherr.h" #include "sshbuf.h" #include "digest.h" + #include "xmalloc.h" +#include "audit.h" #ifdef GSSAPI @@ -1195,9 +1195,9 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c - ret = sshkey_verify(key, signature, signaturelen, data, datalen, - sigalg, ssh->compat, &sig_details); - debug3_f("%s %s signature %s%s%s", auth_method, sshkey_type(key), + debug3_f("%s %s signature using %s %s%s%s", auth_method, + sshkey_type(key), sigalg == NULL ? "default" : sigalg, (ret == 0) ? "verified" : "unverified", - (ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : ""); @@ -1576,13 +1600,19 @@ mm_record_login(struct ssh *ssh, Session } @@ -2006,7 +2006,7 @@ diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h @@ -71,10 +77,12 @@ void session_unused(int); int session_input_channel_req(struct ssh *, Channel *, const char *); void session_close_by_pid(struct ssh *ssh, pid_t, int); - void session_close_by_channel(struct ssh *, int, void *); + void session_close_by_channel(struct ssh *, int, int, void *); -void session_destroy_all(struct ssh *, void (*)(Session *)); +void session_destroy_all(struct ssh *, void (*)(struct ssh*, Session *)); void session_pty_cleanup2(Session *); @@ -2040,7 +2040,7 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c static char *listener_proctitle; @@ -279,6 +280,15 @@ close_listen_socks(void) - num_listen_socks = -1; + num_listen_socks = 0; } +/* @@ -2049,16 +2049,16 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c + */ +int listening_for_clients(void) +{ -+ return num_listen_socks >= 0; ++ return num_listen_socks > 0; +} + static void close_startup_pipes(void) { @@ -377,18 +387,45 @@ grace_alarm_handler(int sig) - } + ssh_remote_port(the_active_state)); } - + -/* Destroy the host and server keys. They will no longer be needed. */ +/* + * Destroy the host and server keys. They will no longer be needed. Careful, @@ -2196,8 +2196,8 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c -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) { - fd_set *fdset; - int i, j, ret, maxfd; + 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.", diff --git a/openssh/openssh-7.7p1-fips.patch b/openssh/openssh-7.7p1-fips.patch index 72bceb1..5351571 100644 --- a/openssh/openssh-7.7p1-fips.patch +++ b/openssh/openssh-7.7p1-fips.patch @@ -1,25 +1,20 @@ -diff -up openssh-8.6p1/cipher-ctr.c.fips openssh-8.6p1/cipher-ctr.c ---- openssh-8.6p1/cipher-ctr.c.fips 2021-04-19 16:53:02.994577324 +0200 -+++ openssh-8.6p1/cipher-ctr.c 2021-04-19 16:53:03.064577862 +0200 -@@ -179,7 +179,8 @@ evp_aes_128_ctr(void) - aes_ctr.do_cipher = ssh_aes_ctr; - #ifndef SSH_OLD_EVP - aes_ctr.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH | -- EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV; -+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CUSTOM_IV | -+ EVP_CIPH_FLAG_FIPS; - #endif - return (&aes_ctr); - } 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-04-19 16:58:47.750263410 +0200 ++++ openssh-8.6p1/dh.c 2021-05-06 12:12:10.107634472 +0200 +@@ -36,6 +36,7 @@ + + #include + #include ++#include + + #include "dh.h" + #include "pathnames.h" @@ -164,6 +164,12 @@ choose_dh(int min, int wantbits, int max int best, bestcount, which, linenum; struct dhgroup dhg; + if (FIPS_mode()) { -+ logit("Using arbitrary primes is not allowed in FIPS mode." ++ verbose("Using arbitrary primes is not allowed in FIPS mode." + " Falling back to known groups."); + return (dh_new_group_fallback(max)); + } @@ -67,8 +62,8 @@ 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-04-19 16:53:03.064577862 +0200 -+++ openssh-8.6p1/dh.h 2021-04-19 16:59:31.951616078 +0200 +--- 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 @@ -45,6 +45,7 @@ DH *dh_new_group_fallback(int); int dh_gen_key(DH *, int); @@ -78,8 +73,16 @@ 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-04-19 16:53:03.058577815 +0200 -+++ openssh-8.6p1/kex.c 2021-04-19 16:53:03.065577869 +0200 +--- 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 +@@ -39,6 +39,7 @@ + + #ifdef WITH_OPENSSL + #include ++#include + #include + # ifdef HAVE_EVP_KDF_CTX_NEW_ID + # include @@ -203,7 +203,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { @@ -94,12 +97,12 @@ diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c } 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-04-19 16:53:03.065577869 +0200 ++++ openssh-8.6p1/kexgexc.c 2021-05-06 12:08:36.498926877 +0200 @@ -28,6 +28,7 @@ #ifdef WITH_OPENSSL -+#include ++#include #include #include @@ -116,8 +119,8 @@ diff -up openssh-8.6p1/kexgexc.c.fips openssh-8.6p1/kexgexc.c /* 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-04-19 16:53:03.065577869 +0200 -@@ -57,6 +57,19 @@ ++++ openssh-8.6p1/myproposal.h 2021-05-06 12:08:36.498926877 +0200 +@@ -57,6 +57,18 @@ "rsa-sha2-512," \ "rsa-sha2-256" @@ -127,12 +130,11 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h + "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ + "rsa-sha2-512-cert-v01@openssh.com," \ + "rsa-sha2-256-cert-v01@openssh.com," \ -+ "ssh-rsa-cert-v01@openssh.com," \ + "ecdsa-sha2-nistp256," \ + "ecdsa-sha2-nistp384," \ + "ecdsa-sha2-nistp521," \ + "rsa-sha2-512," \ -+ "rsa-sha2-256," ++ "rsa-sha2-256" + #define KEX_SERVER_ENCRYPT \ "chacha20-poly1305@openssh.com," \ @@ -166,8 +168,16 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h #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-04-19 16:53:02.999577362 +0200 -+++ openssh-8.6p1/readconf.c 2021-04-19 16:53:03.065577869 +0200 +--- 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 @@ + #include + #include + #include ++#include + #ifdef USE_SYSTEM_GLOB + # include + #else @@ -2538,11 +2538,16 @@ fill_default_options(Options * options) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); @@ -191,8 +201,8 @@ diff -up openssh-8.6p1/readconf.c.fips openssh-8.6p1/readconf.c 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-04-19 16:53:03.034577631 +0200 -+++ openssh-8.6p1/sandbox-seccomp-filter.c 2021-04-19 16:53:03.065577869 +0200 +--- 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_ #ifdef __NR_open SC_DENY(__NR_open, EACCES), @@ -204,8 +214,16 @@ diff -up openssh-8.6p1/sandbox-seccomp-filter.c.fips openssh-8.6p1/sandbox-secco 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-04-19 16:53:03.027577577 +0200 -+++ openssh-8.6p1/servconf.c 2021-04-19 16:53:03.066577877 +0200 +--- 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 @@ + #include + #include + #include ++#include + #ifdef HAVE_UTIL_H + #include + #endif @@ -226,11 +226,16 @@ assemble_algorithms(ServerOptions *o) all_key = sshkey_alg_list(0, 0, 1, ','); all_sig = sshkey_alg_list(0, 1, 1, ','); @@ -229,13 +247,13 @@ diff -up openssh-8.6p1/servconf.c.fips openssh-8.6p1/servconf.c 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-04-19 16:53:03.038577662 +0200 -+++ openssh-8.6p1/ssh.c 2021-04-19 16:53:03.066577877 +0200 +--- 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 @@ #include #include #endif -+#include ++#include #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" @@ -251,13 +269,13 @@ diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c 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-04-19 16:53:03.055577792 +0200 -+++ openssh-8.6p1/sshconnect2.c 2021-04-19 16:53:03.066577877 +0200 +--- 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 @@ -45,6 +45,8 @@ #include #endif -+#include ++#include + #include "openbsd-compat/sys-queue.h" @@ -332,10 +350,10 @@ 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-04-19 16:53:03.060577831 +0200 -+++ openssh-8.6p1/sshd.c 2021-04-19 16:57:45.827769340 +0200 +--- 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 @@ - #include + #endif #include #include +#include @@ -346,18 +364,24 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c #include #include #include -+#include ++#include #include "openbsd-compat/openssl-compat.h" #endif -@@ -1619,6 +1621,7 @@ main(int ac, char **av) - #endif - __progname = ssh_get_progname(av[0]); - -+ OpenSSL_add_all_algorithms(); - /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ - saved_argc = ac; - rexec_argc = ac; +@@ -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); @@ -389,13 +413,13 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.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-04-19 16:53:03.061577838 +0200 -+++ openssh-8.6p1/sshkey.c 2021-04-19 16:53:03.067577885 +0200 -@@ -34,6 +34,7 @@ - #include - #include +--- 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 #endif #include "crypto_api.h" @@ -407,18 +431,80 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c #include "ssh-sk.h" #ifdef WITH_XMSS -@@ -1705,6 +1707,8 @@ rsa_generate_private_key(u_int bits, RSA - } - if (!BN_set_word(f4, RSA_F4) || - !RSA_generate_key_ex(private, bits, f4, 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; +@@ -285,6 +285,18 @@ sshkey_alg_list(int certs_only, int plai + impl = keyimpls[i]; + if (impl->name == NULL || impl->type == KEY_NULL) + continue; ++ if (FIPS_mode()) { ++ switch (impl->type) { ++ case KEY_ED25519: ++ case KEY_ED25519_SK: ++ case KEY_ED25519_CERT: ++ case KEY_ED25519_SK_CERT: ++ continue; ++ break; ++ default: ++ break; ++ } ++ } + 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 + return SSH_ERR_EC_CURVE_MISMATCH; } + ++ switch (type) { ++ case KEY_ED25519: ++ case KEY_ED25519_SK: ++ case KEY_ED25519_CERT: ++ case KEY_ED25519_SK_CERT: ++ if (FIPS_mode()) { ++ sshkey_free(k); ++ logit_f("Ed25519 keys are not allowed in FIPS mode"); ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ break; ++ default: ++ break; ++ } + /* Fill in ret from parsed key */ + sshkey_free_contents(ret); + *ret = *k; +@@ -2916,6 +2916,11 @@ sshkey_sign(struct sshkey *key, + *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 ((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, + *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 ((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-04-19 16:53:03.038577662 +0200 -+++ openssh-8.6p1/ssh-keygen.c 2021-04-19 16:53:03.068577892 +0200 +--- 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 @@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na #endif } @@ -426,7 +512,7 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c + if (FIPS_mode()) { + if (type == KEY_DSA) + fatal("DSA keys are not allowed in FIPS mode"); -+ if (type == KEY_ED25519) ++ if (type == KEY_ED25519 || type == KEY_ED25519_SK) + fatal("ED25519 keys are not allowed in FIPS mode"); + } switch (type) { @@ -451,3 +537,142 @@ 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)); +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 +@@ -1705,6 +1707,8 @@ ssh_rsa_generate(u_int bits, RSA + goto out; + + if (EVP_PKEY_keygen(ctx, &res) <= 0) { ++ 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 +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + + #include "sshkey.h" + #include "kex.h" +@@ -115,10 +116,20 @@ 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; + default: + r = SSH_ERR_INVALID_ARGUMENT; +@@ -186,11 +197,21 @@ 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; + default: + r = SSH_ERR_INVALID_ARGUMENT; +@@ -285,12 +306,22 @@ 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; + 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 --git a/openssh/openssh-7.7p1-redhat.patch b/openssh/openssh-7.7p1-redhat.patch index fcda6c6..1d77f90 100644 --- a/openssh/openssh-7.7p1-redhat.patch +++ b/openssh/openssh-7.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,21 @@ +@@ -0,0 +1,15 @@ +# The options here are in the "Match final block" to be applied as the last +# options and could be potentially overwritten by the user configuration +Match final all @@ -29,12 +29,6 @@ diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat +# mode correctly we set this to yes. + ForwardX11Trusted yes + -+# Send locale-related environment variables -+ SendEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+ SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+ SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+ SendEnv XMODIFIERS -+ +# Uncomment this if you want to use .local domain +# Host *.local diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0 @@ -86,14 +80,7 @@ diff -up openssh/sshd_config.redhat openssh/sshd_config diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat --- openssh/sshd_config_redhat.redhat 2020-02-13 18:14:02.268006439 +0100 +++ openssh/sshd_config_redhat 2020-02-13 18:19:20.765035947 +0100 -@@ -0,0 +1,28 @@ -+# This system is following system-wide crypto policy. The changes to -+# crypto properties (Ciphers, MACs, ...) will not have any effect in -+# this or following included files. To override some configuration option, -+# write it before this block or include it before this file. -+# Please, see manual pages for update-crypto-policies(8) and sshd_config(5). -+Include /etc/crypto-policies/back-ends/opensshserver.config -+ +@@ -0,0 +1,15 @@ +SyslogFacility AUTHPRIV + +ChallengeResponseAuthentication no @@ -109,9 +96,14 @@ diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat +# as it is more configurable and versatile than the built-in version. +PrintMotd no + -+# Accept locale-related environment variables -+AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES -+AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT -+AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE -+AcceptEnv XMODIFIERS +diff -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 +@@ -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 ++# this or following included files. To override some configuration option, ++# write it before this block or include it before this file. ++# Please, see manual pages for update-crypto-policies(8) and sshd_config(5). ++Include /etc/crypto-policies/back-ends/opensshserver.config + diff --git a/openssh/openssh-7.8p1-UsePAM-warning.patch b/openssh/openssh-7.8p1-UsePAM-warning.patch index 8560c9f..a94419e 100644 --- a/openssh/openssh-7.8p1-UsePAM-warning.patch +++ b/openssh/openssh-7.8p1-UsePAM-warning.patch @@ -3,7 +3,7 @@ diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c +++ openssh-8.6p1/sshd.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); + cfg, &includes, NULL, rexeced_flag); + /* 'UsePAM no' is not supported in Fedora */ + if (! options.use_pam) diff --git a/openssh/openssh-7.8p1-role-mls.patch b/openssh/openssh-7.8p1-role-mls.patch index 48f9f10..4dc460a 100644 --- a/openssh/openssh-7.8p1-role-mls.patch +++ b/openssh/openssh-7.8p1-role-mls.patch @@ -93,7 +93,7 @@ diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c (r = sshbuf_put_cstring(b, authctxt->user)) != 0 || +#endif (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || - (r = sshbuf_put_cstring(b, "hostbased")) != 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 @@ -240,14 +240,14 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -1251,7 +1280,7 @@ monitor_valid_userblob(struct ssh *ssh, - { struct sshbuf *b; + struct sshkey *hostkey = NULL; const u_char *p; - char *userstyle, *cp; + char *userstyle, *s, *cp; size_t len; u_char type; - int r, fail = 0; + int hostbound = 0, r, fail = 0; @@ -1282,6 +1311,8 @@ monitor_valid_userblob(struct ssh *ssh, fail++; if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0) diff --git a/openssh/openssh-8.0p1-crypto-policies.patch b/openssh/openssh-8.0p1-crypto-policies.patch index 2ad438c..86c08db 100644 --- a/openssh/openssh-8.0p1-crypto-policies.patch +++ b/openssh/openssh-8.0p1-crypto-policies.patch @@ -1,13 +1,13 @@ -diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 ---- openssh-8.7p1/ssh_config.5.crypto-policies 2021-08-30 13:29:00.174292872 +0200 -+++ openssh-8.7p1/ssh_config.5 2021-08-30 13:31:32.009548808 +0200 -@@ -373,17 +373,13 @@ or +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh_config.5 openssh-9.3p1-patched/ssh_config.5 +--- openssh-9.3p1/ssh_config.5 2023-06-07 10:26:48.284590156 +0200 ++++ openssh-9.3p1-patched/ssh_config.5 2023-06-07 10:26:00.623052194 +0200 +@@ -378,17 +378,13 @@ causes no CNAMEs to be considered for canonicalization. This is the default behaviour. .It Cm CASignatureAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 which algorithms are allowed for signing of certificates @@ -24,13 +24,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set -@@ -445,20 +441,25 @@ If the option is set to +@@ -450,20 +446,25 @@ (the default), the check will not be executed. .It Cm Ciphers +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 ciphers allowed and their order of preference. @@ -54,7 +54,7 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .Pp The supported ciphers are: .Bd -literal -offset indent -@@ -474,13 +475,6 @@ aes256-gcm@openssh.com +@@ -479,13 +480,6 @@ chacha20-poly1305@openssh.com .Ed .Pp @@ -68,19 +68,19 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClearAllForwardings -@@ -874,6 +868,11 @@ command line will be passed untouched to +@@ -885,6 +879,11 @@ The default is .Dq no . .It Cm GSSAPIKexAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 The list of key exchange algorithms that are offered for GSSAPI key exchange. Possible values are .Bd -literal -offset 3n -@@ -886,10 +885,8 @@ gss-nistp256-sha256-, +@@ -897,10 +896,8 @@ gss-curve25519-sha256- .Ed .Pp @@ -92,13 +92,76 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .It Cm HashKnownHosts Indicates that .Xr ssh 1 -@@ -1219,29 +1216,25 @@ it may be zero or more of: +@@ -919,36 +916,25 @@ + but may be manually hashed using + .Xr ssh-keygen 1 . + .It Cm HostbasedAcceptedAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++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 signature algorithms that will be used for hostbased + authentication as a comma-separated list of patterns. + Alternately if the specified list begins with a + .Sq + + character, then the specified signature algorithms will be appended +-to the default set instead of replacing them. ++to the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified signature algorithms (including wildcards) +-will be removed from the default set instead of replacing them. ++will be removed from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified signature algorithms will be placed +-at the head of the default set. +-The default for this option is: +-.Bd -literal -offset 3n +-ssh-ed25519-cert-v01@openssh.com, +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-ed25519, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 +-.Ed ++at the head of the built-in openssh default set. + .Pp + The + .Fl Q +@@ -1001,6 +987,17 @@ + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q HostKeyAlgorithms . ++.Pp ++The proposed ++.Cm HostKeyAlgorithms ++during KEX are limited to the set of algorithms that is defined in ++.Cm PubkeyAcceptedAlgorithms ++and therefore they are indirectly affected by system-wide ++.Xr crypto_policies 7 . ++.Xr crypto_policies 7 can not handle the list of host key algorithms directly as doing so ++would break the order given by the ++.Pa known_hosts ++file. + .It Cm HostKeyAlias + Specifies an alias that should be used instead of the + real host name when looking up or saving the host key +@@ -1232,30 +1229,25 @@ and .Cm pam . .It Cm KexAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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. @@ -107,7 +170,7 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .Sq + -character, then the specified algorithms will be appended to the default set -instead of replacing them. -+character, then the specified algorithms will be appended to the built-in ++character, then the specified methods will be appended to the built-in +openssh default set instead of replacing them. If the specified list begins with a .Sq - @@ -120,6 +183,7 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 -default set. -The default is: -.Bd -literal -offset indent +-sntrup761x25519-sha512@openssh.com, -curve25519-sha256,curve25519-sha256@libssh.org, -ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, -diffie-hellman-group-exchange-sha256, @@ -131,13 +195,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .Pp The list of available key exchange algorithms may also be obtained using .Qq ssh -Q kex . -@@ -1351,37 +1344,33 @@ function, and all code in the +@@ -1365,37 +1357,33 @@ file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 MAC (message authentication code) algorithms @@ -178,13 +242,13 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm NoHostAuthenticationForLocalhost -@@ -1553,36 +1542,25 @@ instead of continuing to execute and pas +@@ -1567,39 +1555,31 @@ The default is .Cm no . .It Cm PubkeyAcceptedAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 signature algorithms that will be used for public key @@ -224,16 +288,33 @@ diff -up openssh-8.7p1/ssh_config.5.crypto-policies openssh-8.7p1/ssh_config.5 .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . -diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 ---- openssh-8.7p1/sshd_config.5.crypto-policies 2021-08-30 13:29:00.157292731 +0200 -+++ openssh-8.7p1/sshd_config.5 2021-08-30 13:32:16.263918533 +0200 -@@ -373,17 +373,13 @@ If the argument is ++.Pp ++This option affects also ++.Cm HostKeyAlgorithms + .It Cm PubkeyAuthentication + Specifies whether to try public key authentication. + The argument to this keyword must be +@@ -2265,7 +2245,9 @@ + This file must be world-readable. + .El + .Sh SEE ALSO +-.Xr ssh 1 ++.Xr ssh 1 , ++.Xr crypto-policies 7 , ++.Xr update-crypto-policies 8 + .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 @@ then no banner is displayed. By default, no banner is displayed. .It Cm CASignatureAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 which algorithms are allowed for signing of certificates @@ -250,13 +331,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 If the specified list begins with a .Sq + character, then the specified algorithms will be appended to the default set -@@ -450,20 +446,25 @@ The default is +@@ -525,20 +521,25 @@ indicating not to .Xr chroot 2 . .It Cm Ciphers +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 ciphers allowed. @@ -280,7 +361,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 .Pp The supported ciphers are: .Pp -@@ -490,13 +491,6 @@ aes256-gcm@openssh.com +@@ -565,13 +566,6 @@ chacha20-poly1305@openssh.com .El .Pp @@ -294,13 +375,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The list of available ciphers may also be obtained using .Qq ssh -Q cipher . .It Cm ClientAliveCountMax -@@ -685,21 +679,22 @@ For this to work +@@ -766,53 +760,43 @@ .Cm GSSAPIKeyExchange needs to be enabled in the server and also used by the client. .It Cm GSSAPIKexAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 The list of key exchange algorithms that are accepted by GSSAPI @@ -326,18 +407,27 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 -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 -@@ -799,26 +794,13 @@ is specified, the location of the socket - .Ev SSH_AUTH_SOCK - environment variable. - .It Cm HostKeyAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 host key signature algorithms - that the server offers. + Specifies the signature algorithms that will be accepted for hostbased + authentication as a list of comma-separated patterns. + Alternately if the specified list begins with a + .Sq + + character, then the specified signature algorithms will be appended to +-the default set instead of replacing them. ++the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified signature algorithms (including wildcards) +-will be removed from the default set instead of replacing them. ++will be removed from the built-in openssh default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified signature algorithms will be placed at +-the head of the default set. -The default for this option is: -.Bd -literal -offset 3n -ssh-ed25519-cert-v01@openssh.com, @@ -348,24 +438,54 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, -rsa-sha2-512-cert-v01@openssh.com, -rsa-sha2-256-cert-v01@openssh.com, --ssh-rsa-cert-v01@openssh.com, -ssh-ed25519, -ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, --rsa-sha2-512,rsa-sha2-256,ssh-rsa +-rsa-sha2-512,rsa-sha2-256 +-.Ed ++the head of the built-in openssh default set. + .Pp + The list of available signature algorithms may also be obtained using + .Qq ssh -Q HostbasedAcceptedAlgorithms . +@@ -879,25 +863,14 @@ + .Ev SSH_AUTH_SOCK + environment variable. + .It Cm HostKeyAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++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 host key signature algorithms + that the server offers. + The default for this option is: +-.Bd -literal -offset 3n +-ssh-ed25519-cert-v01@openssh.com, +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-ed25519, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ssh-ed25519@openssh.com, +-sk-ecdsa-sha2-nistp256@openssh.com, +-rsa-sha2-512,rsa-sha2-256 -.Ed -.Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q HostKeyAlgorithms . .It Cm IgnoreRhosts -@@ -965,20 +947,25 @@ Specifies whether to look at .k5login fi +@@ -1044,20 +1017,25 @@ The default is .Cm yes . .It Cm KexAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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. @@ -374,7 +494,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 .Sq + -character, then the specified algorithms will be appended to the default set -instead of replacing them. -+character, then the specified algorithms will be appended to the built-in ++character, then the specified methods will be appended to the built-in +openssh default set instead of replacing them. If the specified list begins with a .Sq - @@ -389,12 +509,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The supported algorithms are: .Pp .Bl -item -compact -offset indent -@@ -1010,15 +997,6 @@ ecdh-sha2-nistp521 +@@ -1089,16 +1067,6 @@ sntrup761x25519-sha512@openssh.com .El .Pp -The default is: -.Bd -literal -offset indent +-sntrup761x25519-sha512@openssh.com, -curve25519-sha256,curve25519-sha256@libssh.org, -ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, -diffie-hellman-group-exchange-sha256, @@ -405,13 +526,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The list of available key exchange algorithms may also be obtained using .Qq ssh -Q KexAlgorithms . .It Cm ListenAddress -@@ -1104,21 +1082,26 @@ function, and all code in the +@@ -1184,21 +1152,26 @@ file. This option is intended for debugging and no overrides are enabled by default. .It Cm MACs +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 MAC (message authentication code) algorithms. @@ -436,7 +557,7 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 .Pp The algorithms that contain .Qq -etm -@@ -1161,15 +1144,6 @@ umac-64-etm@openssh.com +@@ -1241,15 +1214,6 @@ umac-128-etm@openssh.com .El .Pp @@ -452,13 +573,13 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 The list of available MAC algorithms may also be obtained using .Qq ssh -Q mac . .It Cm Match -@@ -1548,37 +1522,25 @@ or equivalent.) +@@ -1633,36 +1597,25 @@ The default is .Cm yes . .It Cm PubkeyAcceptedAlgorithms +The default is handled system-wide by +.Xr crypto-policies 7 . -+To see the defaults and how to modify this default, see manual page ++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 signature algorithms that will be accepted for public key @@ -488,14 +609,24 @@ diff -up openssh-8.7p1/sshd_config.5.crypto-policies openssh-8.7p1/sshd_config.5 -sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, -rsa-sha2-512-cert-v01@openssh.com, -rsa-sha2-256-cert-v01@openssh.com, --ssh-rsa-cert-v01@openssh.com, -ssh-ed25519, -ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, -sk-ssh-ed25519@openssh.com, -sk-ecdsa-sha2-nistp256@openssh.com, --rsa-sha2-512,rsa-sha2-256,ssh-rsa +-rsa-sha2-512,rsa-sha2-256 -.Ed +built-in openssh default set. .Pp The list of available signature algorithms may also be obtained using .Qq ssh -Q PubkeyAcceptedAlgorithms . +@@ -2131,7 +2084,9 @@ + .El + .Sh SEE ALSO + .Xr sftp-server 8 , +-.Xr sshd 8 ++.Xr sshd 8 , ++.Xr crypto-policies 7 , ++.Xr update-crypto-policies 8 + .Sh AUTHORS + .An -nosplit + OpenSSH is a derivative of the original and free diff --git a/openssh/openssh-8.0p1-openssl-evp.patch b/openssh/openssh-8.0p1-openssl-evp.patch deleted file mode 100644 index ade0bbb..0000000 --- a/openssh/openssh-8.0p1-openssl-evp.patch +++ /dev/null @@ -1,720 +0,0 @@ -From ed7ec0cdf577ffbb0b15145340cf51596ca3eb89 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 14 May 2019 10:45:45 +0200 -Subject: [PATCH] Use high-level OpenSSL API for signatures - ---- - digest-openssl.c | 16 ++++ - digest.h | 6 ++ - ssh-dss.c | 65 ++++++++++------ - ssh-ecdsa.c | 69 ++++++++++------- - ssh-rsa.c | 193 +++++++++-------------------------------------- - sshkey.c | 77 +++++++++++++++++++ - sshkey.h | 4 + - 7 files changed, 221 insertions(+), 209 deletions(-) - -diff --git a/digest-openssl.c b/digest-openssl.c -index da7ed72bc..6a21d8adb 100644 ---- a/digest-openssl.c -+++ b/digest-openssl.c -@@ -63,6 +63,22 @@ const struct ssh_digest digests[] = { - { -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 --git a/digest.h b/digest.h -index 274574d0e..c7ceeb36f 100644 ---- a/digest.h -+++ b/digest.h -@@ -32,6 +32,12 @@ - struct sshbuf; - struct ssh_digest_ctx; - -+#ifdef WITH_OPENSSL -+#include -+/* Converts internal digest representation to the OpenSSL one */ -+const EVP_MD *ssh_digest_to_md(int digest_type); -+#endif -+ - /* Looks up a digest algorithm by name */ - int ssh_digest_alg_by_name(const char *name); - -diff --git a/ssh-dss.c b/ssh-dss.c -index a23c383dc..ea45e7275 100644 ---- a/ssh-dss.c -+++ b/ssh-dss.c -@@ -52,11 +52,15 @@ int - ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat) - { -+ 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) -@@ -67,17 +71,24 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - 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 ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; -+ 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); -@@ -110,7 +121,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - DSA_SIG_free(sig); - sshbuf_free(b); - return ret; -@@ -121,20 +132,20 @@ ssh_dss_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat) - { -+ EVP_PKEY *pkey = NULL; - DSA_SIG *sig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; -- u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; -- size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); -+ 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 || - signature == NULL || signaturelen == 0) - return SSH_ERR_INVALID_ARGUMENT; -- if (dlen == 0) -- return SSH_ERR_INTERNAL_ERROR; - - /* fetch signature */ - if ((b = sshbuf_from(signature, signaturelen)) == NULL) -@@ -176,25 +187,31 @@ ssh_dss_verify(const struct sshkey *key, - } - sig_r = sig_s = NULL; /* transferred */ - -- /* sha1 the data */ -- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, -- digest, sizeof(digest))) != 0) -+ if ((slen = i2d_DSA_SIG(sig, NULL)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; -- -- switch (DSA_do_verify(digest, dlen, sig, 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(sig, &psig)) == 0) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } - -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, datalen, -+ sigb, slen); -+ EVP_PKEY_free(pkey); -+ - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - DSA_SIG_free(sig); - BN_clear_free(sig_r); - BN_clear_free(sig_s); -diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c -index 599c7199d..b036796e8 100644 ---- a/ssh-ecdsa.c -+++ b/ssh-ecdsa.c -@@ -50,11 +50,13 @@ int - ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, u_int compat) - { -+ EVP_PKEY *pkey = NULL; - ECDSA_SIG *sig = NULL; -+ unsigned char *sigb = NULL; -+ const unsigned char *psig; - const BIGNUM *sig_r, *sig_s; - int hash_alg; -- u_char digest[SSH_DIGEST_MAX_LENGTH]; -- size_t len, dlen; -+ int len; - struct sshbuf *b = NULL, *bb = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; - -@@ -67,18 +69,24 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - sshkey_type_plain(key->type) != KEY_ECDSA) - return SSH_ERR_INVALID_ARGUMENT; - -- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || -- (dlen = ssh_digest_bytes(hash_alg)) == 0) -+ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) - return SSH_ERR_INTERNAL_ERROR; -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, -- digest, sizeof(digest))) != 0) -+ -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; -+ ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data, -+ datalen); -+ EVP_PKEY_free(pkey); -+ if (ret < 0) { - goto out; -+ } - -- if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) { -+ psig = sigb; -+ if ((sig = d2i_ECDSA_SIG(NULL, &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; -@@ -102,7 +110,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - sshbuf_free(b); - sshbuf_free(bb); - ECDSA_SIG_free(sig); -@@ -115,22 +123,21 @@ ssh_ecdsa_verify(const struct sshkey *key, - const u_char *signature, size_t signaturelen, - const u_char *data, size_t datalen, u_int compat) - { -+ EVP_PKEY *pkey = NULL; - ECDSA_SIG *sig = NULL; - BIGNUM *sig_r = NULL, *sig_s = NULL; -- int hash_alg; -- u_char digest[SSH_DIGEST_MAX_LENGTH]; -- size_t dlen; -+ 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 || - signature == NULL || signaturelen == 0) - return SSH_ERR_INVALID_ARGUMENT; - -- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || -- (dlen = ssh_digest_bytes(hash_alg)) == 0) -+ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) - return SSH_ERR_INTERNAL_ERROR; - - /* fetch signature */ -@@ -166,28 +173,36 @@ ssh_ecdsa_verify(const struct sshkey *key, - } - sig_r = sig_s = NULL; /* transferred */ - -- if (sshbuf_len(sigbuf) != 0) { -- ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; -+ /* Figure out the length */ -+ if ((len = i2d_ECDSA_SIG(sig, NULL)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ if ((sigb = malloc(len)) == NULL) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, -- digest, sizeof(digest))) != 0) -+ psig = sigb; -+ if ((len = i2d_ECDSA_SIG(sig, &psig)) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; -+ } - -- switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) { -- case 1: -- ret = 0; -- break; -- case 0: -- ret = SSH_ERR_SIGNATURE_INVALID; -+ if (sshbuf_len(sigbuf) != 0) { -+ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; -- default: -- ret = SSH_ERR_LIBCRYPTO_ERROR; -+ } -+ -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -+ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, sigb, len); -+ EVP_PKEY_free(pkey); - - out: -- explicit_bzero(digest, sizeof(digest)); -+ free(sigb); - sshbuf_free(sigbuf); - sshbuf_free(b); - ECDSA_SIG_free(sig); -diff --git a/ssh-rsa.c b/ssh-rsa.c -index 9b14f9a9a..8ef3a6aca 100644 ---- a/ssh-rsa.c -+++ b/ssh-rsa.c -@@ -37,7 +37,7 @@ - - #include "openbsd-compat/openssl-compat.h" - --static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); -+static int openssh_RSA_verify(int, const u_char *, size_t, u_char *, size_t, EVP_PKEY *); - - static const char * - rsa_hash_alg_ident(int hash_alg) -@@ -90,21 +90,6 @@ rsa_hash_id_from_keyname(const char *alg) - 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) - { -@@ -164,11 +149,10 @@ int - ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - const u_char *data, size_t datalen, const char *alg_ident) - { -- const BIGNUM *rsa_n; -- u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; -- size_t slen = 0; -- u_int dlen, 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) -@@ -180,33 +164,24 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - hash_alg = SSH_DIGEST_SHA1; - else - hash_alg = rsa_hash_id_from_keyname(alg_ident); -+ - 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 ((dlen = 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; -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) -+ return SSH_ERR_ALLOC_FAIL; -+ ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data, -+ datalen); -+ EVP_PKEY_free(pkey); -+ if (ret < 0) { - goto out; - } - -- if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { -- ret = SSH_ERR_LIBCRYPTO_ERROR; -- goto out; -- } - if (len < slen) { - size_t diff = slen - len; - memmove(sig + diff, sig, len); -@@ -215,6 +190,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - ret = SSH_ERR_INTERNAL_ERROR; - goto out; - } -+ - /* encode signature */ - if ((b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; -@@ -235,7 +211,6 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, - *lenp = len; - ret = 0; - out: -- explicit_bzero(digest, sizeof(digest)); - freezero(sig, slen); - sshbuf_free(b); - return ret; -@@ -246,10 +221,10 @@ ssh_rsa_verify(const struct sshkey *key, - const u_char *sig, size_t siglen, const u_char *data, size_t datalen, - const char *alg) - { -- const BIGNUM *rsa_n; -+ EVP_PKEY *pkey = NULL; - char *sigtype = NULL; - int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; -- size_t len = 0, diff, modlen, dlen; -+ size_t len = 0, diff, modlen; - struct sshbuf *b = NULL; - u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; - -@@ -257,8 +232,7 @@ ssh_rsa_verify(const struct sshkey *key, - 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) -@@ -310,16 +284,15 @@ ssh_rsa_verify(const struct sshkey *key, - explicit_bzero(sigblob, diff); - len = modlen; - } -- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { -- ret = SSH_ERR_INTERNAL_ERROR; -+ -+ if ((pkey = EVP_PKEY_new()) == NULL || -+ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) { -+ ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((ret = ssh_digest_memory(hash_alg, data, datalen, -- digest, sizeof(digest))) != 0) -- goto out; -+ ret = openssh_RSA_verify(hash_alg, data, datalen, sigblob, len, pkey); -+ EVP_PKEY_free(pkey); - -- ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, -- key->rsa); - out: - freezero(sigblob, len); - free(sigtype); -@@ -328,122 +301,26 @@ ssh_rsa_verify(const struct sshkey *key, - 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; -+ const RSA *rsa; -+ 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; -- } -+ rsa = EVP_PKEY_get0_RSA(pkey); - rsasize = RSA_size(rsa); - 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; - } - #endif /* WITH_OPENSSL */ -diff --git a/sshkey.c b/sshkey.c -index ad1957762..b95ed0b10 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -358,6 +358,83 @@ sshkey_type_plain(int type) - } - - #ifdef WITH_OPENSSL -+int -+sshkey_calculate_signature(EVP_PKEY *pkey, int hash_alg, u_char **sigp, -+ int *lenp, const u_char *data, size_t datalen) -+{ -+ EVP_MD_CTX *ctx = NULL; -+ u_char *sig = NULL; -+ int ret, slen, len; -+ -+ if (sigp == NULL || lenp == NULL) { -+ return SSH_ERR_INVALID_ARGUMENT; -+ } -+ -+ slen = EVP_PKEY_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_SignInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || -+ EVP_SignUpdate(ctx, data, datalen) <= 0 || -+ EVP_SignFinal(ctx, sig, &len, pkey) <= 0) { -+ 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_VerifyInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || -+ EVP_VerifyUpdate(ctx, data, datalen) <= 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto done; -+ } -+ ret = EVP_VerifyFinal(ctx, sigbuf, siglen, pkey); -+ switch (ret) { -+ case 1: -+ ret = 0; -+ break; -+ case 0: -+ ret = SSH_ERR_SIGNATURE_INVALID; -+ break; -+ default: -+ 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) -diff --git a/sshkey.h b/sshkey.h -index a91e60436..270901a87 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -179,6 +179,10 @@ const char *sshkey_ssh_name(const struct sshkey *); - const char *sshkey_ssh_name_plain(const struct sshkey *); - int sshkey_names_valid2(const char *, int); - char *sshkey_alg_list(int, int, int, char); -+int sshkey_calculate_signature(EVP_PKEY*, int, u_char **, -+ int *, const u_char *, size_t); -+int sshkey_verify_signature(EVP_PKEY *, int, const u_char *, -+ size_t, u_char *, int); - - int sshkey_from_blob(const u_char *, size_t, struct sshkey **); - int sshkey_fromb(struct sshbuf *, struct sshkey **); - diff --git a/openssh/openssh-8.7p1-CVE-2023-25136.patch b/openssh/openssh-8.7p1-CVE-2023-25136.patch deleted file mode 100644 index ca661ee..0000000 --- a/openssh/openssh-8.7p1-CVE-2023-25136.patch +++ /dev/null @@ -1,38 +0,0 @@ -diff --git a/compat.c b/compat.c -index 46dfe3a9c2e..478a9403eea 100644 ---- a/compat.c -+++ b/compat.c -@@ -190,26 +190,26 @@ compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop) - char * - compat_kex_proposal(struct ssh *ssh, char *p) - { -- char *cp = NULL; -+ char *cp = NULL, *cp2 = NULL; - - if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) - return xstrdup(p); - debug2_f("original KEX proposal: %s", p); - if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) -- if ((p = match_filter_denylist(p, -+ if ((cp = match_filter_denylist(p, - "curve25519-sha256@libssh.org")) == NULL) - fatal("match_filter_denylist failed"); - if ((ssh->compat & SSH_OLD_DHGEX) != 0) { -- cp = p; -- if ((p = match_filter_denylist(p, -+ if ((cp2 = match_filter_denylist(cp ? cp : p, - "diffie-hellman-group-exchange-sha256," - "diffie-hellman-group-exchange-sha1")) == NULL) - fatal("match_filter_denylist failed"); - free(cp); -+ cp = cp2; - } -- debug2_f("compat KEX proposal: %s", p); -- if (*p == '\0') -+ if (cp == NULL || *cp == '\0') - fatal("No supported key exchange algorithms found"); -- return p; -+ debug2_f("compat KEX proposal: %s", cp); -+ return cp; - } - diff --git a/openssh/openssh-8.7p1-evpgenkey.patch b/openssh/openssh-8.7p1-evpgenkey.patch deleted file mode 100644 index 1af9b49..0000000 --- a/openssh/openssh-8.7p1-evpgenkey.patch +++ /dev/null @@ -1,110 +0,0 @@ -diff -up openssh-8.7p1/sshkey.c.evpgenrsa openssh-8.7p1/sshkey.c ---- openssh-8.7p1/sshkey.c.evpgenrsa 2022-06-30 15:14:58.200518353 +0200 -+++ openssh-8.7p1/sshkey.c 2022-06-30 15:24:31.499641196 +0200 -@@ -1657,7 +1657,8 @@ sshkey_cert_type(const struct sshkey *k) - static int - rsa_generate_private_key(u_int bits, RSA **rsap) - { -- RSA *private = NULL; -+ EVP_PKEY_CTX *ctx = NULL; -+ EVP_PKEY *res = NULL; - BIGNUM *f4 = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; - -@@ -1667,20 +1668,42 @@ rsa_generate_private_key(u_int bits, RSA - bits > SSHBUF_MAX_BIGNUM * 8) - return SSH_ERR_KEY_LENGTH; - *rsap = NULL; -- 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*/ -+ *rsap = EVP_PKEY_get1_RSA(res); -+ if (*rsap) { -+ ret = 0; -+ } else { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- *rsap = private; -- private = NULL; -- ret = 0; - out: -- RSA_free(private); -+ EVP_PKEY_CTX_free(ctx); -+ EVP_PKEY_free(res); - BN_free(f4); - return ret; - } -@@ -1820,7 +1820,8 @@ sshkey_ecdsa_key_to_nid(EC_KEY *k) - static int - ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap) - { -- EC_KEY *private; -+ EVP_PKEY_CTX *ctx = NULL; -+ EVP_PKEY *res = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; - - if (nid == NULL || ecdsap == NULL) -@@ -1828,20 +1829,29 @@ ecdsa_generate_private_key(u_int bits, i - if ((*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1) - return SSH_ERR_KEY_LENGTH; - *ecdsap = NULL; -- if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) { -+ -+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if (EC_KEY_generate_key(private) != 1) { -+ -+ if (EVP_PKEY_keygen_init(ctx) <= 0 || EVP_PKEY_CTX_set_group_name(ctx, OBJ_nid2sn(*nid)) <= 0 -+ || 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*/ -+ *ecdsap = EVP_PKEY_get1_EC_KEY(res); -+ if (*ecdsap) { -+ EC_KEY_set_asn1_flag(*ecdsap, OPENSSL_EC_NAMED_CURVE); -+ ret = 0; -+ } else { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE); -- *ecdsap = private; -- private = NULL; -- ret = 0; - out: -- EC_KEY_free(private); -+ EVP_PKEY_CTX_free(ctx); -+ EVP_PKEY_free(res); - return ret; - } - # endif /* OPENSSL_HAS_ECC */ diff --git a/openssh/openssh-8.7p1-gssapi-auth.patch b/openssh/openssh-8.7p1-gssapi-auth.patch deleted file mode 100644 index 6908cad..0000000 --- a/openssh/openssh-8.7p1-gssapi-auth.patch +++ /dev/null @@ -1,20 +0,0 @@ -diff --color -rup a/monitor.c b/monitor.c ---- a/monitor.c 2022-07-11 15:11:28.146863144 +0200 -+++ b/monitor.c 2022-07-11 15:15:35.726655877 +0200 -@@ -376,8 +376,15 @@ monitor_child_preauth(struct ssh *ssh, s - if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { - auth_log(ssh, authenticated, partial, - auth_method, auth_submethod); -- if (!partial && !authenticated) -+ if (!partial && !authenticated) { -+#ifdef GSSAPI -+ /* If gssapi-with-mic failed, MONITOR_REQ_GSSCHECKMIC is disabled. -+ * We have to reenable it to try again for gssapi-keyex */ -+ if (strcmp(auth_method, "gssapi-with-mic") == 0 && options.gss_keyex) -+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); -+#endif - authctxt->failures++; -+ } - if (authenticated || partial) { - auth2_update_session_info(authctxt, - auth_method, auth_submethod); diff --git a/openssh/openssh-8.7p1-host-based-auth.patch b/openssh/openssh-8.7p1-host-based-auth.patch deleted file mode 100644 index 23efe91..0000000 --- a/openssh/openssh-8.7p1-host-based-auth.patch +++ /dev/null @@ -1,151 +0,0 @@ -diff --color -rup a/sshconnect2.c b/sshconnect2.c ---- a/sshconnect2.c 2022-07-11 17:00:02.618575727 +0200 -+++ b/sshconnect2.c 2022-07-11 17:03:05.096085690 +0200 -@@ -2288,9 +2288,9 @@ userauth_hostbased(struct ssh *ssh) - if (authctxt->sensitive->keys[i] == NULL || - authctxt->sensitive->keys[i]->type == KEY_UNSPEC) - continue; -- if (match_pattern_list( -+ if (!sshkey_match_keyname_to_sigalgs( - sshkey_ssh_name(authctxt->sensitive->keys[i]), -- authctxt->active_ktype, 0) != 1) -+ authctxt->active_ktype)) - continue; - /* we take and free the key */ - private = authctxt->sensitive->keys[i]; -@@ -2316,7 +2316,8 @@ userauth_hostbased(struct ssh *ssh) - error_f("sshkey_fingerprint failed"); - goto out; - } -- debug_f("trying hostkey %s %s", sshkey_ssh_name(private), fp); -+ debug_f("trying hostkey %s %s using sigalg %s", -+ sshkey_ssh_name(private), fp, authctxt->active_ktype); - - /* figure out a name for the client host */ - lname = get_local_name(ssh_packet_get_connection_in(ssh)); -diff --color -rup a/sshkey.c b/sshkey.c ---- a/sshkey.c 2022-07-11 17:00:02.609575554 +0200 -+++ b/sshkey.c 2022-07-11 17:12:30.905976443 +0200 -@@ -252,6 +252,29 @@ sshkey_ecdsa_nid_from_name(const char *n - return -1; - } - -+int -+sshkey_match_keyname_to_sigalgs(const char *keyname, const char *sigalgs) -+{ -+ int ktype; -+ -+ if (sigalgs == NULL || *sigalgs == '\0' || -+ (ktype = sshkey_type_from_name(keyname)) == KEY_UNSPEC) -+ return 0; -+ else if (ktype == KEY_RSA) { -+ return match_pattern_list("ssh-rsa", sigalgs, 0) == 1 || -+ match_pattern_list("rsa-sha2-256", sigalgs, 0) == 1 || -+ match_pattern_list("rsa-sha2-512", sigalgs, 0) == 1; -+ } else if (ktype == KEY_RSA_CERT) { -+ return match_pattern_list("ssh-rsa-cert-v01@openssh.com", -+ sigalgs, 0) == 1 || -+ match_pattern_list("rsa-sha2-256-cert-v01@openssh.com", -+ sigalgs, 0) == 1 || -+ match_pattern_list("rsa-sha2-512-cert-v01@openssh.com", -+ sigalgs, 0) == 1; -+ } else -+ return match_pattern_list(keyname, sigalgs, 0) == 1; -+} -+ - char * - sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) - { -diff --color -rup a/sshkey.h b/sshkey.h ---- a/sshkey.h 2022-07-11 17:00:02.603575438 +0200 -+++ b/sshkey.h 2022-07-11 17:13:01.052556879 +0200 -@@ -194,6 +194,10 @@ int sshkey_is_cert(const struct sshkey - int sshkey_is_sk(const struct sshkey *); - int sshkey_type_is_cert(int); - int sshkey_type_plain(int); -+ -+/* Returns non-zero if key name match sigalgs pattern list. (handles RSA) */ -+int sshkey_match_keyname_to_sigalgs(const char *, const char *); -+ - int sshkey_to_certified(struct sshkey *); - int sshkey_drop_cert(struct sshkey *); - int sshkey_cert_copy(const struct sshkey *, struct sshkey *); -diff --color -rup a/ssh-keysign.c b/ssh-keysign.c ---- a/ssh-keysign.c 2021-08-20 06:03:49.000000000 +0200 -+++ b/ssh-keysign.c 2022-07-11 17:00:23.306973667 +0200 -@@ -62,7 +62,7 @@ - extern char *__progname; - - static int --valid_request(struct passwd *pw, char *host, struct sshkey **ret, -+valid_request(struct passwd *pw, char *host, struct sshkey **ret, char **pkalgp, - u_char *data, size_t datalen) - { - struct sshbuf *b; -@@ -75,6 +75,8 @@ valid_request(struct passwd *pw, char *h - - if (ret != NULL) - *ret = NULL; -+ if (pkalgp != NULL) -+ *pkalgp = NULL; - fail = 0; - - if ((b = sshbuf_from(data, datalen)) == NULL) -@@ -122,8 +124,6 @@ valid_request(struct passwd *pw, char *h - fail++; - } else if (key->type != pktype) - fail++; -- free(pkalg); -- free(pkblob); - - /* client host name, handle trailing dot */ - if ((r = sshbuf_get_cstring(b, &p, &len)) != 0) -@@ -154,8 +154,19 @@ valid_request(struct passwd *pw, char *h - - if (fail) - sshkey_free(key); -- else if (ret != NULL) -- *ret = key; -+ else { -+ if (ret != NULL) { -+ *ret = key; -+ key = NULL; -+ } -+ if (pkalgp != NULL) { -+ *pkalgp = pkalg; -+ pkalg = NULL; -+ } -+ } -+ sshkey_free(key); -+ free(pkalg); -+ free(pkblob); - - return (fail ? -1 : 0); - } -@@ -170,7 +181,7 @@ main(int argc, char **argv) - struct passwd *pw; - int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd; - u_char *signature, *data, rver; -- char *host, *fp; -+ char *host, *fp, *pkalg; - size_t slen, dlen; - - if (pledge("stdio rpath getpw dns id", NULL) != 0) -@@ -258,7 +269,7 @@ main(int argc, char **argv) - - if ((r = sshbuf_get_string(b, &data, &dlen)) != 0) - fatal_r(r, "%s: buffer error", __progname); -- if (valid_request(pw, host, &key, data, dlen) < 0) -+ if (valid_request(pw, host, &key, &pkalg, data, dlen) < 0) - fatal("%s: not a valid request", __progname); - free(host); - -@@ -279,7 +290,7 @@ main(int argc, char **argv) - } - - if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, -- NULL, NULL, NULL, 0)) != 0) -+ pkalg, NULL, NULL, 0)) != 0) - fatal_r(r, "%s: sshkey_sign failed", __progname); - free(data); - diff --git a/openssh/openssh-8.7p1-ibmca.patch b/openssh/openssh-8.7p1-ibmca.patch index c9c12ee..88914bf 100644 --- a/openssh/openssh-8.7p1-ibmca.patch +++ b/openssh/openssh-8.7p1-ibmca.patch @@ -4,9 +4,8 @@ #include "includes.h" --#ifndef HAVE_CLOSEFROM -+#if (!defined HAVE_CLOSEFROM) || (defined __s390__) +-#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) ++#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) || (defined __s390__) #include - #include - + #include diff --git a/openssh/openssh-8.7p1-mem-leak.patch b/openssh/openssh-8.7p1-mem-leak.patch deleted file mode 100644 index 8c9ac80..0000000 --- a/openssh/openssh-8.7p1-mem-leak.patch +++ /dev/null @@ -1,156 +0,0 @@ -diff --color -rup a/compat.c b/compat.c ---- a/compat.c 2021-08-20 06:03:49.000000000 +0200 -+++ b/compat.c 2022-07-14 17:39:23.770268440 +0200 -@@ -157,11 +157,12 @@ compat_banner(struct ssh *ssh, const cha - debug_f("no match: %s", version); - } - -+/* Always returns pointer to allocated memory, caller must free. */ - char * - compat_cipher_proposal(struct ssh *ssh, char *cipher_prop) - { - if (!(ssh->compat & SSH_BUG_BIGENDIANAES)) -- return cipher_prop; -+ return xstrdup(cipher_prop); - debug2_f("original cipher proposal: %s", cipher_prop); - if ((cipher_prop = match_filter_denylist(cipher_prop, "aes*")) == NULL) - fatal("match_filter_denylist failed"); -@@ -171,11 +172,12 @@ compat_cipher_proposal(struct ssh *ssh, - return cipher_prop; - } - -+/* Always returns pointer to allocated memory, caller must free. */ - char * - compat_pkalg_proposal(struct ssh *ssh, char *pkalg_prop) - { - if (!(ssh->compat & SSH_BUG_RSASIGMD5)) -- return pkalg_prop; -+ return xstrdup(pkalg_prop); - debug2_f("original public key proposal: %s", pkalg_prop); - if ((pkalg_prop = match_filter_denylist(pkalg_prop, "ssh-rsa")) == NULL) - fatal("match_filter_denylist failed"); -@@ -185,21 +187,26 @@ compat_pkalg_proposal(struct ssh *ssh, c - return pkalg_prop; - } - -+/* Always returns pointer to allocated memory, caller must free. */ - char * - compat_kex_proposal(struct ssh *ssh, char *p) - { -+ char *cp = NULL; -+ - if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0) -- return p; -+ return xstrdup(p); - debug2_f("original KEX proposal: %s", p); - if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0) - if ((p = match_filter_denylist(p, - "curve25519-sha256@libssh.org")) == NULL) - fatal("match_filter_denylist failed"); - if ((ssh->compat & SSH_OLD_DHGEX) != 0) { -+ cp = p; - if ((p = match_filter_denylist(p, - "diffie-hellman-group-exchange-sha256," - "diffie-hellman-group-exchange-sha1")) == NULL) - fatal("match_filter_denylist failed"); -+ free(cp); - } - debug2_f("compat KEX proposal: %s", p); - if (*p == '\0') -diff --color -rup a/sshconnect2.c b/sshconnect2.c ---- a/sshconnect2.c 2022-07-14 17:38:43.241496549 +0200 -+++ b/sshconnect2.c 2022-07-14 17:39:23.772268479 +0200 -@@ -222,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, st - { - char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; - char *s, *all_key; -+ char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; - int r, use_known_hosts_order = 0; - - #if defined(GSSAPI) && defined(WITH_OPENSSL) -@@ -252,10 +253,9 @@ ssh_kex2(struct ssh *ssh, char *host, st - - if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) - fatal_f("kex_names_cat"); -- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, s); -+ myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, s); - myproposal[PROPOSAL_ENC_ALGS_CTOS] = -- compat_cipher_proposal(ssh, options.ciphers); -- myproposal[PROPOSAL_ENC_ALGS_STOC] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc = - compat_cipher_proposal(ssh, options.ciphers); - myproposal[PROPOSAL_COMP_ALGS_CTOS] = - myproposal[PROPOSAL_COMP_ALGS_STOC] = -@@ -264,12 +264,12 @@ ssh_kex2(struct ssh *ssh, char *host, st - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; - if (use_known_hosts_order) { - /* Query known_hosts and prefer algorithms that appear there */ -- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = - compat_pkalg_proposal(ssh, - order_hostkeyalgs(host, hostaddr, port, cinfo)); - } else { - /* Use specified HostkeyAlgorithms exactly */ -- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = - compat_pkalg_proposal(ssh, options.hostkeyalgorithms); - } - -@@ -383,6 +383,10 @@ ssh_kex2(struct ssh *ssh, char *host, st - (r = ssh_packet_write_wait(ssh)) != 0) - fatal_fr(r, "send packet"); - #endif -+ /* Free only parts of proposal that were dynamically allocated here. */ -+ free(prop_kex); -+ free(prop_enc); -+ free(prop_hostkey); - } - - /* -diff --color -rup a/sshd.c b/sshd.c ---- a/sshd.c 2022-07-14 17:38:43.242496568 +0200 -+++ b/sshd.c 2022-07-14 17:42:07.616388978 +0200 -@@ -2493,14 +2493,15 @@ do_ssh2_kex(struct ssh *ssh) - { - char *myproposal[PROPOSAL_MAX] = { KEX_SERVER }; - struct kex *kex; -+ char *hostkey_types = NULL; -+ char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; - int r; - -- myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, -+ myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, - options.kex_algorithms); -- myproposal[PROPOSAL_ENC_ALGS_CTOS] = compat_cipher_proposal(ssh, -- options.ciphers); -- myproposal[PROPOSAL_ENC_ALGS_STOC] = compat_cipher_proposal(ssh, -- options.ciphers); -+ myproposal[PROPOSAL_ENC_ALGS_CTOS] = -+ myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc = -+ compat_cipher_proposal(ssh, options.ciphers); - myproposal[PROPOSAL_MAC_ALGS_CTOS] = - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; - -@@ -2513,8 +2514,10 @@ do_ssh2_kex(struct ssh *ssh) - ssh_packet_set_rekey_limits(ssh, options.rekey_limit, - options.rekey_interval); - -- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( -- ssh, list_hostkey_types()); -+ hostkey_types = list_hostkey_types(); -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = -+ compat_pkalg_proposal(ssh, hostkey_types); -+ free(hostkey_types); - - #if defined(GSSAPI) && defined(WITH_OPENSSL) - { -@@ -2606,6 +2609,9 @@ do_ssh2_kex(struct ssh *ssh) - (r = ssh_packet_write_wait(ssh)) != 0) - fatal_fr(r, "send test"); - #endif -+ free(prop_kex); -+ free(prop_enc); -+ free(prop_hostkey); - debug("KEX done"); - } - diff --git a/openssh/openssh-8.7p1-minimize-sha1-use.patch b/openssh/openssh-8.7p1-minimize-sha1-use.patch deleted file mode 100644 index fc517da..0000000 --- a/openssh/openssh-8.7p1-minimize-sha1-use.patch +++ /dev/null @@ -1,207 +0,0 @@ -diff --color -ru a/clientloop.c b/clientloop.c ---- a/clientloop.c 2022-06-29 16:35:06.677597259 +0200 -+++ b/clientloop.c 2022-06-29 16:40:29.737926205 +0200 -@@ -116,6 +116,9 @@ - #include "ssh-gss.h" - #endif - -+/* Permitted RSA signature algorithms for UpdateHostkeys proofs */ -+#define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" -+ - /* import options */ - extern Options options; - -@@ -2110,8 +2113,10 @@ - struct hostkeys_update_ctx *ctx = (struct hostkeys_update_ctx *)_ctx; - size_t i, ndone; - struct sshbuf *signdata; -- int r, kexsigtype, use_kexsigtype; -+ int r, plaintype; - const u_char *sig; -+ const char *rsa_kexalg = NULL; -+ char *alg = NULL; - size_t siglen; - - if (ctx->nnew == 0) -@@ -2122,9 +2127,9 @@ - hostkeys_update_ctx_free(ctx); - return; - } -- kexsigtype = sshkey_type_plain( -- sshkey_type_from_name(ssh->kex->hostkey_alg)); -- -+ if (sshkey_type_plain(sshkey_type_from_name( -+ ssh->kex->hostkey_alg)) == KEY_RSA) -+ rsa_kexalg = ssh->kex->hostkey_alg; - if ((signdata = sshbuf_new()) == NULL) - fatal_f("sshbuf_new failed"); - /* -@@ -2135,6 +2140,7 @@ - for (ndone = i = 0; i < ctx->nkeys; i++) { - if (ctx->keys_match[i]) - continue; -+ plaintype = sshkey_type_plain(ctx->keys[i]->type); - /* Prepare data to be signed: session ID, unique string, key */ - sshbuf_reset(signdata); - if ( (r = sshbuf_put_cstring(signdata, -@@ -2148,19 +2154,33 @@ - error_fr(r, "parse sig"); - goto out; - } -+ if ((r = sshkey_get_sigtype(sig, siglen, &alg)) != 0) { -+ error_fr(r, "server gave unintelligible signature " -+ "for %s key %zu", sshkey_type(ctx->keys[i]), i); -+ goto out; -+ } - /* -- * For RSA keys, prefer to use the signature type negotiated -- * during KEX to the default (SHA1). -+ * Special case for RSA keys: if a RSA hostkey was negotiated, -+ * then use its signature type for verification of RSA hostkey -+ * proofs. Otherwise, accept only RSA-SHA256/512 signatures. - */ -- use_kexsigtype = kexsigtype == KEY_RSA && -- sshkey_type_plain(ctx->keys[i]->type) == KEY_RSA; -- debug3_f("verify %s key %zu using %s sigalg", -- sshkey_type(ctx->keys[i]), i, -- use_kexsigtype ? ssh->kex->hostkey_alg : "default"); -+ if (plaintype == KEY_RSA && rsa_kexalg == NULL && -+ match_pattern_list(alg, HOSTKEY_PROOF_RSA_ALGS, 0) != 1) { -+ debug_f("server used untrusted RSA signature algorithm " -+ "%s for key %zu, disregarding", alg, i); -+ free(alg); -+ /* zap the key from the list */ -+ sshkey_free(ctx->keys[i]); -+ ctx->keys[i] = NULL; -+ ndone++; -+ continue; -+ } -+ debug3_f("verify %s key %zu using sigalg %s", -+ sshkey_type(ctx->keys[i]), i, alg); -+ free(alg); - if ((r = sshkey_verify(ctx->keys[i], sig, siglen, - sshbuf_ptr(signdata), sshbuf_len(signdata), -- use_kexsigtype ? ssh->kex->hostkey_alg : NULL, 0, -- NULL)) != 0) { -+ plaintype == KEY_RSA ? rsa_kexalg : NULL, 0, NULL)) != 0) { - error_fr(r, "server gave bad signature for %s key %zu", - sshkey_type(ctx->keys[i]), i); - goto out; -diff --git a/hostfile.c b/hostfile.c -index a035b381..bd49e3ac 100644 ---- a/hostfile.c -+++ b/hostfile.c -@@ -642,7 +642,7 @@ hostfile_replace_entries(const char *filename, const char *host, const char *ip, - /* Re-add the requested keys */ - want = HKF_MATCH_HOST | (ip == NULL ? 0 : HKF_MATCH_IP); - for (i = 0; i < nkeys; i++) { -- if ((want & ctx.match_keys[i]) == want) -+ if (keys[i] == NULL || (want & ctx.match_keys[i]) == want) - continue; - if ((fp = sshkey_fingerprint(keys[i], hash_alg, - SSH_FP_DEFAULT)) == NULL) { -diff --color -ru a/kex.c b/kex.c ---- a/kex.c 2022-06-29 16:35:06.775599179 +0200 -+++ b/kex.c 2022-06-29 16:42:00.839710940 +0200 -@@ -959,6 +959,18 @@ - return (1); - } - -+/* returns non-zero if proposal contains any algorithm from algs */ -+static int -+has_any_alg(const char *proposal, const char *algs) -+{ -+ char *cp; -+ -+ if ((cp = match_list(proposal, algs, NULL)) == NULL) -+ return 0; -+ free(cp); -+ return 1; -+} -+ - static int - kex_choose_conf(struct ssh *ssh) - { -@@ -994,6 +1006,16 @@ - free(ext); - } - -+ /* Check whether client supports rsa-sha2 algorithms */ -+ if (kex->server && (kex->flags & KEX_INITIAL)) { -+ if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "rsa-sha2-256,rsa-sha2-256-cert-v01@openssh.com")) -+ kex->flags |= KEX_RSA_SHA2_256_SUPPORTED; -+ if (has_any_alg(peer[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "rsa-sha2-512,rsa-sha2-512-cert-v01@openssh.com")) -+ kex->flags |= KEX_RSA_SHA2_512_SUPPORTED; -+ } -+ - /* Algorithm Negotiation */ - if ((r = choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], - sprop[PROPOSAL_KEX_ALGS])) != 0) { -diff --color -ru a/kex.h b/kex.h ---- a/kex.h 2022-06-29 16:35:06.766599003 +0200 -+++ b/kex.h 2022-06-29 16:42:24.199168567 +0200 -@@ -116,6 +116,8 @@ - - #define KEX_INIT_SENT 0x0001 - #define KEX_INITIAL 0x0002 -+#define KEX_RSA_SHA2_256_SUPPORTED 0x0008 /* only set in server for now */ -+#define KEX_RSA_SHA2_512_SUPPORTED 0x0010 /* only set in server for now */ - - struct sshenc { - char *name; -diff --color -ru a/serverloop.c b/serverloop.c ---- a/serverloop.c 2021-08-20 06:03:49.000000000 +0200 -+++ b/serverloop.c 2022-06-29 16:45:05.902336428 +0200 -@@ -684,16 +684,18 @@ - struct sshbuf *resp = NULL; - struct sshbuf *sigbuf = NULL; - struct sshkey *key = NULL, *key_pub = NULL, *key_prv = NULL; -- int r, ndx, kexsigtype, use_kexsigtype, success = 0; -+ int r, ndx, success = 0; - const u_char *blob; -+ const char *sigalg, *kex_rsa_sigalg = NULL; - u_char *sig = 0; - size_t blen, slen; - - if ((resp = sshbuf_new()) == NULL || (sigbuf = sshbuf_new()) == NULL) - fatal_f("sshbuf_new"); - -- kexsigtype = sshkey_type_plain( -- sshkey_type_from_name(ssh->kex->hostkey_alg)); -+ if (sshkey_type_plain(sshkey_type_from_name( -+ ssh->kex->hostkey_alg)) == KEY_RSA) -+ kex_rsa_sigalg = ssh->kex->hostkey_alg; - while (ssh_packet_remaining(ssh) > 0) { - sshkey_free(key); - key = NULL; -@@ -726,16 +728,24 @@ - * For RSA keys, prefer to use the signature type negotiated - * during KEX to the default (SHA1). - */ -- use_kexsigtype = kexsigtype == KEY_RSA && -- sshkey_type_plain(key->type) == KEY_RSA; -+ sigalg = NULL; -+ if (sshkey_type_plain(key->type) == KEY_RSA) { -+ if (kex_rsa_sigalg != NULL) -+ sigalg = kex_rsa_sigalg; -+ else if (ssh->kex->flags & KEX_RSA_SHA2_512_SUPPORTED) -+ sigalg = "rsa-sha2-512"; -+ else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED) -+ sigalg = "rsa-sha2-256"; -+ } -+ debug3_f("sign %s key (index %d) using sigalg %s", -+ sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg); - if ((r = sshbuf_put_cstring(sigbuf, - "hostkeys-prove-00@openssh.com")) != 0 || - (r = sshbuf_put_stringb(sigbuf, - ssh->kex->session_id)) != 0 || - (r = sshkey_puts(key, sigbuf)) != 0 || - (r = ssh->kex->sign(ssh, key_prv, key_pub, &sig, &slen, -- sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), -- use_kexsigtype ? ssh->kex->hostkey_alg : NULL)) != 0 || -+ sshbuf_ptr(sigbuf), sshbuf_len(sigbuf), sigalg)) != 0 || - (r = sshbuf_put_string(resp, sig, slen)) != 0) { - error_fr(r, "assemble signature"); - goto out; diff --git a/openssh/openssh-8.7p1-minrsabits.patch b/openssh/openssh-8.7p1-minrsabits.patch index b53c383..2ed59a3 100644 --- a/openssh/openssh-8.7p1-minrsabits.patch +++ b/openssh/openssh-8.7p1-minrsabits.patch @@ -1,446 +1,24 @@ -diff --git a/auth2-hostbased.c b/auth2-hostbased.c -index 36b9d2f5..6b517db4 100644 ---- a/auth2-hostbased.c -+++ b/auth2-hostbased.c -@@ -119,6 +119,11 @@ userauth_hostbased(struct ssh *ssh, const char *method) - "(null)" : key->cert->signature_type); - goto done; - } -+ if ((r = sshkey_check_rsa_length(key, -+ options.required_rsa_size)) != 0) { -+ logit_r(r, "refusing %s key", sshkey_type(key)); -+ goto done; -+ } - - if (!authctxt->valid || authctxt->user == NULL) { - debug2_f("disabled because of invalid user"); -diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index 962fd342..5d59febc 100644 ---- a/auth2-pubkey.c -+++ b/auth2-pubkey.c -@@ -175,6 +175,11 @@ userauth_pubkey(struct ssh *ssh, const char *method) - "(null)" : key->cert->signature_type); - goto done; - } -+ if ((r = sshkey_check_rsa_length(key, -+ options.required_rsa_size)) != 0) { -+ logit_r(r, "refusing %s key", sshkey_type(key)); -+ goto done; -+ } - key_s = format_key(key); - if (sshkey_is_cert(key)) - ca_s = format_key(key->cert->signature_key); diff --git a/readconf.c b/readconf.c index 7f26c680..42be690b 100644 --- a/readconf.c +++ b/readconf.c -@@ -174,7 +174,7 @@ typedef enum { - oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, - oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms, - oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump, -- oSecurityKeyProvider, oKnownHostsCommand, -+ oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize, - oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported - } OpCodes; - -@@ -320,6 +320,8 @@ static struct { - { "proxyjump", oProxyJump }, +@@ -320,6 +320,7 @@ static struct { { "securitykeyprovider", oSecurityKeyProvider }, { "knownhostscommand", oKnownHostsCommand }, -+ { "requiredrsasize", oRequiredRSASize }, + { "requiredrsasize", oRequiredRSASize }, + { "rsaminsize", oRequiredRSASize }, /* alias */ + { "enableescapecommandline", oEnableEscapeCommandline }, { NULL, oBadOption } - }; -@@ -2176,6 +2177,10 @@ parse_pubkey_algos: - *charptr = xstrdup(arg); - break; - -+ case oRequiredRSASize: -+ intptr = &options->required_rsa_size; -+ goto parse_int; -+ - case oDeprecated: - debug("%s line %d: Deprecated option \"%s\"", - filename, linenum, keyword); -@@ -2423,6 +2428,7 @@ initialize_options(Options * options) - options->hostbased_accepted_algos = NULL; - options->pubkey_accepted_algos = NULL; - options->known_hosts_command = NULL; -+ options->required_rsa_size = -1; - } - - /* -@@ -2619,6 +2625,8 @@ fill_default_options(Options * options) - if (options->sk_provider == NULL) - options->sk_provider = xstrdup("$SSH_SK_PROVIDER"); - #endif -+ if (options->required_rsa_size == -1) -+ options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; - - /* Expand KEX name lists */ - all_cipher = cipher_alg_list(',', 0); -@@ -3308,6 +3316,7 @@ dump_client_config(Options *o, const char *host) - dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts); - dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max); - dump_cfg_int(oServerAliveInterval, o->server_alive_interval); -+ dump_cfg_int(oRequiredRSASize, o->required_rsa_size); - - /* String options */ - dump_cfg_string(oBindAddress, o->bind_address); -diff --git a/readconf.h b/readconf.h -index f647bd42..ffb5ec4f 100644 ---- a/readconf.h -+++ b/readconf.h -@@ -176,6 +176,8 @@ typedef struct { - - char *known_hosts_command; - -+ int required_rsa_size; /* minimum size of RSA keys */ -+ - char *ignored_unknown; /* Pattern list of unknown tokens to ignore */ - } Options; - diff --git a/servconf.c b/servconf.c index 29df0463..423772b1 100644 --- a/servconf.c +++ b/servconf.c -@@ -195,6 +195,7 @@ initialize_server_options(ServerOptions *options) - options->fingerprint_hash = -1; - options->disable_forwarding = -1; - options->expose_userauth_info = -1; -+ options->required_rsa_size = -1; - } - - /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ -@@ -441,6 +442,8 @@ fill_default_server_options(ServerOptions *options) - options->expose_userauth_info = 0; - if (options->sk_provider == NULL) - options->sk_provider = xstrdup("internal"); -+ if (options->required_rsa_size == -1) -+ options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE; - - assemble_algorithms(options); - -@@ -517,6 +520,7 @@ typedef enum { - sStreamLocalBindMask, sStreamLocalBindUnlink, - sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, - sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, -+ sRequiredRSASize, - sDeprecated, sIgnore, sUnsupported - } ServerOpCodes; - -@@ -676,6 +680,8 @@ static struct { - { "rdomain", sRDomain, SSHCFG_ALL }, +@@ -676,6 +680,7 @@ static struct { { "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 }, { NULL, sBadOption, 0 } - }; - -@@ -2438,6 +2443,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, - *charptr = xstrdup(arg); - break; - -+ case sRequiredRSASize: -+ intptr = &options->required_rsa_size; -+ goto parse_int; -+ - case sDeprecated: - case sIgnore: - case sUnsupported: -@@ -2610,6 +2619,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth) - M_CP_INTOPT(rekey_limit); - M_CP_INTOPT(rekey_interval); - M_CP_INTOPT(log_level); -+ M_CP_INTOPT(required_rsa_size); - - /* - * The bind_mask is a mode_t that may be unsigned, so we can't use -@@ -2874,6 +2884,7 @@ dump_config(ServerOptions *o) - dump_cfg_int(sMaxSessions, o->max_sessions); - dump_cfg_int(sClientAliveInterval, o->client_alive_interval); - dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max); -+ dump_cfg_int(sRequiredRSASize, o->required_rsa_size); - dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask); - - /* formatted integer arguments */ -diff --git a/servconf.h b/servconf.h -index 8a04463e..9346155c 100644 ---- a/servconf.h -+++ b/servconf.h -@@ -229,6 +229,7 @@ typedef struct { - int expose_userauth_info; - u_int64_t timing_secret; - char *sk_provider; -+ int required_rsa_size; /* minimum size of RSA keys */ - } ServerOptions; - - /* Information about the incoming connection as used by Match */ -diff --git a/ssh.c b/ssh.c -index 559bf2af..25be53d5 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -516,14 +516,22 @@ resolve_canonicalize(char **hostp, int port) - } - - /* -- * Check the result of hostkey loading, ignoring some errors and -- * fatal()ing for others. -+ * Check the result of hostkey loading, ignoring some errors and either -+ * discarding the key or fatal()ing for others. - */ - static void --check_load(int r, const char *path, const char *message) -+check_load(int r, struct sshkey **k, const char *path, const char *message) - { - switch (r) { - case 0: -+ /* Check RSA keys size and discard if undersized */ -+ if (k != NULL && *k != NULL && -+ (r = sshkey_check_rsa_length(*k, -+ options.required_rsa_size)) != 0) { -+ error_r(r, "load %s \"%s\"", message, path); -+ free(*k); -+ *k = NULL; -+ } - break; - case SSH_ERR_INTERNAL_ERROR: - case SSH_ERR_ALLOC_FAIL: -@@ -1578,7 +1586,7 @@ main(int ac, char **av) - if ((o) >= sensitive_data.nkeys) \ - fatal_f("pubkey out of array bounds"); \ - check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \ -- p, "pubkey"); \ -+ &(sensitive_data.keys[o]), p, "pubkey"); \ - } while (0) - #define L_CERT(p,o) do { \ - if ((o) >= sensitive_data.nkeys) \ -@@ -1586,7 +1594,8 @@ main(int ac, char **av) - #define L_CERT(p,o) do { \ - if ((o) >= sensitive_data.nkeys) \ - fatal_f("cert out of array bounds"); \ -- check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \ -+ check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \ -+ &(sensitive_data.keys[o]), p, "cert"); \ - } while (0) - - if (options.hostbased_authentication == 1) { -@@ -2244,7 +2253,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) - filename = default_client_percent_dollar_expand(cp, cinfo); - free(cp); - check_load(sshkey_load_public(filename, &public, NULL), -- filename, "pubkey"); -+ &public, filename, "pubkey"); - debug("identity file %s type %d", filename, - public ? public->type : -1); - free(options.identity_files[i]); -@@ -2284,7 +2293,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) - continue; - xasprintf(&cp, "%s-cert", filename); - check_load(sshkey_load_public(cp, &public, NULL), -- filename, "pubkey"); -+ &public, filename, "pubkey"); - debug("identity file %s type %d", cp, - public ? public->type : -1); - if (public == NULL) { -@@ -2315,7 +2324,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo) - free(cp); - - check_load(sshkey_load_public(filename, &public, NULL), -- filename, "certificate"); -+ &public, filename, "certificate"); - debug("certificate file %s type %d", filename, - public ? public->type : -1); - free(options.certificate_files[i]); -diff --git a/sshconnect2.c b/sshconnect2.c -index f9bd19ea..58fe98db 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -96,6 +96,11 @@ static const struct ssh_conn_info *xxx_conn_info; - static int - verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh) - { -+ int r; -+ -+ if ((r = sshkey_check_rsa_length(hostkey, -+ 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) - fatal("Host key verification failed."); -@@ -1606,6 +1611,13 @@ load_identity_file(Identity *id) - private = NULL; - quit = 1; - } -+ if (!quit && (r = sshkey_check_rsa_length(private, -+ options.required_rsa_size)) != 0) { -+ debug_fr(r, "Skipping key %s", id->filename); -+ sshkey_free(private); -+ private = NULL; -+ quit = 1; -+ } - if (!quit && private != NULL && id->agent_fd == -1 && - !(id->key && id->isprivate)) - maybe_add_key_to_agent(id->filename, private, comment, -@@ -1752,6 +1764,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt) - close(agent_fd); - } else { - for (j = 0; j < idlist->nkeys; j++) { -+ if ((r = sshkey_check_rsa_length(idlist->keys[j], -+ options.required_rsa_size)) != 0) { -+ debug_fr(r, "ignoring %s agent key", -+ sshkey_ssh_name(idlist->keys[j])); -+ continue; -+ } - found = 0; - TAILQ_FOREACH(id, &files, next) { - /* -diff --git a/sshd.c b/sshd.c -index 17eee9d8..395ef493 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -1870,6 +1870,13 @@ main(int ac, char **av) - fatal_r(r, "Could not demote key: \"%s\"", - options.host_key_files[i]); - } -+ if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey, -+ options.required_rsa_size)) != 0) { -+ error_fr(r, "Host key %s", options.host_key_files[i]); -+ sshkey_free(pubkey); -+ sshkey_free(key); -+ continue; -+ } - sensitive_data.host_keys[i] = key; - sensitive_data.host_pubkeys[i] = pubkey; - -diff --git a/sshkey.c b/sshkey.c -index ed2b5dff..77093235 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -2365,18 +2365,24 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf) - return ret; - } - --#ifdef WITH_OPENSSL --static int --check_rsa_length(const RSA *rsa) -+int -+sshkey_check_rsa_length(const struct sshkey *k, int min_size) - { -+#ifdef WITH_OPENSSL - const BIGNUM *rsa_n; -+ int nbits; - -- RSA_get0_key(rsa, &rsa_n, NULL, NULL); -- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) -+ if (k == NULL || k->rsa == NULL || -+ (k->type != KEY_RSA && k->type != KEY_RSA_CERT)) -+ return 0; -+ RSA_get0_key(k->rsa, &rsa_n, NULL, NULL); -+ nbits = BN_num_bits(rsa_n); -+ if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE || -+ (min_size > 0 && nbits < min_size)) - return SSH_ERR_KEY_LENGTH; -+#endif /* WITH_OPENSSL */ - return 0; - } --#endif - - static int - sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, -@@ -2439,7 +2445,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp, - goto out; - } - rsa_n = rsa_e = NULL; /* transferred */ -- if ((ret = check_rsa_length(key->rsa)) != 0) -+ if ((ret = sshkey_check_rsa_length(key, 0)) != 0) - goto out; - #ifdef DEBUG_PK - RSA_print_fp(stderr, key->rsa, 8); -@@ -3642,7 +3648,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp) - goto out; - } - rsa_p = rsa_q = NULL; /* transferred */ -- if ((r = check_rsa_length(k->rsa)) != 0) -+ if ((r = sshkey_check_rsa_length(k, 0)) != 0) - goto out; - if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0) - goto out; -@@ -4644,7 +4650,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- if ((r = check_rsa_length(prv->rsa)) != 0) -+ if ((r = sshkey_check_rsa_length(prv, 0)) != 0) - goto out; - } else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA && - (type == KEY_UNSPEC || type == KEY_DSA)) { -diff --git a/sshkey.h b/sshkey.h -index 094815e0..be254e6b 100644 ---- a/sshkey.h -+++ b/sshkey.h -@@ -273,6 +273,7 @@ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type, - int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob, - int type, struct sshkey **pubkeyp); - -+int sshkey_check_rsa_length(const struct sshkey *, int); - /* XXX should be internal, but used by ssh-keygen */ - int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *); - -diff --git a/ssh.1 b/ssh.1 -index b4956aec..e255b9b9 100644 ---- a/ssh.1 -+++ b/ssh.1 -@@ -571,6 +571,7 @@ For full details of the options listed below, and their possible values, see - .It RemoteCommand - .It RemoteForward - .It RequestTTY -+.It RequiredRSASize - .It SendEnv - .It ServerAliveInterval - .It ServerAliveCountMax -diff --git a/ssh_config.5 b/ssh_config.5 -index 24a46460..d1ede18e 100644 ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -1634,6 +1634,17 @@ and - .Fl T - flags for - .Xr ssh 1 . -+.It Cm RequiredRSASize -+Specifies the minimum RSA key size (in bits) that -+.Xr ssh 1 -+will accept. -+User authentication keys smaller than this limit will be ignored. -+Servers that present host keys smaller than this limit will cause the -+connection to be terminated. -+The default is -+.Cm 1024 -+bits. -+Note that this limit may only be raised from the default. - .It Cm RevokedHostKeys - Specifies revoked host public keys. - Keys listed in this file will be refused for host authentication. -diff --git a/sshd_config.5 b/sshd_config.5 -index 867a747d..f5a06637 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -1596,6 +1596,16 @@ is - .Cm default none , - which means that rekeying is performed after the cipher's default amount - of data has been sent or received and no time based rekeying is done. -+.It Cm RequiredRSASize -+Specifies the minimum RSA key size (in bits) that -+.Xr sshd 8 -+will accept. -+User and host-based authentication keys smaller than this limit will be -+refused. -+The default is -+.Cm 1024 -+bits. -+Note that this limit may only be raised from the default. - .It Cm RevokedKeys - Specifies revoked public keys file, or - .Cm none diff --git a/openssh/openssh-8.7p1-negotiate-supported-algs.patch b/openssh/openssh-8.7p1-negotiate-supported-algs.patch index 2fb9297..ee3637f 100644 --- a/openssh/openssh-8.7p1-negotiate-supported-algs.patch +++ b/openssh/openssh-8.7p1-negotiate-supported-algs.patch @@ -1,63 +1,117 @@ -diff --color -rup a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh ---- a/regress/hostkey-agent.sh 2021-08-20 06:03:49.000000000 +0200 -+++ b/regress/hostkey-agent.sh 2022-07-14 11:58:12.172786060 +0200 -@@ -13,8 +13,12 @@ r=$? - grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig - echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig +diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostkey-agent.sh +--- openssh-9.3p1/regress/hostkey-agent.sh.xxx 2023-05-29 18:15:56.311236887 +0200 ++++ openssh-9.3p1/regress/hostkey-agent.sh 2023-05-29 18:16:07.598503551 +0200 +@@ -17,8 +17,21 @@ trace "make CA key" + + ${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA" +PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \ + grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"` +SSH_ACCEPTED_KEYTYPES=`echo "$SSH_KEYTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"` ++echo $PUBKEY_ACCEPTED_ALGOS | grep "rsa" ++r=$? ++if [ $r == 0 ]; then ++echo $SSH_ACCEPTED_KEYTYPES | grep "rsa" ++r=$? ++if [ $r -ne 0 ]; then ++SSH_ACCEPTED_KEYTYPES="$SSH_ACCEPTED_KEYTYPES ssh-rsa" ++fi ++fi + trace "load hostkeys" -for k in $SSH_KEYTYPES ; do +for k in $SSH_ACCEPTED_KEYTYPES ; do ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k" - ( - printf 'localhost-with-alias,127.0.0.1,::1 ' -@@ -31,7 +35,7 @@ cp $OBJ/known_hosts.orig $OBJ/known_host + ${SSHKEYGEN} -s $OBJ/agent-ca -qh -n localhost-with-alias \ + -I localhost-with-alias $OBJ/agent-key.$k.pub || \ +@@ -32,12 +48,16 @@ rm $OBJ/agent-ca # Don't need CA private + unset SSH_AUTH_SOCK - for ps in yes; do -- for k in $SSH_KEYTYPES ; do -+ for k in $SSH_ACCEPTED_KEYTYPES ; do - verbose "key type $k privsep=$ps" - cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy - echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy -diff --color -rup a/sshconnect2.c b/sshconnect2.c ---- a/sshconnect2.c 2022-07-14 10:10:07.262975710 +0200 -+++ b/sshconnect2.c 2022-07-14 10:10:32.068452067 +0200 -@@ -222,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, st +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; do + verbose "key type $k" ++ hka=$k ++ if [ $k = "ssh-rsa" ]; then ++ hka="rsa-sha2-512" ++ fi + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy +- echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy ++ echo "HostKeyAlgorithms $hka" >> $OBJ/sshd_proxy + echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy +- opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" ++ opts="-oHostKeyAlgorithms=$hka -F $OBJ/ssh_proxy" + ( printf 'localhost-with-alias,127.0.0.1,::1 ' ; + cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts + SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` +@@ -50,15 +70,16 @@ for k in $SSH_KEYTYPES ; do + done + + SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com'` ++SSH_ACCEPTED_CERTTYPES=`echo "$SSH_CERTTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"` + + # Prepare sshd_proxy for certificates. + cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy + HOSTKEYALGS="" +-for k in $SSH_CERTTYPES ; do ++for k in $SSH_ACCEPTED_CERTTYPES ; do + test -z "$HOSTKEYALGS" || HOSTKEYALGS="${HOSTKEYALGS}," + HOSTKEYALGS="${HOSTKEYALGS}${k}" + done +-for k in $SSH_KEYTYPES ; do ++for k in $SSH_ACCEPTED_KEYTYPES ; do + echo "Hostkey $OBJ/agent-key.${k}.pub" >> $OBJ/sshd_proxy + echo "HostCertificate $OBJ/agent-key.${k}-cert.pub" >> $OBJ/sshd_proxy + test -f $OBJ/agent-key.${k}.pub || fatal "no $k key" +@@ -70,7 +93,7 @@ echo "HostKeyAlgorithms $HOSTKEYALGS" >> + ( printf '@cert-authority localhost-with-alias ' ; + cat $OBJ/agent-ca.pub) > $OBJ/known_hosts + +-for k in $SSH_CERTTYPES ; do ++for k in $SSH_ACCEPTED_CERTTYPES ; do + verbose "cert type $k" + opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy" + SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'` +diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c +--- openssh-9.3p1/sshconnect2.c.xxx 2023-04-26 17:37:35.100827792 +0200 ++++ openssh-9.3p1/sshconnect2.c 2023-04-26 17:50:31.860748877 +0200 +@@ -221,7 +221,7 @@ ssh_kex2(struct ssh *ssh, char *host, st + const struct ssh_conn_info *cinfo) { - char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; - char *s, *all_key; -+ char *hostkeyalgs = NULL, *pkalg = NULL; - char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL; + char *myproposal[PROPOSAL_MAX]; +- char *s, *all_key, *hkalgs = NULL; ++ char *s, *all_key, *hkalgs = NULL, *filtered_algs = NULL; int r, use_known_hosts_order = 0; -@@ -264,14 +265,19 @@ ssh_kex2(struct ssh *ssh, char *host, st - myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs; - if (use_known_hosts_order) { - /* Query known_hosts and prefer algorithms that appear there */ -- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = -- compat_pkalg_proposal(ssh, -- order_hostkeyalgs(host, hostaddr, port, cinfo)); -+ if ((hostkeyalgs = order_hostkeyalgs(host, hostaddr, port, cinfo)) == NULL) -+ fatal_f("order_hostkeyalgs"); -+ pkalg = match_filter_allowlist(hostkeyalgs, options.pubkey_accepted_algos); -+ free(hostkeyalgs); - } else { -- /* Use specified HostkeyAlgorithms exactly */ -- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = -- compat_pkalg_proposal(ssh, options.hostkeyalgorithms); -+ /* Use specified HostkeyAlgorithms */ -+ pkalg = match_filter_allowlist(options.hostkeyalgorithms, options.pubkey_accepted_algos); - } -+ if (pkalg == NULL) -+ fatal_f("match_filter_allowlist"); -+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey = -+ compat_pkalg_proposal(ssh, pkalg); -+ free(pkalg); + #if defined(GSSAPI) && defined(WITH_OPENSSL) +@@ -260,9 +260,21 @@ ssh_kex2(struct ssh *ssh, char *host, st + if (use_known_hosts_order) + hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo); + ++ filtered_algs = hkalgs ? match_filter_allowlist(hkalgs, options.pubkey_accepted_algos) ++ : match_filter_allowlist(options.hostkeyalgorithms, ++ options.pubkey_accepted_algos); ++ if (filtered_algs == NULL) { ++ if (hkalgs) ++ fatal_f("No match between algorithms for %s (host %s) and pubkey accepted algorithms %s", ++ hkalgs, host, options.pubkey_accepted_algos); ++ else ++ fatal_f("No match between host key algorithms %s and pubkey accepted algorithms %s", ++ options.hostkeyalgorithms, options.pubkey_accepted_algos); ++ } ++ + kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers, + options.macs, compression_alg_list(options.compression), +- hkalgs ? hkalgs : options.hostkeyalgorithms); ++ filtered_algs); #if defined(GSSAPI) && defined(WITH_OPENSSL) if (options.gss_keyex) { +@@ -303,6 +315,7 @@ ssh_kex2(struct ssh *ssh, char *host, st + #endif + + free(hkalgs); ++ free(filtered_algs); + + /* start key exchange */ + if ((r = kex_setup(ssh, myproposal)) != 0) diff --git a/openssh/openssh-8.7p1-nohostsha1proof.patch b/openssh/openssh-8.7p1-nohostsha1proof.patch new file mode 100644 index 0000000..7fea800 --- /dev/null +++ b/openssh/openssh-8.7p1-nohostsha1proof.patch @@ -0,0 +1,402 @@ +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 + compat_banner(struct ssh *ssh, const char *version) + { + int i; ++ int forbid_ssh_rsa = 0; + static struct { + char *pat; + int bugs; +@@ -145,16 +146,21 @@ compat_banner(struct ssh *ssh, const cha + }; + + /* process table, return first match */ ++ forbid_ssh_rsa = (ssh->compat & SSH_RH_RSASIGSHA); + ssh->compat = 0; + for (i = 0; check[i].pat; i++) { + if (match_pattern_list(version, check[i].pat, 0) == 1) { + debug_f("match: %s pat %s compat 0x%08x", + version, check[i].pat, check[i].bugs); + ssh->compat = check[i].bugs; ++ if (forbid_ssh_rsa) ++ ssh->compat |= SSH_RH_RSASIGSHA; + return; + } + } + debug_f("no match: %s", version); ++ if (forbid_ssh_rsa) ++ ssh->compat |= SSH_RH_RSASIGSHA; + } + + /* 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 +@@ -30,7 +30,7 @@ + #define SSH_BUG_UTF8TTYMODE 0x00000001 + #define SSH_BUG_SIGTYPE 0x00000002 + #define SSH_BUG_SIGTYPE74 0x00000004 +-/* #define unused 0x00000008 */ ++#define SSH_RH_RSASIGSHA 0x00000008 + #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; + struct sshbuf *sigbuf = NULL; + u_char *p = NULL, *signature = NULL; +- char *alg = NULL; ++ char *alg = NULL, *effective_alg; + 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 + } + + if ((key = get_hostkey_by_index(keyid)) != NULL) { +- if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, alg, ++ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0 ++ && (sshkey_type_plain(key->type) == KEY_RSA)) { ++ effective_alg = safe_rsa; ++ } else { ++ effective_alg = alg; ++ } ++ if ((r = sshkey_sign(key, &signature, &siglen, p, datlen, effective_alg, + options.sk_provider, NULL, compat)) != 0) + fatal_fr(r, "sign"); + } else if ((key = get_hostkey_public_by_index(keyid, ssh)) != NULL && + auth_sock > 0) { ++ if (ssh->compat & SSH_RH_RSASIGSHA && strcmp(alg, "ssh-rsa") == 0 ++ && (sshkey_type_plain(key->type) == KEY_RSA)) { ++ effective_alg = safe_rsa; ++ } else { ++ effective_alg = alg; ++ } + if ((r = ssh_agent_sign(auth_sock, key, &signature, &siglen, +- p, datlen, alg, compat)) != 0) ++ p, datlen, effective_alg, compat)) != 0) + fatal_fr(r, "agent sign"); + } else + fatal_f("no hostkey from index %d", keyid); + +- debug3_f("%s %s signature len=%zu", alg, ++ debug3_f("%s (effective: %s) %s signature len=%zu", alg, effective_alg, + 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 +@@ -97,7 +97,8 @@ do_kex_with_key(char *kex, int keytype, + memcpy(kex_params.proposal, myproposal, sizeof(myproposal)); + if (kex != NULL) + kex_params.proposal[PROPOSAL_KEX_ALGS] = kex; +- keyname = strdup(sshkey_ssh_name(private)); ++ keyname = (strcmp(sshkey_ssh_name(private), "ssh-rsa")) ? ++ strdup(sshkey_ssh_name(private)) : strdup("rsa-sha2-256"); + 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 +@@ -110,6 +110,7 @@ sshkey_file_tests(void) + sshkey_free(k2); + TEST_DONE(); + ++ /* Skip this test, SHA1 signatures are not supported + 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) + ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1); + ASSERT_STRING_EQ(k2->cert->signature_type, "ssh-rsa"); + sshkey_free(k2); +- TEST_DONE(); ++ TEST_DONE(); */ + + 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) + TEST_DONE(); + + #ifdef WITH_OPENSSL ++ /* Skip this test, SHA1 signatures are not supported + TEST_START("fuzz RSA sig"); + buf = load_file("rsa_1"); + ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0); + sshbuf_free(buf); + sig_fuzz(k1, "ssh-rsa"); + sshkey_free(k1); +- TEST_DONE(); ++ TEST_DONE();*/ + + 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 +@@ -60,6 +60,9 @@ build_cert(struct sshbuf *b, struct sshk + u_char *sigblob; + size_t siglen; + ++ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */ ++ int expected = (sig_alg == NULL || strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0; ++ + 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 + 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, +- sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), 0); +- ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ ++ sshbuf_ptr(b), sshbuf_len(b), sig_alg, NULL, NULL, 0), expected); ++ if (expected == 0) ++ ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */ + + free(sigblob); + sshbuf_free(ca_buf); +@@ -119,16 +123,22 @@ signature_test(struct sshkey *k, struct + { + 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; ++ if (k && (sshkey_type_plain(k->type) == KEY_DSA || sshkey_type_plain(k->type) == KEY_DSA_CERT)) ++ expected = SSH_ERR_LIBCRYPTO_ERROR; + + ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg, +- NULL, NULL, 0), 0); +- ASSERT_SIZE_T_GT(len, 8); +- ASSERT_PTR_NE(sig, NULL); +- ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); +- ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); +- /* Fuzz test is more comprehensive, this is just a smoke test */ +- sig[len - 5] ^= 0x10; +- ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ NULL, NULL, 0), expected); ++ if (expected == 0) { ++ ASSERT_SIZE_T_GT(len, 8); ++ ASSERT_PTR_NE(sig, NULL); ++ ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, NULL, 0, NULL), 0); ++ /* Fuzz test is more comprehensive, this is just a smoke test */ ++ sig[len - 5] ^= 0x10; ++ ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, NULL, 0, NULL), 0); ++ } + free(sig); + } + +@@ -514,7 +524,7 @@ sshkey_tests(void) + ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, + NULL), 0); + k3 = get_private("rsa_1"); +- build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, NULL); ++ build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1, "rsa-sha2-256"); + 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 +@@ -80,6 +80,7 @@ + #include "auth-options.h" + #include "serverloop.h" + #include "ssherr.h" ++#include "compat.h" + + extern ServerOptions options; + +@@ -737,6 +737,10 @@ server_input_hostkeys_prove(struct ssh * + 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); ++ } + 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 + retried = 1; + goto retry_pin; + } ++ if ((r == SSH_ERR_LIBCRYPTO_ERROR) && strcmp("ssh-rsa", alg)) { ++ char rsa_safe_alg[] = "rsa-sha2-512"; ++ debug3_f("trying to fallback to algorithm %s", rsa_safe_alg); ++ ++ if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen, ++ rsa_safe_alg, options.sk_provider, pin, compat)) != 0) ++ debug_fr(r, "sshkey_sign - RSA fallback"); ++ } + 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) + Authctxt *authctxt; + struct connection_info *connection_info = NULL; + sigset_t sigmask; ++ int forbid_ssh_rsa = 0; + + #ifdef HAVE_SECUREWARE + (void)set_auth_parameters(ac, av); +@@ -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", +@@ -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 +@@ -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 --git a/openssh/openssh-8.7p1-recursive-scp.patch b/openssh/openssh-8.7p1-recursive-scp.patch index 25765fb..f0d9b0f 100644 --- a/openssh/openssh-8.7p1-recursive-scp.patch +++ b/openssh/openssh-8.7p1-recursive-scp.patch @@ -5,11 +5,11 @@ diff -up openssh-8.7p1/scp.c.scp-sftpdirs openssh-8.7p1/scp.c if (src_is_dir && iamrecursive) { if (upload_dir(conn, src, abs_dst, pflag, -- SFTP_PROGRESS_ONLY, 0, 0, 1) != 0) { -+ SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { - error("failed to upload directory %s to %s", - src, abs_dst); - errs = 1; +- 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 @@ -22,11 +22,13 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c { struct sshbuf *msg; u_int expected_id, count, id; -@@ -1012,9 +1012,38 @@ do_realpath_expand(struct sftp_conn *con - - if ((r = sshbuf_get_u32(msg, &status)) != 0) +@@ -1033,11 +1033,43 @@ do_realpath_expand(struct sftp_conn *con + if ((r = sshbuf_get_u32(msg, &status)) != 0 || + (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) fatal_fr(r, "parse status"); -- error("Couldn't canonicalize: %s", fx2txt(status)); +- error("%s %s: %s", expand ? "expand" : "realpath", +- path, *errmsg == '\0' ? fx2txt(status) : errmsg); +- free(errmsg); - sshbuf_free(msg); - return NULL; + if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) { @@ -35,29 +37,34 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c + sshbuf_free(msg); + return NULL; + } -+ ++ debug2("Sending SSH2_FXP_REALPATH \"%s\" - create dir", path); + send_string_request(conn, id, SSH2_FXP_REALPATH, + path, strlen(path)); + + get_msg(conn, msg); + if ((r = sshbuf_get_u8(msg, &type)) != 0 || -+ (r = sshbuf_get_u32(msg, &id)) != 0) ++ (r = sshbuf_get_u32(msg, &id)) != 0) + fatal_fr(r, "parse"); + + if (id != expected_id) + fatal("ID mismatch (%u != %u)", id, expected_id); + + if (type == SSH2_FXP_STATUS) { -+ u_int status; ++ free(errmsg); + -+ if ((r = sshbuf_get_u32(msg, &status)) != 0) ++ if ((r = sshbuf_get_u32(msg, &status)) != 0 || ++ (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0) + fatal_fr(r, "parse status"); -+ error("Couldn't canonicalize: %s", fx2txt(status)); ++ error("%s %s: %s", expand ? "expand" : "realpath", ++ path, *errmsg == '\0' ? fx2txt(status) : errmsg); ++ free(errmsg); + sshbuf_free(msg); + return NULL; + } + } else { -+ error("Couldn't canonicalize: %s", fx2txt(status)); ++ error("%s %s: %s", expand ? "expand" : "realpath", ++ path, *errmsg == '\0' ? fx2txt(status) : errmsg); ++ free(errmsg); + sshbuf_free(msg); + return NULL; + } @@ -94,33 +101,33 @@ diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c - if ((src_canon = do_realpath(conn, src)) == NULL) { + if ((src_canon = do_realpath(conn, src, 0)) == NULL) { - error("Unable to canonicalize path \"%s\"", src); - return -1; - } + error("download \"%s\": path canonicalization failed", src); + return -1; + } @@ -2115,12 +2143,12 @@ upload_dir_internal(struct sftp_conn *co int upload_dir(struct sftp_conn *conn, const char *src, const char *dst, int preserve_flag, int print_flag, int resume, int fsync_flag, -- int follow_link_flag) -+ int follow_link_flag, int create_dir) +- 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("Unable to canonicalize path \"%s\"", dst); - return -1; - } + error("upload \"%s\": path canonicalization failed", dst); + return -1; + } @@ -2557,7 +2585,7 @@ crossload_dir(struct sftp_conn *from, st char *from_path_canon; int ret; - if ((from_path_canon = do_realpath(from, from_path)) == NULL) { + if ((from_path_canon = do_realpath(from, from_path, 0)) == NULL) { - error("Unable to canonicalize path \"%s\"", from_path); - return -1; - } + 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 @@ -136,9 +143,9 @@ diff -up openssh-8.7p1/sftp-client.h.scp-sftpdirs openssh-8.7p1/sftp-client.h @@ -159,7 +159,7 @@ int do_upload(struct sftp_conn *, const * times if 'pflag' is set */ - int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, -- int, int); -+ int, int, int); + int 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 @@ -149,8 +156,8 @@ diff -up openssh-8.7p1/sftp.c.scp-sftpdirs openssh-8.7p1/sftp.c if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { if (upload_dir(conn, g.gl_pathv[i], abs_dst, pflag || global_pflag, 1, resume, -- fflag || global_fflag, 0) == -1) -+ fflag || global_fflag, 0, 0) == -1) +- 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, diff --git a/openssh/openssh-8.7p1-scp-clears-file.patch b/openssh/openssh-8.7p1-scp-clears-file.patch deleted file mode 100644 index 4c033da..0000000 --- a/openssh/openssh-8.7p1-scp-clears-file.patch +++ /dev/null @@ -1,304 +0,0 @@ -diff --color -rup a/scp.c b/scp.c ---- a/scp.c 2022-07-26 14:51:40.560120817 +0200 -+++ b/scp.c 2022-07-26 14:52:37.118213004 +0200 -@@ -1324,12 +1324,12 @@ source_sftp(int argc, char *src, char *t - - if (src_is_dir && iamrecursive) { - if (upload_dir(conn, src, abs_dst, pflag, -- SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) { -+ SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) { - error("failed to upload directory %s to %s", - src, abs_dst); - errs = 1; - } -- } else if (do_upload(conn, src, abs_dst, pflag, 0, 0) != 0) { -+ } else if (do_upload(conn, src, abs_dst, pflag, 0, 0, 1) != 0) { - error("failed to upload file %s to %s", src, abs_dst); - errs = 1; - } -@@ -1566,11 +1566,11 @@ sink_sftp(int argc, char *dst, const cha - debug("Fetching %s to %s\n", g.gl_pathv[i], abs_dst); - if (globpath_is_dir(g.gl_pathv[i]) && iamrecursive) { - if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, -- pflag, SFTP_PROGRESS_ONLY, 0, 0, 1) == -1) -+ pflag, SFTP_PROGRESS_ONLY, 0, 0, 1, 1) == -1) - err = -1; - } else { - if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, -- pflag, 0, 0) == -1) -+ pflag, 0, 0, 1) == -1) - err = -1; - } - free(abs_dst); -diff --color -rup a/sftp.c b/sftp.c ---- a/sftp.c 2022-07-26 14:51:40.561120836 +0200 -+++ b/sftp.c 2022-07-26 14:52:37.119213023 +0200 -@@ -666,12 +666,12 @@ process_get(struct sftp_conn *conn, cons - if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { - if (download_dir(conn, g.gl_pathv[i], abs_dst, NULL, - pflag || global_pflag, 1, resume, -- fflag || global_fflag, 0) == -1) -+ fflag || global_fflag, 0, 0) == -1) - err = -1; - } else { - if (do_download(conn, g.gl_pathv[i], abs_dst, NULL, - pflag || global_pflag, resume, -- fflag || global_fflag) == -1) -+ fflag || global_fflag, 0) == -1) - err = -1; - } - free(abs_dst); -@@ -760,12 +760,12 @@ process_put(struct sftp_conn *conn, cons - if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { - if (upload_dir(conn, g.gl_pathv[i], abs_dst, - pflag || global_pflag, 1, resume, -- fflag || global_fflag, 0, 0) == -1) -+ fflag || global_fflag, 0, 0, 0) == -1) - err = -1; - } else { - if (do_upload(conn, g.gl_pathv[i], abs_dst, - pflag || global_pflag, resume, -- fflag || global_fflag) == -1) -+ fflag || global_fflag, 0) == -1) - err = -1; - } - } -diff --color -rup a/sftp-client.c b/sftp-client.c ---- a/sftp-client.c 2022-07-26 14:51:40.561120836 +0200 -+++ b/sftp-client.c 2022-07-26 15:09:54.825295533 +0200 -@@ -1454,7 +1454,7 @@ progress_meter_path(const char *path) - int - do_download(struct sftp_conn *conn, const char *remote_path, - const char *local_path, Attrib *a, int preserve_flag, int resume_flag, -- int fsync_flag) -+ int fsync_flag, int inplace_flag) - { - struct sshbuf *msg; - u_char *handle; -@@ -1498,8 +1498,8 @@ do_download(struct sftp_conn *conn, cons - &handle, &handle_len) != 0) - return -1; - -- local_fd = open(local_path, -- O_WRONLY | O_CREAT | (resume_flag ? 0 : O_TRUNC), mode | S_IWUSR); -+ local_fd = open(local_path, O_WRONLY | O_CREAT | -+ ((resume_flag || inplace_flag) ? 0 : O_TRUNC), mode | S_IWUSR); - if (local_fd == -1) { - error("Couldn't open local file \"%s\" for writing: %s", - local_path, strerror(errno)); -@@ -1661,8 +1661,11 @@ do_download(struct sftp_conn *conn, cons - /* Sanity check */ - if (TAILQ_FIRST(&requests) != NULL) - fatal("Transfer complete, but requests still in queue"); -- /* Truncate at highest contiguous point to avoid holes on interrupt */ -- if (read_error || write_error || interrupted) { -+ /* -+ * Truncate at highest contiguous point to avoid holes on interrupt, -+ * or unconditionally if writing in place. -+ */ -+ if (inplace_flag || read_error || write_error || interrupted) { - if (reordered && resume_flag) { - error("Unable to resume download of \"%s\": " - "server reordered requests", local_path); -@@ -1724,7 +1727,7 @@ do_download(struct sftp_conn *conn, cons - static int - download_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, - int depth, Attrib *dirattrib, int preserve_flag, int print_flag, -- int resume_flag, int fsync_flag, int follow_link_flag) -+ int resume_flag, int fsync_flag, int follow_link_flag, int inplace_flag) - { - int i, ret = 0; - SFTP_DIRENT **dir_entries; -@@ -1781,7 +1784,7 @@ download_dir_internal(struct sftp_conn * - if (download_dir_internal(conn, new_src, new_dst, - depth + 1, &(dir_entries[i]->a), preserve_flag, - print_flag, resume_flag, -- fsync_flag, follow_link_flag) == -1) -+ fsync_flag, follow_link_flag, inplace_flag) == -1) - ret = -1; - } else if (S_ISREG(dir_entries[i]->a.perm) || - (follow_link_flag && S_ISLNK(dir_entries[i]->a.perm))) { -@@ -1793,7 +1796,8 @@ download_dir_internal(struct sftp_conn * - if (do_download(conn, new_src, new_dst, - S_ISLNK(dir_entries[i]->a.perm) ? NULL : - &(dir_entries[i]->a), -- preserve_flag, resume_flag, fsync_flag) == -1) { -+ preserve_flag, resume_flag, fsync_flag, -+ inplace_flag) == -1) { - error("Download of file %s to %s failed", - new_src, new_dst); - ret = -1; -@@ -1831,7 +1835,7 @@ download_dir_internal(struct sftp_conn * - int - download_dir(struct sftp_conn *conn, const char *src, const char *dst, - Attrib *dirattrib, int preserve_flag, int print_flag, int resume_flag, -- int fsync_flag, int follow_link_flag) -+ int fsync_flag, int follow_link_flag, int inplace_flag) - { - char *src_canon; - int ret; -@@ -1843,26 +1847,25 @@ download_dir(struct sftp_conn *conn, con - - ret = download_dir_internal(conn, src_canon, dst, 0, - dirattrib, preserve_flag, print_flag, resume_flag, fsync_flag, -- follow_link_flag); -+ follow_link_flag, inplace_flag); - free(src_canon); - return ret; - } - - int - do_upload(struct sftp_conn *conn, const char *local_path, -- const char *remote_path, int preserve_flag, int resume, int fsync_flag) -+ const char *remote_path, int preserve_flag, int resume, -+ int fsync_flag, int inplace_flag) - { - int r, local_fd; -- u_int status = SSH2_FX_OK; -- u_int id; -- u_char type; -+ u_int openmode, id, status = SSH2_FX_OK, reordered = 0; - off_t offset, progress_counter; -- u_char *handle, *data; -+ u_char type, *handle, *data; - struct sshbuf *msg; - struct stat sb; -- Attrib a, *c = NULL; -- u_int32_t startid; -- u_int32_t ackid; -+ Attrib a, t, *c = NULL; -+ u_int32_t startid, ackid; -+ u_int64_t highwater = 0; - struct request *ack = NULL; - struct requests acks; - size_t handle_len; -@@ -1913,10 +1916,15 @@ do_upload(struct sftp_conn *conn, const - } - } - -+ openmode = SSH2_FXF_WRITE|SSH2_FXF_CREAT; -+ if (resume) -+ openmode |= SSH2_FXF_APPEND; -+ else if (!inplace_flag) -+ openmode |= SSH2_FXF_TRUNC; -+ - /* Send open request */ -- if (send_open(conn, remote_path, "dest", SSH2_FXF_WRITE|SSH2_FXF_CREAT| -- (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC), -- &a, &handle, &handle_len) != 0) { -+ if (send_open(conn, remote_path, "dest", openmode, &a, -+ &handle, &handle_len) != 0) { - close(local_fd); - return -1; - } -@@ -1999,6 +2007,12 @@ do_upload(struct sftp_conn *conn, const - ack->id, ack->len, (unsigned long long)ack->offset); - ++ackid; - progress_counter += ack->len; -+ if (!reordered && ack->offset <= highwater) -+ highwater = ack->offset + ack->len; -+ else if (!reordered && ack->offset > highwater) { -+ debug3_f("server reordered ACKs"); -+ reordered = 1; -+ } - free(ack); - } - offset += len; -@@ -2017,6 +2031,14 @@ do_upload(struct sftp_conn *conn, const - status = SSH2_FX_FAILURE; - } - -+ if (inplace_flag || (resume && (status != SSH2_FX_OK || interrupted))) { -+ debug("truncating at %llu", (unsigned long long)highwater); -+ attrib_clear(&t); -+ t.flags = SSH2_FILEXFER_ATTR_SIZE; -+ t.size = highwater; -+ do_fsetstat(conn, handle, handle_len, &t); -+ } -+ - if (close(local_fd) == -1) { - error("Couldn't close local file \"%s\": %s", local_path, - strerror(errno)); -@@ -2041,7 +2063,7 @@ do_upload(struct sftp_conn *conn, const - static int - upload_dir_internal(struct sftp_conn *conn, const char *src, const char *dst, - int depth, int preserve_flag, int print_flag, int resume, int fsync_flag, -- int follow_link_flag) -+ int follow_link_flag, int inplace_flag) - { - int ret = 0; - DIR *dirp; -@@ -2119,12 +2141,13 @@ upload_dir_internal(struct sftp_conn *co - - if (upload_dir_internal(conn, new_src, new_dst, - depth + 1, preserve_flag, print_flag, resume, -- fsync_flag, follow_link_flag) == -1) -+ fsync_flag, follow_link_flag, inplace_flag) == -1) - ret = -1; - } else if (S_ISREG(sb.st_mode) || - (follow_link_flag && S_ISLNK(sb.st_mode))) { - if (do_upload(conn, new_src, new_dst, -- preserve_flag, resume, fsync_flag) == -1) { -+ preserve_flag, resume, fsync_flag, -+ inplace_flag) == -1) { - error("Uploading of file %s to %s failed!", - new_src, new_dst); - ret = -1; -@@ -2144,7 +2167,7 @@ upload_dir_internal(struct sftp_conn *co - int - upload_dir(struct sftp_conn *conn, const char *src, const char *dst, - int preserve_flag, int print_flag, int resume, int fsync_flag, -- int follow_link_flag, int create_dir) -+ int follow_link_flag, int create_dir, int inplace_flag) - { - char *dst_canon; - int ret; -@@ -2155,7 +2178,7 @@ upload_dir(struct sftp_conn *conn, const - } - - ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, -- print_flag, resume, fsync_flag, follow_link_flag); -+ print_flag, resume, fsync_flag, follow_link_flag, inplace_flag); - - free(dst_canon); - return ret; -diff --color -rup a/sftp-client.h b/sftp-client.h ---- a/sftp-client.h 2022-07-26 14:51:40.561120836 +0200 -+++ b/sftp-client.h 2022-07-26 14:52:37.120213042 +0200 -@@ -138,28 +138,29 @@ int do_fsync(struct sftp_conn *conn, u_c - * Download 'remote_path' to 'local_path'. Preserve permissions and times - * if 'pflag' is set - */ --int do_download(struct sftp_conn *, const char *, const char *, -- Attrib *, int, int, int); -+int do_download(struct sftp_conn *, const char *, const char *, Attrib *, -+ int, int, int, int); - - /* - * Recursively download 'remote_directory' to 'local_directory'. Preserve - * times if 'pflag' is set - */ --int download_dir(struct sftp_conn *, const char *, const char *, -- Attrib *, int, int, int, int, int); -+int download_dir(struct sftp_conn *, const char *, const char *, Attrib *, -+ int, int, int, int, int, int); - - /* - * Upload 'local_path' to 'remote_path'. Preserve permissions and times - * if 'pflag' is set - */ --int do_upload(struct sftp_conn *, const char *, const char *, int, int, int); -+int do_upload(struct sftp_conn *, const char *, const char *, -+ int, int, int, int); - - /* - * Recursively upload 'local_directory' to 'remote_directory'. Preserve - * times if 'pflag' is set - */ --int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int, -- int, int, int); -+int upload_dir(struct sftp_conn *, const char *, const char *, -+ int, int, int, int, int, int, int); - - /* - * Download a 'from_path' from the 'from' connection and upload it to diff --git a/openssh/openssh-8.7p1-scp-kill-switch.patch b/openssh/openssh-8.7p1-scp-kill-switch.patch index 6710304..161ab2d 100644 --- a/openssh/openssh-8.7p1-scp-kill-switch.patch +++ b/openssh/openssh-8.7p1-scp-kill-switch.patch @@ -13,8 +13,8 @@ diff -up openssh-8.7p1/scp.1.kill-scp openssh-8.7p1/scp.1 --- openssh-8.7p1/scp.1.kill-scp 2021-09-16 12:09:02.646714578 +0200 +++ openssh-8.7p1/scp.1 2021-09-16 12:26:49.978628226 +0200 @@ -278,6 +278,13 @@ to print debugging messages about their - This is helpful in - debugging connection, authentication, and configuration problems. + By default a 32KB buffer is used. + .El .El +.Pp +Usage of SCP protocol can be blocked by creating a world-readable diff --git a/openssh/openssh-8.7p1-sftp-default-protocol.patch b/openssh/openssh-8.7p1-sftp-default-protocol.patch deleted file mode 100644 index c3527b1..0000000 --- a/openssh/openssh-8.7p1-sftp-default-protocol.patch +++ /dev/null @@ -1,87 +0,0 @@ -diff --git a/scp.1 b/scp.1 -index 68aac04b..a96e95ad 100644 ---- a/scp.1 -+++ b/scp.1 -@@ -18,7 +18,7 @@ - .Nd OpenSSH secure file copy - .Sh SYNOPSIS - .Nm scp --.Op Fl 346ABCOpqRrsTv -+.Op Fl 346ABCOpqRrTv - .Op Fl c Ar cipher - .Op Fl D Ar sftp_server_path - .Op Fl F Ar ssh_config -@@ -79,7 +76,9 @@ The options are as follows: - Copies between two remote hosts are transferred through the local host. - Without this option the data is copied directly between the two remote - hosts. --Note that, when using the original SCP protocol (the default), this option -+Note that, when using the original SCP protocol (via the -+.Fl O -+flag), this option - selects batch mode for the second host as - .Nm - cannot ask for passwords or passphrases for both hosts. -@@ -146,7 +145,6 @@ Limits the used bandwidth, specified in Kbit/s. - wildcard patterns and for expanding paths with a - .Sq ~ - prefix for older SFTP servers. --This mode is the default. - .It Fl o Ar ssh_option - Can be used to pass options to - .Nm ssh -@@ -258,8 +258,6 @@ to use for the encrypted connection. - The program must understand - .Xr ssh 1 - options. --.It Fl s --Use the SFTP protocol for transfers rather than the original scp protocol. - .It Fl T - Disable strict filename checking. - By default when copying files from a remote host to a local directory -@@ -299,11 +289,23 @@ debugging connection, authentication, and configuration problems. - .Xr ssh_config 5 , - .Xr sftp-server 8 , - .Xr sshd 8 -+.Sh CAVEATS -+The original scp protocol (selected by the -+.Fl O -+flag) requires execution of the remote user's shell to perform -+.Xr glob 3 -+pattern matching. -+This requires careful quoting of any characters that have special meaning to -+the remote shell, such as quote characters. - .Sh HISTORY - .Nm - is based on the rcp program in - .Bx - source code from the Regents of the University of California. -+.Pp -+Since OpenSSH 8.8 (8.7 in Red Hat/Fedora builds), -+.Nm -+has use the SFTP protocol for transfers by default. - .Sh AUTHORS - .An Timo Rinne Aq Mt tri@iki.fi - .An Tatu Ylonen Aq Mt ylo@cs.hut.fi -diff --git a/scp.c b/scp.c -index e039350c..c7cf7529 100644 ---- a/scp.c -+++ b/scp.c -@@ -448,7 +448,7 @@ main(int argc, char **argv) - const char *errstr; - extern char *optarg; - extern int optind; -- enum scp_mode_e mode = MODE_SCP; -+ enum scp_mode_e mode = MODE_SFTP; - char *sftp_direct = NULL; - - /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ -@@ -1983,7 +1983,7 @@ void - usage(void) - { - (void) fprintf(stderr, -- "usage: scp [-346ABCOpqRrsTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" -+ "usage: scp [-346ABCOpqRrTv] [-c cipher] [-D sftp_server_path] [-F ssh_config]\n" - " [-i identity_file] [-J destination] [-l limit]\n" - " [-o ssh_option] [-P port] [-S program] source ... target\n"); - exit(1); diff --git a/openssh/openssh-8.7p1-sftpscp-dir-create.patch b/openssh/openssh-8.7p1-sftpscp-dir-create.patch deleted file mode 100644 index bc504f9..0000000 --- a/openssh/openssh-8.7p1-sftpscp-dir-create.patch +++ /dev/null @@ -1,135 +0,0 @@ -diff -up openssh-8.7p1/scp.c.sftpdirs openssh-8.7p1/scp.c ---- openssh-8.7p1/scp.c.sftpdirs 2022-02-02 14:11:12.553447509 +0100 -+++ openssh-8.7p1/scp.c 2022-02-02 14:12:56.081316414 +0100 -@@ -130,6 +130,7 @@ - #include "misc.h" - #include "progressmeter.h" - #include "utf8.h" -+#include "sftp.h" - - #include "sftp-common.h" - #include "sftp-client.h" -@@ -1264,13 +1265,18 @@ tolocal(int argc, char **argv, enum scp_ - static char * - prepare_remote_path(struct sftp_conn *conn, const char *path) - { -+ size_t nslash; -+ - /* Handle ~ prefixed paths */ -- if (*path != '~') -- return xstrdup(path); - if (*path == '\0' || strcmp(path, "~") == 0) - return xstrdup("."); -- if (strncmp(path, "~/", 2) == 0) -- return xstrdup(path + 2); -+ if (*path != '~') -+ return xstrdup(path); -+ if (strncmp(path, "~/", 2) == 0) { -+ if ((nslash = strspn(path + 2, "/")) == strlen(path + 2)) -+ return xstrdup("."); -+ return xstrdup(path + 2 + nslash); -+ } - if (can_expand_path(conn)) - return do_expand_path(conn, path); - /* No protocol extension */ -@@ -1282,10 +1288,16 @@ void - source_sftp(int argc, char *src, char *targ, struct sftp_conn *conn) - { - char *target = NULL, *filename = NULL, *abs_dst = NULL; -- int target_is_dir; -- -+ int src_is_dir, target_is_dir; -+ Attrib a; -+ struct stat st; -+ -+ memset(&a, '\0', sizeof(a)); -+ if (stat(src, &st) != 0) -+ fatal("stat local \"%s\": %s", src, strerror(errno)); -+ src_is_dir = S_ISDIR(st.st_mode); - if ((filename = basename(src)) == NULL) -- fatal("basename %s: %s", src, strerror(errno)); -+ fatal("basename \"%s\": %s", src, strerror(errno)); - - /* - * No need to glob here - the local shell already took care of -@@ -1295,8 +1307,12 @@ source_sftp(int argc, char *src, char *t - cleanup_exit(255); - target_is_dir = remote_is_dir(conn, target); - if (targetshouldbedirectory && !target_is_dir) { -- fatal("Target is not a directory, but more files selected " -- "for upload"); -+ debug("target directory \"%s\" does not exist", target); -+ a.flags = SSH2_FILEXFER_ATTR_PERMISSIONS; -+ a.perm = st.st_mode | 0700; /* ensure writable */ -+ if (do_mkdir(conn, target, &a, 1) != 0) -+ cleanup_exit(255); /* error already logged */ -+ target_is_dir = 1; - } - if (target_is_dir) - abs_dst = path_append(target, filename); -@@ -1306,7 +1322,7 @@ source_sftp(int argc, char *src, char *t - } - debug3_f("copying local %s to remote %s", src, abs_dst); - -- if (local_is_dir(src) && iamrecursive) { -+ if (src_is_dir && iamrecursive) { - if (upload_dir(conn, src, abs_dst, pflag, - SFTP_PROGRESS_ONLY, 0, 0, 1) != 0) { - error("failed to upload directory %s to %s", -@@ -1487,14 +1506,15 @@ sink_sftp(int argc, char *dst, const cha - char *abs_dst = NULL; - glob_t g; - char *filename, *tmp = NULL; -- int i, r, err = 0; -+ int i, r, err = 0, dst_is_dir; -+ struct stat st; - - memset(&g, 0, sizeof(g)); -+ - /* - * Here, we need remote glob as SFTP can not depend on remote shell - * expansions - */ -- - if ((abs_src = prepare_remote_path(conn, src)) == NULL) { - err = -1; - goto out; -@@ -1510,11 +1530,24 @@ sink_sftp(int argc, char *dst, const cha - goto out; - } - -- if (g.gl_matchc > 1 && !local_is_dir(dst)) { -- error("Multiple files match pattern, but destination " -- "\"%s\" is not a directory", dst); -- err = -1; -- goto out; -+ if ((r = stat(dst, &st)) != 0) -+ debug2_f("stat local \"%s\": %s", dst, strerror(errno)); -+ dst_is_dir = r == 0 && S_ISDIR(st.st_mode); -+ -+ if (g.gl_matchc > 1 && !dst_is_dir) { -+ if (r == 0) { -+ error("Multiple files match pattern, but destination " -+ "\"%s\" is not a directory", dst); -+ err = -1; -+ goto out; -+ } -+ debug2_f("creating destination \"%s\"", dst); -+ if (mkdir(dst, 0777) != 0) { -+ error("local mkdir \"%s\": %s", dst, strerror(errno)); -+ err = -1; -+ goto out; -+ } -+ dst_is_dir = 1; - } - - for (i = 0; g.gl_pathv[i] && !interrupted; i++) { -@@ -1525,7 +1558,7 @@ sink_sftp(int argc, char *dst, const cha - goto out; - } - -- if (local_is_dir(dst)) -+ if (dst_is_dir) - abs_dst = path_append(dst, filename); - else - abs_dst = xstrdup(dst); diff --git a/openssh/openssh-8.7p1-ssh-manpage.patch b/openssh/openssh-8.7p1-ssh-manpage.patch index 04e4c06..c7f6f1e 100644 --- a/openssh/openssh-8.7p1-ssh-manpage.patch +++ b/openssh/openssh-8.7p1-ssh-manpage.patch @@ -14,9 +14,9 @@ diff --color -ru a/ssh.1 b/ssh.1 .It ControlPersist .It DynamicForward +.It EnableSSHKeysign + .It EnableEscapeCommandline .It EscapeChar .It ExitOnForwardFailure - .It FingerprintHash @@ -538,6 +540,8 @@ .It IdentitiesOnly .It IdentityAgent diff --git a/openssh/openssh-8.8p1-skip-some-tests.patch b/openssh/openssh-8.8p1-skip-some-tests.patch deleted file mode 100644 index 7268eb3..0000000 --- a/openssh/openssh-8.8p1-skip-some-tests.patch +++ /dev/null @@ -1,41 +0,0 @@ -diff -up openssh-8.8p1/regress/hostkey-agent.sh.redhat openssh-8.8p1/regress/hostkey-agent.sh ---- openssh-8.8p1/regress/hostkey-agent.sh.redhat 2022-08-10 15:54:42.084777662 +0200 -+++ openssh-8.8p1/regress/hostkey-agent.sh 2022-08-10 17:01:25.651269994 +0200 -@@ -36,6 +36,8 @@ unset SSH_AUTH_SOCK - - for ps in yes; do - for k in $SSH_ACCEPTED_KEYTYPES ; do -+ [ "$k" == "ssh-rsa" ] && continue -+ [ "$k" == "ssh-dss" ] && continue - verbose "key type $k privsep=$ps" - cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy - echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy -diff -up openssh-8.8p1/regress/hostkey-rotate.sh.redhat openssh-8.8p1/regress/hostkey-rotate.sh ---- openssh-8.8p1/regress/hostkey-rotate.sh.redhat 2022-08-10 16:57:12.720029146 +0200 -+++ openssh-8.8p1/regress/hostkey-rotate.sh 2022-08-10 17:15:48.274923865 +0200 -@@ -40,6 +40,8 @@ trace "prepare hostkeys" - nkeys=0 - all_algs="" - for k in $SSH_HOSTKEY_TYPES; do -+ [ "$k" == "ssh-rsa" ] && continue -+ [ "$k" == "ssh-dss" ] && continue - ${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k" - echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig - nkeys=`expr $nkeys + 1` -@@ -87,11 +89,15 @@ dossh -oStrictHostKeyChecking=yes -oHost - # Check that other keys learned - expect_nkeys $nkeys "learn hostkeys" - for k in $SSH_HOSTKEY_TYPES; do -+ [ "$k" == "ssh-rsa" ] && continue -+ [ "$k" == "ssh-dss" ] && continue - check_key_present $k || fail "didn't learn keytype $k" - done - - # Check each key type - for k in $SSH_HOSTKEY_TYPES; do -+ [ "$k" == "ssh-rsa" ] && continue -+ [ "$k" == "ssh-dss" ] && continue - verbose "learn additional hostkeys, type=$k" - dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$k,$all_algs - expect_nkeys $nkeys "learn hostkeys $k" - diff --git a/openssh/openssh-9.0p1-evp-fips-dh.patch b/openssh/openssh-9.0p1-evp-fips-dh.patch new file mode 100644 index 0000000..d0470d9 --- /dev/null +++ b/openssh/openssh-9.0p1-evp-fips-dh.patch @@ -0,0 +1,292 @@ +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 +@@ -37,6 +37,9 @@ + #include + #include + #include ++#include ++#include ++#include + + #include "dh.h" + #include "pathnames.h" +@@ -290,10 +293,15 @@ + int + dh_gen_key(DH *dh, int need) + { +- int pbits; +- const BIGNUM *dh_p, *pub_key; ++ const BIGNUM *dh_p, *dh_g; ++ BIGNUM *pub_key = NULL, *priv_key = NULL; ++ EVP_PKEY *pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ OSSL_PARAM_BLD *param_bld = NULL; ++ OSSL_PARAM *params = NULL; ++ int pbits, r = 0; + +- DH_get0_pqg(dh, &dh_p, NULL, NULL); ++ DH_get0_pqg(dh, &dh_p, NULL, &dh_g); + + if (need < 0 || dh_p == NULL || + (pbits = BN_num_bits(dh_p)) <= 0 || +@@ -301,19 +309,85 @@ + return SSH_ERR_INVALID_ARGUMENT; + if (need < 256) + need = 256; ++ ++ if ((param_bld = OSSL_PARAM_BLD_new()) == NULL || ++ (ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL) { ++ OSSL_PARAM_BLD_free(param_bld); ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ if (OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_FFC_P, dh_p) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_FFC_G, dh_g) != 1) { ++ error_f("Could not set p,q,g parameters"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + /* + * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), + * so double requested need here. + */ +- if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1))) +- return SSH_ERR_LIBCRYPTO_ERROR; +- +- if (DH_generate_key(dh) == 0) +- return SSH_ERR_LIBCRYPTO_ERROR; +- DH_get0_key(dh, &pub_key, NULL); +- if (!dh_pub_is_valid(dh, pub_key)) +- return SSH_ERR_INVALID_FORMAT; +- return 0; ++ if (OSSL_PARAM_BLD_push_int(param_bld, ++ OSSL_PKEY_PARAM_DH_PRIV_LEN, ++ MINIMUM(need * 2, pbits - 1)) != 1 || ++ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata_init(ctx) != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_fromdata(ctx, &pkey, ++ EVP_PKEY_KEY_PARAMETERS, params) != 1) { ++ error_f("Failed key generation"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* reuse context for key generation */ ++ EVP_PKEY_CTX_free(ctx); ++ ctx = NULL; ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL || ++ EVP_PKEY_keygen_init(ctx) != 1) { ++ error_f("Could not create or init context"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_generate(ctx, &pkey) != 1) { ++ error_f("Could not generate keys"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (EVP_PKEY_public_check(ctx) != 1) { ++ error_f("The public key is incorrect"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY, ++ &pub_key) != 1 || ++ EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY, ++ &priv_key) != 1 || ++ DH_set0_key(dh, pub_key, priv_key) != 1) { ++ error_f("Could not set pub/priv keys to DH struct"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ /* transferred */ ++ pub_key = NULL; ++ priv_key = NULL; ++out: ++ OSSL_PARAM_free(params); ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ EVP_PKEY_free(pkey); ++ BN_clear_free(pub_key); ++ BN_clear_free(priv_key); ++ return r; + } + + 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,47 @@ + return r; + } + ++#ifdef WITH_OPENSSL ++/* ++ * Creates an EVP_PKEY from the given parameters and keys. ++ * The private key can be omitted. ++ */ ++int ++kex_create_evp_dh(EVP_PKEY **pkey, const BIGNUM *p, const BIGNUM *q, ++ const BIGNUM *g, const BIGNUM *pub, const BIGNUM *priv) ++{ ++ OSSL_PARAM_BLD *param_bld = NULL; ++ EVP_PKEY_CTX *ctx = NULL; ++ int r = 0; ++ ++ /* create EVP_PKEY-DH key */ ++ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL || ++ (param_bld = OSSL_PARAM_BLD_new()) == NULL) { ++ error_f("EVP_PKEY_CTX or PARAM_BLD init failed"); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1 || ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PUB_KEY, pub) != 1) { ++ error_f("Failed pushing params to OSSL_PARAM_BLD"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if (priv != NULL && ++ OSSL_PARAM_BLD_push_BN(param_bld, ++ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) { ++ error_f("Failed pushing private key to OSSL_PARAM_BLD"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++out: ++ OSSL_PARAM_BLD_free(param_bld); ++ EVP_PKEY_CTX_free(ctx); ++ 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 +@@ -35,6 +35,10 @@ + + #include "openbsd-compat/openssl-compat.h" + #include ++#include ++#include ++#include ++#include + + #include "sshkey.h" + #include "kex.h" +@@ -83,9 +87,12 @@ + kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out) + { + BIGNUM *shared_secret = NULL; ++ const BIGNUM *pub, *priv, *p, *q, *g; ++ EVP_PKEY *pkey = NULL, *dh_pkey = NULL; ++ EVP_PKEY_CTX *ctx = NULL; + u_char *kbuf = NULL; + size_t klen = 0; +- int kout, r; ++ int kout, r = 0; + + #ifdef DEBUG_KEXDH + fprintf(stderr, "dh_pub= "); +@@ -100,24 +107,59 @@ + r = SSH_ERR_MESSAGE_INCOMPLETE; + goto out; + } +- klen = DH_size(kex->dh); ++ ++ DH_get0_key(kex->dh, &pub, &priv); ++ DH_get0_pqg(kex->dh, &p, &q, &g); ++ /* import key */ ++ r = kex_create_evp_dh(&pkey, p, q, g, pub, priv); ++ if (r != 0) { ++ error_f("Could not create EVP_PKEY for dh"); ++ ERR_print_errors_fp(stderr); ++ goto out; ++ } ++ /* import peer key ++ * the parameters should be the same as with pkey ++ */ ++ r = kex_create_evp_dh(&dh_pkey, p, q, g, dh_pub, NULL); ++ if (r != 0) { ++ error_f("Could not import peer key for dh"); ++ ERR_print_errors_fp(stderr); ++ goto out; ++ } ++ ++ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL) { ++ error_f("Could not init EVP_PKEY_CTX for dh"); ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if (EVP_PKEY_derive_init(ctx) != 1 || ++ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 || ++ EVP_PKEY_derive(ctx, NULL, &klen) != 1) { ++ error_f("Could not get key size"); ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } + if ((kbuf = malloc(klen)) == NULL || + (shared_secret = BN_new()) == NULL) { + r = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 || +- BN_bin2bn(kbuf, kout, shared_secret) == NULL) { ++ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1 || ++ BN_bin2bn(kbuf, klen, shared_secret) == NULL) { ++ error_f("Could not derive key"); + r = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + #ifdef DEBUG_KEXDH +- dump_digest("shared secret", kbuf, kout); ++ dump_digest("shared secret", kbuf, klen); + #endif + r = sshbuf_put_bignum2(out, shared_secret); + out: + freezero(kbuf, klen); + BN_clear_free(shared_secret); ++ EVP_PKEY_free(pkey); ++ EVP_PKEY_free(dh_pkey); ++ EVP_PKEY_CTX_free(ctx); + 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,8 @@ + 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 *); + + #if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) + void dump_digest(const char *, const u_char *, int); diff --git a/openssh/openssh-9.0p1-evp-fips-ecdh.patch b/openssh/openssh-9.0p1-evp-fips-ecdh.patch new file mode 100644 index 0000000..0313c6f --- /dev/null +++ b/openssh/openssh-9.0p1-evp-fips-ecdh.patch @@ -0,0 +1,207 @@ +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/openssh-8.0p1-gssapi-keyex.patch b/openssh/openssh-9.3p1-gssapi-keyex.patch similarity index 97% rename from openssh/openssh-8.0p1-gssapi-keyex.patch rename to openssh/openssh-9.3p1-gssapi-keyex.patch index e26bebd..68dc906 100644 --- a/openssh/openssh-8.0p1-gssapi-keyex.patch +++ b/openssh/openssh-9.3p1-gssapi-keyex.patch @@ -12,13 +12,22 @@ index e7549470..b68c1710 100644 @@ -125,7 +126,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ - auth2-none.o auth2-passwd.o auth2-pubkey.o \ + auth2-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 \ - loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.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 \ +@@ -523,7 +523,7 @@ regress-prep: + ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile + + REGRESSLIBS=libssh.a $(LIBCOMPAT) +-TESTLIBS=$(LIBS) $(CHANNELLIBS) ++TESTLIBS=$(LIBS) $(CHANNELLIBS) $(GSSLIBS) + + regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c $(REGRESSLIBS) + $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/modpipe.c \ diff -up a/auth.c.gsskex b/auth.c --- a/auth.c.gsskex 2021-08-20 06:03:49.000000000 +0200 +++ b/auth.c 2021-08-27 12:41:51.262788953 +0200 @@ -135,7 +144,7 @@ index 9351e042..d6446c0c 100644 --- a/auth2-gss.c +++ b/auth2-gss.c @@ -1,7 +1,7 @@ - /* $OpenBSD: auth2-gss.c,v 1.32 2021/01/27 10:15:08 djm Exp $ */ + /* $OpenBSD: auth2-gss.c,v 1.33 2021/12/19 22:12:07 djm Exp $ */ /* - * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. @@ -151,7 +160,7 @@ index 9351e042..d6446c0c 100644 + * The 'gssapi_keyex' userauth mechanism. + */ +static int -+userauth_gsskeyex(struct ssh *ssh) ++userauth_gsskeyex(struct ssh *ssh, const char *method) +{ + Authctxt *authctxt = ssh->authctxt; + int r, authenticated = 0; @@ -212,19 +221,20 @@ index 9351e042..d6446c0c 100644 else logit("GSSAPI MIC check failed"); -@@ -326,6 +370,12 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) +@@ -326,6 +370,13 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) return 0; } +Authmethod method_gsskeyex = { + "gssapi-keyex", ++ NULL, + userauth_gsskeyex, + &options.gss_authentication +}; + Authmethod method_gssapi = { "gssapi-with-mic", - userauth_gssapi, + NULL, diff --git a/auth2.c b/auth2.c index 0e776224..1c217268 100644 --- a/auth2.c @@ -375,16 +385,12 @@ index ebd0dbca..1bdac6a4 100644 +#include "ssh-gss.h" +#endif + - /* import options */ - extern Options options; + /* Permitted RSA signature algorithms for UpdateHostkeys proofs */ + #define HOSTKEY_PROOF_RSA_ALGS "rsa-sha2-512,rsa-sha2-256" -@@ -1379,9 +1383,18 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, - break; - - /* Do channel operations unless rekeying in progress. */ -- if (!ssh_packet_is_rekeying(ssh)) -+ if (!ssh_packet_is_rekeying(ssh)) { - channel_after_select(ssh, readset, writeset); +@@ -1379,6 +1383,14 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, + /* Do channel operations. */ + channel_after_poll(ssh, pfd, npfd_active); +#ifdef GSSAPI + if (options.gss_renewal_rekey && @@ -393,11 +399,10 @@ index ebd0dbca..1bdac6a4 100644 + need_rekeying = 1; + } +#endif -+ } + /* Buffer input from the connection. */ - client_process_net_input(ssh, readset); - + if (conn_in_ready) + client_process_net_input(ssh); diff --git a/configure.ac b/configure.ac index b689db4b..efafb6bd 100644 --- a/configure.ac @@ -1254,15 +1259,9 @@ diff --git a/kex.c b/kex.c index ce85f043..574c7609 100644 --- a/kex.c +++ b/kex.c -@@ -57,11 +57,16 @@ - #include "misc.h" - #include "dispatch.h" - #include "monitor.h" -+#include "xmalloc.h" - - #include "ssherr.h" - #include "sshbuf.h" +@@ -57,6 +57,10 @@ #include "digest.h" + #include "xmalloc.h" +#ifdef GSSAPI +#include "ssh-gss.h" @@ -1360,9 +1359,9 @@ index ce85f043..574c7609 100644 + return 1; +} + - /* put algorithm proposal into buffer */ - int - kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) + /* + * 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); @@ -1370,9 +1369,9 @@ index ce85f043..574c7609 100644 +#ifdef GSSAPI + free(kex->gss_host); +#endif /* GSSAPI */ + sshbuf_free(kex->initial_sig); + sshkey_free(kex->initial_hostkey); free(kex->failed_choice); - free(kex->hostkey_alg); - free(kex->name); diff --git a/kex.h b/kex.h index a5ae6ac0..fe714141 100644 --- a/kex.h @@ -1414,9 +1413,9 @@ index a5ae6ac0..fe714141 100644 char *kex_names_cat(const char *, const char *); int kex_assemble_names(char **, const char *, const char *); +int kex_gss_names_valid(const char *); - - int kex_exchange_identification(struct ssh *, int, const char *); - + 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 *); @@ -1489,7 +1488,7 @@ new file mode 100644 index 00000000..f6e1405e --- /dev/null +++ b/kexgssc.c -@@ -0,0 +1,599 @@ +@@ -0,0 +1,600 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -2088,6 +2087,7 @@ index 00000000..f6e1405e + sshbuf_free(server_host_key_blob); + return r; +} ++ +#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ diff --git a/kexgsss.c b/kexgsss.c new file mode 100644 @@ -2612,6 +2612,23 @@ 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 + if (ent->flags & (MON_AUTHDECIDE|MON_ALOG)) { + auth_log(ssh, authenticated, partial, + auth_method, auth_submethod); +- if (!partial && !authenticated) ++ if (!partial && !authenticated) { ++#ifdef GSSAPI ++ /* If gssapi-with-mic failed, MONITOR_REQ_GSSCHECKMIC is disabled. ++ * We have to reenable it to try again for gssapi-keyex */ ++ if (strcmp(auth_method, "gssapi-with-mic") == 0 && options.gss_keyex) ++ monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); ++#endif + authctxt->failures++; ++ } + if (authenticated || partial) { + auth2_update_session_info(authctxt, + auth_method, auth_submethod); @@ -406,6 +419,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -3011,7 +3028,7 @@ diff -up a/readconf.c.gsskex b/readconf.c options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; @@ -2463,8 +2516,18 @@ fill_default_options(Options * options) - options->pubkey_authentication = 1; + options->pubkey_authentication = SSH_PUBKEY_AUTH_ALL; if (options->gss_authentication == -1) options->gss_authentication = 0; + if (options->gss_keyex == -1) @@ -3496,7 +3513,7 @@ index af00fb30..03bc87eb 100644 /* @@ -163,6 +161,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) - char *s, *all_key; + char *s, *all_key, *hkalgs = NULL; int r, use_known_hosts_order = 0; +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3508,9 +3525,10 @@ 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) - compat_pkalg_proposal(ssh, options.hostkeyalgorithms); - } - + kex_proposal_populate_entries(ssh, myproposal, s, options.ciphers, + options.macs, compression_alg_list(options.compression), + hkalgs ? hkalgs : options.hostkeyalgorithms); ++ +#if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { + /* Add the GSSAPI mechanisms currently supported on this @@ -3546,11 +3564,10 @@ index af00fb30..03bc87eb 100644 + } + } +#endif -+ - if (options.rekey_limit || options.rekey_interval) - ssh_packet_set_rekey_limits(ssh, options.rekey_limit, - options.rekey_interval); -@@ -224,16 +256,46 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + + free(hkalgs); + +@@ -224,17 +256,47 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) # ifdef OPENSSL_HAS_ECC ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif @@ -3568,7 +3585,7 @@ index af00fb30..03bc87eb 100644 +# endif +#endif /* WITH_OPENSSL */ ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; - ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP761X25519_SHA512] = kex_gen_client; ssh->kex->verify_host_key=&verify_host_key_callback; +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3583,6 +3600,7 @@ index af00fb30..03bc87eb 100644 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); /* remove ext-info from the KEX proposals for rekeying */ + free(myproposal[PROPOSAL_KEX_ALGS]); myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(ssh, options.kex_algorithms); +#if defined(GSSAPI) && defined(WITH_OPENSSL) @@ -3751,8 +3769,8 @@ index 60b2aaf7..d92f03aa 100644 exit(1); } @@ -2347,6 +2348,48 @@ do_ssh2_kex(struct ssh *ssh) - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( - ssh, list_hostkey_types()); + + free(hkalgs); +#if defined(GSSAPI) && defined(WITH_OPENSSL) + { @@ -3885,22 +3903,40 @@ diff --git a/sshkey.c b/sshkey.c index 57995ee6..fd5b7724 100644 --- a/sshkey.c +++ b/sshkey.c -@@ -154,6 +154,7 @@ static const struct keytype keytypes[] = { - KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 }, - # endif /* OPENSSL_HAS_ECC */ - #endif /* WITH_OPENSSL */ -+ { "null", "null", NULL, KEY_NULL, 0, 0, 0 }, - { NULL, NULL, NULL, -1, -1, 0, 0 } +@@ -127,6 +127,17 @@ + extern const struct sshkey_impl sshkey_xmss_impl; + extern const struct sshkey_impl sshkey_xmss_cert_impl; + #endif ++const struct sshkey_impl sshkey_null_impl = { ++ /* .name = */ "null", ++ /* .shortname = */ "null", ++ /* .sigalg = */ NULL, ++ /* .type = */ KEY_NULL, ++ /* .nid = */ 0, ++ /* .cert = */ 0, ++ /* .sigonly = */ 0, ++ /* .keybits = */ 0, ++ /* .funcs = */ NULL, ++}; + + const struct sshkey_impl * const keyimpls[] = { + &sshkey_ed25519_impl, +@@ -162,6 +179,7 @@ static const struct keytype keytypes[] = + &sshkey_xmss_impl, + &sshkey_xmss_cert_impl, + #endif ++ &sshkey_null_impl, + NULL }; -@@ -255,7 +256,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) - const struct keytype *kt; +@@ -286,7 +304,7 @@ sshkey_alg_list(int certs_only, int plai - for (kt = keytypes; kt->type != -1; kt++) { -- if (kt->name == NULL) -+ if (kt->name == NULL || kt->type == KEY_NULL) + for (i = 0; keyimpls[i] != NULL; i++) { + impl = keyimpls[i]; +- if (impl->name == NULL) ++ if (impl->name == NULL || impl->type == KEY_NULL) continue; - if (!include_sigonly && kt->sigonly) + if (!include_sigonly && impl->sigonly) continue; diff --git a/sshkey.h b/sshkey.h index 71a3fddc..37a43a67 100644 diff --git a/openssh/openssh-9.3p1-merged-openssl-evp.patch b/openssh/openssh-9.3p1-merged-openssl-evp.patch new file mode 100644 index 0000000..95d86c3 --- /dev/null +++ b/openssh/openssh-9.3p1-merged-openssl-evp.patch @@ -0,0 +1,1236 @@ +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 +@@ -268,6 +271,10 @@ + const char *sshkey_ssh_name_plain(const struct sshkey *); + int sshkey_names_valid2(const char *, int); + char *sshkey_alg_list(int, int, int, char); ++int sshkey_calculate_signature(EVP_PKEY*, int, u_char **, ++ int *, const u_char *, size_t); ++int sshkey_verify_signature(EVP_PKEY *, int, const u_char *, ++ size_t, u_char *, int); + + int sshkey_from_blob(const u_char *, size_t, struct sshkey **); + int sshkey_fromb(struct sshbuf *, struct sshkey **); +@@ -324,6 +331,13 @@ + + void sshkey_sig_details_free(struct sshkey_sig_details *); + ++#ifdef WITH_OPENSSL ++EVP_PKEY *sshkey_create_evp(OSSL_PARAM_BLD *, EVP_PKEY_CTX *); ++int ssh_create_evp_dss(const struct sshkey *, EVP_PKEY **); ++int ssh_create_evp_rsa(const struct sshkey *, EVP_PKEY **); ++int ssh_create_evp_ec(EC_KEY *, int, EVP_PKEY **); ++#endif /* WITH_OPENSSL */ ++ + #ifdef SSHKEY_INTERNAL + int sshkey_sk_fields_equal(const struct sshkey *a, const struct sshkey *b); + void sshkey_sk_cleanup(struct sshkey *k); +@@ -338,6 +352,10 @@ + #endif + #endif + ++#ifdef ENABLE_PKCS11 ++int pkcs11_get_ecdsa_idx(void); ++#endif ++ + #if !defined(WITH_OPENSSL) + # undef RSA + # undef DSA +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-pkcs11.c openssh-9.3p1-patched/ssh-pkcs11.c +--- openssh-9.3p1/ssh-pkcs11.c 2023-06-06 15:53:36.592443989 +0200 ++++ openssh-9.3p1-patched/ssh-pkcs11.c 2023-06-06 15:52:25.626551768 +0200 +@@ -777,8 +777,24 @@ + + return (0); + } ++ ++int ++is_ecdsa_pkcs11(EC_KEY *ecdsa) ++{ ++ if (EC_KEY_get_ex_data(ecdsa, ec_key_idx) != NULL) ++ return 1; ++ return 0; ++} + #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + ++int ++is_rsa_pkcs11(RSA *rsa) ++{ ++ if (RSA_get_ex_data(rsa, rsa_idx) != NULL) ++ return 1; ++ return 0; ++} ++ + /* remove trailing spaces. 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; ++ ++int ++is_ecdsa_pkcs11(EC_KEY *ecdsa) ++{ ++ const EC_KEY_METHOD *meth; ++ ECDSA_SIG *(*sign_sig)(const unsigned char *dgst, int dgstlen, ++ const BIGNUM *kinv, const BIGNUM *rp, EC_KEY *eckey) = NULL; ++ ++ meth = EC_KEY_get_method(ecdsa); ++ EC_KEY_METHOD_get_sign(meth, NULL, NULL, &sign_sig); ++ if (sign_sig == ecdsa_do_sign) ++ return 1; ++ return 0; ++} + #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ + ++int ++is_rsa_pkcs11(RSA *rsa) ++{ ++ const RSA_METHOD *meth; ++ int (*priv_enc)(int flen, const unsigned char *from, ++ unsigned char *to, RSA *rsa, int padding) = NULL; ++ ++ meth = RSA_get_method(rsa); ++ priv_enc = RSA_meth_get_priv_enc(meth); ++ if (priv_enc == rsa_encrypt) ++ return 1; ++ return 0; ++} ++ + /* redirect private key crypto operations to the ssh-pkcs11-helper */ + static void + wrap_key(struct sshkey *k) +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-pkcs11.h openssh-9.3p1-patched/ssh-pkcs11.h +--- openssh-9.3p1/ssh-pkcs11.h 2023-06-06 15:53:36.592443989 +0200 ++++ openssh-9.3p1-patched/ssh-pkcs11.h 2023-06-06 15:52:25.626551768 +0200 +@@ -39,6 +39,11 @@ + u_int32_t *); + #endif + ++#ifdef HAVE_EC_KEY_METHOD_NEW ++int is_ecdsa_pkcs11(EC_KEY *ecdsa); ++#endif ++int is_rsa_pkcs11(RSA *rsa); ++ + #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) + #undef ENABLE_PKCS11 + #endif +diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh-rsa.c openssh-9.3p1-patched/ssh-rsa.c +--- openssh-9.3p1/ssh-rsa.c 2023-03-15 22:28:19.000000000 +0100 ++++ openssh-9.3p1-patched/ssh-rsa.c 2023-06-06 15:52:25.627551781 +0200 +@@ -23,6 +23,8 @@ + + #include + #include ++#include ++#include + + #include + #include +@@ -36,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/openssh-9.3p1-openssl-compat.patch b/openssh/openssh-9.3p1-openssl-compat.patch new file mode 100644 index 0000000..cf512ef --- /dev/null +++ b/openssh/openssh-9.3p1-openssl-compat.patch @@ -0,0 +1,40 @@ +--- 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/openssh-9.3p1-upstream-cve-2023-38408.patch b/openssh/openssh-9.3p1-upstream-cve-2023-38408.patch deleted file mode 100644 index 5632ba1..0000000 --- a/openssh/openssh-9.3p1-upstream-cve-2023-38408.patch +++ /dev/null @@ -1,17 +0,0 @@ -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 */ diff --git a/openssh/openssh-8.0p1-pkcs11-uri.patch b/openssh/openssh-9.3p2-pkcs11-uri.patch similarity index 88% rename from openssh/openssh-8.0p1-pkcs11-uri.patch rename to openssh/openssh-9.3p2-pkcs11-uri.patch index 8592607..ffaf98a 100644 --- a/openssh/openssh-8.0p1-pkcs11-uri.patch +++ b/openssh/openssh-9.3p2-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 -Naur a/configure.ac b/configure.ac +--- a/configure.ac 2023-10-20 19:13:59.336263852 +0600 ++++ b/configure.ac 2023-10-20 19:11:41.812164445 +0600 +@@ -2056,12 +2056,14 @@ [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]) +@@ -2085,6 +2087,40 @@ 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 +@@ -5692,6 +5728,7 @@ 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 -@@ -103,7 +103,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ +diff -Naur a/Makefile.in b/Makefile.in +--- a/Makefile.in 2023-10-20 19:13:59.290264154 +0600 ++++ b/Makefile.in 2023-10-20 19:11:41.813164439 +0600 +@@ -105,7 +105,7 @@ 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 \ @@ -76,8 +76,8 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in + ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ ssh-ed25519.o digest-openssl.o digest-libc.o \ - hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ -@@ -302,6 +302,8 @@ clean: regressclean + hmac.o ed25519.o hash.o \ +@@ -299,6 +299,8 @@ rm -f regress/unittests/sshsig/test_sshsig$(EXEEXT) rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8$(EXEEXT) @@ -86,16 +86,16 @@ 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 @@ 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 - (cd openbsd-compat && $(MAKE) distclean) - if test -d pkg ; then \ - rm -fr pkg ; \ -@@ -513,6 +517,7 @@ regress-prep: + 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 @@ $(MKDIR_P) `pwd`/regress/unittests/sshkey $(MKDIR_P) `pwd`/regress/unittests/sshsig $(MKDIR_P) `pwd`/regress/unittests/utf8 @@ -103,9 +103,9 @@ 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 -@@ -677,6 +682,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT +@@ -685,6 +690,17 @@ regress/unittests/test_helper/libtest_helper.a \ - -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) + -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(TESTLIBS) +UNITTESTS_TEST_PKCS11_OBJS=\ + regress/unittests/pkcs11/tests.o @@ -115,25 +115,26 @@ diff -up openssh-8.7p1/Makefile.in.pkcs11-uri openssh-8.7p1/Makefile.in + regress/unittests/test_helper/libtest_helper.a libssh.a + $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_PKCS11_OBJS) \ + regress/unittests/test_helper/libtest_helper.a \ -+ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) ++ -lssh -lopenbsd-compat -lcrypto $(LIBS) ++ + # These all need to be compiled -fPIC, so they are treated differently. SK_DUMMY_OBJS=\ regress/misc/sk-dummy/sk-dummy.lo \ -@@ -711,7 +726,8 @@ regress-unit-binaries: regress-prep $(RE +@@ -720,7 +736,8 @@ 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) \ ++ regress/unittests/pkcs11/test_pkcs11$(EXEEXT) tests: file-tests t-exec interop-tests unit echo all tests passed -diff -up openssh-8.7p1/regress/agent-pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/agent-pkcs11.sh ---- openssh-8.7p1/regress/agent-pkcs11.sh.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/regress/agent-pkcs11.sh 2021-08-30 13:07:43.663700096 +0200 -@@ -113,7 +113,7 @@ else +diff -Naur a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh +--- a/regress/agent-pkcs11.sh 2023-07-19 12:31:34.000000000 +0600 ++++ b/regress/agent-pkcs11.sh 2023-10-20 19:11:41.813164439 +0600 +@@ -113,7 +113,7 @@ done trace "remove pkcs11 keys" @@ -142,10 +143,10 @@ diff -up openssh-8.7p1/regress/agent-pkcs11.sh.pkcs11-uri openssh-8.7p1/regress/ 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 -Naur a/regress/Makefile b/regress/Makefile +--- a/regress/Makefile 2023-07-19 12:31:34.000000000 +0600 ++++ b/regress/Makefile 2023-10-20 19:11:41.813164439 +0600 +@@ -127,7 +127,8 @@ 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 +156,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: +@@ -258,8 +259,9 @@ V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ @@ -167,9 +168,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 -Naur a/regress/pkcs11.sh b/regress/pkcs11.sh +--- a/regress/pkcs11.sh 1970-01-01 06:00:00.000000000 +0600 ++++ b/regress/pkcs11.sh 2023-10-20 19:11:41.813164439 +0600 @@ -0,0 +1,349 @@ +# +# Copyright (c) 2017 Red Hat @@ -520,9 +521,10 @@ 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 -Naur a/regress/unittests/Makefile b/regress/unittests/Makefile +--- a/regress/unittests/Makefile 2023-07-19 12:31:34.000000000 +0600 ++++ b/regress/unittests/Makefile 2023-10-20 19:11:41.813164439 +0600 @@ -2,6 +2,6 @@ REGRESS_FAIL_EARLY?= yes @@ -531,10 +533,10 @@ 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 -@@ -0,0 +1,337 @@ +diff -Naur a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c +--- a/regress/unittests/pkcs11/tests.c 1970-01-01 06:00:00.000000000 +0600 ++++ b/regress/unittests/pkcs11/tests.c 2023-10-20 19:11:41.814164432 +0600 +@@ -0,0 +1,346 @@ +/* + * Copyright (c) 2017 Red Hat + * @@ -563,7 +565,7 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 +#include "sshbuf.h" +#include "ssh-pkcs11-uri.h" + -+#define EMPTY_URI compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL) ++#define EMPTY_URI compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL) + +/* prototypes are not public -- specify them here internally for tests */ +struct sshbuf *percent_encode(const char *, size_t, char *); @@ -596,6 +598,10 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 + ASSERT_STRING_EQ(a->lib_manuf, b->lib_manuf); + else /* both should be null */ + ASSERT_PTR_EQ(a->lib_manuf, b->lib_manuf); ++ if (b->serial != NULL) ++ ASSERT_STRING_EQ(a->serial, b->serial); ++ else /* both should be null */ ++ ASSERT_PTR_EQ(a->serial, b->serial); +} + +void @@ -630,7 +636,7 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 + +struct pkcs11_uri * +compose_uri(unsigned char *id, size_t id_len, char *token, char *lib_manuf, -+ char *manuf, char *module_path, char *object, char *pin) ++ char *manuf, char *serial, char *module_path, char *object, char *pin) +{ + struct pkcs11_uri *uri = pkcs11_uri_init(); + if (id_len > 0) { @@ -641,6 +647,7 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 + uri->token = token; + uri->lib_manuf = lib_manuf; + uri->manuf = manuf; ++ uri->serial = serial; + uri->object = object; + uri->pin = pin; + return uri; @@ -651,47 +658,49 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 +{ + /* path arguments */ + check_parse("pkcs11:id=%01", -+ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + check_parse("pkcs11:id=%00%01", -+ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + check_parse("pkcs11:token=SSH%20Keys", -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL, NULL)); + check_parse("pkcs11:library-manufacturer=OpenSC", -+ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL, NULL)); + check_parse("pkcs11:manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL)); ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL, NULL)); ++ check_parse("pkcs11:serial=IamSerial", ++ compose_uri(NULL, 0, NULL, NULL, NULL, "IamSerial", NULL, NULL, NULL)); + check_parse("pkcs11:object=SIGN%20Key", -+ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "SIGN Key", NULL)); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, "SIGN Key", NULL)); + /* query arguments */ + check_parse("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + check_parse("pkcs11:?pin-value=123456", -+ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, "123456")); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL, "123456")); + + /* combinations */ + /* ID SHOULD be percent encoded */ + check_parse("pkcs11:token=SSH%20Key;id=0", -+ compose_uri("0", 1, "SSH Key", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("0", 1, "SSH Key", NULL, NULL, NULL, NULL, NULL, NULL)); + check_parse( + "pkcs11:manufacturer=CAC?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, "CAC", ++ compose_uri(NULL, 0, NULL, NULL, "CAC", NULL, + "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + check_parse( + "pkcs11:object=RSA%20Key?module-path=/usr/lib64/pkcs11/opencryptoki.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, + "/usr/lib64/pkcs11/opencryptoki.so", "RSA Key", NULL)); + check_parse("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so&pin-value=123456", -+ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, "123456")); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, "123456")); + + /* empty path component matches everything */ + check_parse("pkcs11:", EMPTY_URI); + + /* empty string is a valid to match against (and different from NULL) */ + check_parse("pkcs11:token=", -+ compose_uri(NULL, 0, "", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "", NULL, NULL, NULL, NULL, NULL, NULL)); + /* Percent character needs to be percent-encoded */ + check_parse("pkcs11:token=%25", -+ compose_uri(NULL, 0, "%", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "%", NULL, NULL, NULL, NULL, NULL, NULL)); +} + +static void @@ -703,7 +712,7 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 + check_parse_rv("pkcs11:id=%ZZ", EMPTY_URI, -1); + /* Space MUST be percent encoded -- XXX not enforced yet */ + check_parse("pkcs11:token=SSH Keys", -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL, NULL)); + /* MUST NOT contain duplicate attributes of the same name */ + check_parse_rv("pkcs11:id=%01;id=%02", EMPTY_URI, -1); + /* MUST NOT contain duplicate attributes of the same name */ @@ -734,29 +743,31 @@ diff -up openssh-8.7p1/regress/unittests/pkcs11/tests.c.pkcs11-uri openssh-8.7p1 +{ + /* path arguments */ + check_gen("pkcs11:id=%01", -+ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + check_gen("pkcs11:id=%00%01", -+ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); + check_gen("pkcs11:token=SSH%20Keys", /* space must be percent encoded */ -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL, NULL)); + /* library-manufacturer is not implmented now */ + /*check_gen("pkcs11:library-manufacturer=OpenSC", -+ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL));*/ ++ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL, NULL));*/ + check_gen("pkcs11:manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL)); ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL, NULL)); ++ check_gen("pkcs11:serial=IamSerial", ++ compose_uri(NULL, 0, NULL, NULL, NULL, "IamSerial", NULL, NULL, NULL)); + check_gen("pkcs11:object=RSA%20Key", -+ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "RSA Key", NULL)); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, "RSA Key", NULL)); + /* query arguments */ + check_gen("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + + /* combinations */ + check_gen("pkcs11:id=%02;token=SSH%20Keys", -+ compose_uri("\x02", 1, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ compose_uri("\x02", 1, "SSH Keys", NULL, NULL, NULL, NULL, NULL, NULL)); + check_gen("pkcs11:id=%EE%02?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri("\xEE\x02", 2, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ compose_uri("\xEE\x02", 2, NULL, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + check_gen("pkcs11:object=Encryption%20Key;manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, "Encryption Key", NULL)); ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, "Encryption Key", NULL)); + + /* empty path component matches everything */ + check_gen("pkcs11:", EMPTY_URI); @@ -872,26 +883,28 @@ 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 @@ - #include "digest.h" +\ В конце файла нет новой строки +diff -Naur a/ssh-add.c b/ssh-add.c +--- a/ssh-add.c 2023-07-19 12:31:34.000000000 +0600 ++++ b/ssh-add.c 2023-10-20 19:11:41.814164432 +0600 +@@ -69,6 +69,7 @@ #include "ssh-sk.h" #include "sk-api.h" + #include "hostfile.h" +#include "ssh-pkcs11-uri.h" /* argv0 */ extern char *__progname; -@@ -229,6 +230,32 @@ delete_all(int agent_fd, int qflag) +@@ -230,6 +231,34 @@ return ret; } +#ifdef ENABLE_PKCS11 -+static int update_card(int, int, const char *, int, char *); ++static int update_card(int, int, const char *, int, struct dest_constraint **, size_t, char *); + +int -+update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag) ++update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag, ++ struct dest_constraint **dest_constraints, size_t ndest_constraints) +{ + char *pin = NULL; + struct pkcs11_uri *uri; @@ -909,19 +922,20 @@ 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, pin); ++ return update_card(agent_fd, adding, pkcs11_uri, qflag, ++ dest_constraints, ndest_constraints, pin); +} +#endif + static int add_file(int agent_fd, const char *filename, int key_only, int qflag, - const char *skprovider) -@@ -445,12 +472,11 @@ add_file(int agent_fd, const char *filen - } + const char *skprovider, struct dest_constraint **dest_constraints, +@@ -445,12 +474,11 @@ static int --update_card(int agent_fd, int add, const char *id, int qflag) -+update_card(int agent_fd, int add, const char *id, int qflag, char *pin) + 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) { - char *pin = NULL; int r, ret = -1; @@ -931,33 +945,34 @@ 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,13 @@ static int - do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, - const char *skprovider) +@@ -637,6 +665,14 @@ + const char *skprovider, struct dest_constraint **dest_constraints, + size_t ndest_constraints) { +#ifdef ENABLE_PKCS11 + if (strlen(file) >= strlen(PKCS11_URI_SCHEME) && + strncmp(file, PKCS11_URI_SCHEME, + strlen(PKCS11_URI_SCHEME)) == 0) { -+ return update_pkcs11_uri(agent_fd, !deleting, file, qflag); ++ return update_pkcs11_uri(agent_fd, !deleting, file, qflag, ++ dest_constraints, ndest_constraints); + } +#endif if (deleting) { if (delete_file(agent_fd, file, key_only, qflag) == -1) return -1; -@@ -813,7 +846,7 @@ main(int argc, char **argv) +@@ -963,7 +999,7 @@ } if (pkcs11provider != NULL) { if (update_card(agent_fd, !deleting, pkcs11provider, -- qflag) == -1) -+ qflag, NULL) == -1) +- qflag, dest_constraints, ndest_constraints) == -1) ++ qflag, dest_constraints, ndest_constraints, 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 -Naur a/ssh-agent.c b/ssh-agent.c +--- a/ssh-agent.c 2023-07-19 12:31:34.000000000 +0600 ++++ b/ssh-agent.c 2023-10-20 19:11:41.814164432 +0600 +@@ -1379,10 +1379,72 @@ } #ifdef ENABLE_PKCS11 @@ -1031,8 +1046,8 @@ 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"); +@@ -1408,33 +1470,28 @@ + "providers is disabled", provider); goto send; } - if (realpath(provider, canonical_provider) == NULL) { @@ -1043,7 +1058,6 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c - 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; @@ -1054,6 +1068,7 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c death = monotime() + lifetime; - count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments); ++ + debug_f("add %.100s", sane_uri); + count = pkcs11_add_provider(sane_uri, pin, &keys, &comments); for (i = 0; i < count; i++) { @@ -1073,15 +1088,15 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c } id->death = death; id->confirm = confirm; -@@ -910,6 +967,7 @@ process_add_smartcard_key(SocketEntry *e +@@ -1453,6 +1510,7 @@ send: free(pin); free(provider); + free(sane_uri); free(keys); free(comments); - send_status(e, success); -@@ -918,7 +976,7 @@ send: + free_dest_constraints(dest_constraints, ndest_constraints); +@@ -1462,7 +1520,7 @@ static void process_remove_smartcard_key(SocketEntry *e) { @@ -1090,7 +1105,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 +@@ -1474,30 +1532,28 @@ } free(pin); @@ -1108,8 +1123,9 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c nxt = TAILQ_NEXT(id, next); /* Skip file--based keys */ if (id->provider == NULL) - continue; +- continue; - if (!strcmp(canonical_provider, id->provider)) { ++ + if (!strcmp(sane_uri, id->provider)) { TAILQ_REMOVE(&idtab->idlist, id, next); free_identity(id); @@ -1122,40 +1138,15 @@ diff -up openssh-8.7p1/ssh-agent.c.pkcs11-uri openssh-8.7p1/ssh-agent.c else error_f("pkcs11_del_provider failed"); send: - free(provider); +- free(provider); + free(sane_uri); 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 - .Cm CertificateFile - in order to provide any certificate also needed for authentication with - the identity. -+.Pp -+The authentication identity can be also specified in a form of PKCS#11 URI -+starting with a string -+.Cm pkcs11: . -+There is supported a subset of the PKCS#11 URI as defined -+in RFC 7512 (implemented path arguments -+.Cm id , -+.Cm manufacturer , -+.Cm object , -+.Cm token -+and query arguments -+.Cm module-path -+and -+.Cm pin-value -+). The URI can not be in quotes. - .It Cm IgnoreUnknown - Specifies a pattern-list of unknown options to be ignored if they are - encountered in configuration parsing. -diff -up openssh-8.7p1/ssh.c.pkcs11-uri openssh-8.7p1/ssh.c ---- openssh-8.7p1/ssh.c.pkcs11-uri 2021-08-30 13:07:43.578699383 +0200 -+++ openssh-8.7p1/ssh.c 2021-08-30 13:07:43.666700121 +0200 -@@ -826,6 +826,14 @@ main(int ac, char **av) +diff -Naur a/ssh.c b/ssh.c +--- a/ssh.c 2023-10-20 19:13:59.298264101 +0600 ++++ b/ssh.c 2023-10-20 19:11:41.815164426 +0600 +@@ -840,6 +840,14 @@ options.gss_deleg_creds = 1; break; case 'i': @@ -1170,7 +1161,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) +@@ -1712,6 +1720,7 @@ #ifdef ENABLE_PKCS11 (void)pkcs11_del_provider(options.pkcs11_provider); #endif @@ -1178,7 +1169,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 +@@ -2228,6 +2237,45 @@ options.escape_char : SSH_ESCAPECHAR_NONE, id); } @@ -1224,7 +1215,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 +@@ -2242,11 +2290,6 @@ char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; @@ -1236,7 +1227,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 +@@ -2259,33 +2302,46 @@ sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 @@ -1302,10 +1293,35 @@ 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 -Naur a/ssh_config.5 b/ssh_config.5 +--- a/ssh_config.5 2023-10-20 19:13:59.299264095 +0600 ++++ b/ssh_config.5 2023-10-20 19:11:41.815164426 +0600 +@@ -1124,6 +1124,21 @@ + .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 -Naur a/ssh-keygen.c b/ssh-keygen.c +--- a/ssh-keygen.c 2023-07-19 12:31:34.000000000 +0600 ++++ b/ssh-keygen.c 2023-10-20 19:11:41.816164419 +0600 +@@ -866,8 +866,11 @@ free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ @@ -1319,30 +1335,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 - u_int nkeys, i; - struct sshbuf *msg; - -+ 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 - *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); - if (labelsp) - *labelsp = xcalloc(nkeys, sizeof(char *)); -+ debug_f("nkeys = %u", nkeys); - for (i = 0; i < nkeys; i++) { - /* XXX clean up properly instead of fatal() */ - if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || -diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c ---- openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri 2021-08-20 06:03:49.000000000 +0200 -+++ openssh-8.7p1/ssh-pkcs11.c 2021-08-30 13:12:27.709084157 +0200 -@@ -55,8 +55,8 @@ struct pkcs11_slotinfo { +diff -Naur a/ssh-pkcs11.c b/ssh-pkcs11.c +--- a/ssh-pkcs11.c 2023-07-19 12:31:34.000000000 +0600 ++++ b/ssh-pkcs11.c 2023-10-20 19:15:23.755711022 +0600 +@@ -55,8 +55,8 @@ int logged_in; }; @@ -1353,7 +1349,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c void *handle; CK_FUNCTION_LIST *function_list; CK_INFO info; -@@ -65,6 +65,13 @@ struct pkcs11_provider { +@@ -65,6 +65,13 @@ struct pkcs11_slotinfo *slotinfo; int valid; int refcount; @@ -1367,7 +1363,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c TAILQ_ENTRY(pkcs11_provider) next; }; -@@ -75,6 +82,7 @@ struct pkcs11_key { +@@ -75,6 +82,7 @@ CK_ULONG slotidx; char *keyid; int keyid_len; @@ -1375,7 +1371,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c }; int pkcs11_interactive = 0; -@@ -106,26 +114,61 @@ pkcs11_init(int interactive) +@@ -106,26 +114,61 @@ * this is called when a provider gets unregistered. */ static void @@ -1404,6 +1400,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c - 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); +- p->valid = 0; +- p->function_list = NULL; +- dlclose(p->handle); + m->valid = 0; + m->function_list = NULL; + dlclose(m->handle); @@ -1442,13 +1441,11 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + return; + pkcs11_module_unref(p->module); + p->module = NULL; - p->valid = 0; -- p->function_list = NULL; -- dlclose(p->handle); ++ p->valid = 0; } /* -@@ -137,11 +180,9 @@ pkcs11_provider_unref(struct pkcs11_prov +@@ -137,12 +180,10 @@ { debug_f("provider \"%s\" refcount %d", p->name, p->refcount); if (--p->refcount <= 0) { @@ -1457,12 +1454,13 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c free(p->name); - free(p->slotlist); - free(p->slotinfo); + free(p); + if (p->module) + pkcs11_module_unref(p->module); - free(p); } } -@@ -159,6 +200,20 @@ pkcs11_terminate(void) + +@@ -159,6 +200,20 @@ } } @@ -1483,7 +1481,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c /* lookup provider by name */ static struct pkcs11_provider * pkcs11_provider_lookup(char *provider_id) -@@ -173,19 +228,55 @@ pkcs11_provider_lookup(char *provider_id +@@ -173,19 +228,55 @@ return (NULL); } @@ -1493,6 +1491,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c int pkcs11_del_provider(char *provider_id) { +- struct pkcs11_provider *p; + int rv; + struct pkcs11_uri *uri; + @@ -1522,13 +1521,13 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c +int +pkcs11_del_provider_by_uri(struct pkcs11_uri *uri) +{ - struct pkcs11_provider *p; ++ 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); @@ -1542,9 +1541,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c } static RSA_METHOD *rsa_method; -@@ -195,6 +286,55 @@ static EC_KEY_METHOD *ec_key_method; +@@ -195,6 +286,56 @@ static int ec_key_idx = 0; - #endif + #endif /* OPENSSL_HAS_ECC && HAVE_EC_KEY_METHOD_NEW */ +/* + * This can't be in the ssh-pkcs11-uri, becase we can not depend on @@ -1584,6 +1583,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + 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 */ @@ -1598,7 +1598,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 @@ if (k11->provider) pkcs11_provider_unref(k11->provider); free(k11->keyid); @@ -1606,7 +1606,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 @@ CK_RV rv; int ret = -1; @@ -1617,9 +1617,12 @@ 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); -@@ -262,12 +403,12 @@ pkcs11_login_slot(struct pkcs11_provider +@@ -260,14 +402,14 @@ + 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 '%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) { @@ -1632,7 +1635,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 @@ static int pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) { @@ -1649,7 +1652,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 @@ *val = 0; @@ -1667,7 +1670,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 @@ int always_auth = 0; int did_login = 0; @@ -1685,7 +1688,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 @@ return (-1); } @@ -1696,7 +1699,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 @@ /* redirect private key operations for rsa key to pkcs11 token */ static int pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1705,7 +1708,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 @@ memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); } @@ -1718,7 +1721,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 @@ return (NULL); } @@ -1729,7 +1732,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 @@ static int pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, @@ -1738,20 +1741,40 @@ 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 - k11->keyid = xmalloc(k11->keyid_len); - memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); - +@@ -615,6 +766,11 @@ + 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; + } -+ EC_KEY_set_method(ec, ec_key_method); EC_KEY_set_ex_data(ec, ec_key_idx, k11); -@@ -650,8 +806,8 @@ pkcs11_open_session(struct pkcs11_provid +@@ -622,7 +778,8 @@ + } + #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 + rmspace(u_char *buf, size_t len) + { +@@ -630,8 +787,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; +@@ -651,8 +808,8 @@ CK_SESSION_HANDLE session; int login_required, ret; @@ -1762,7 +1785,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 +@@ -662,9 +819,9 @@ error("pin required"); return (-SSH_PKCS11_ERR_PIN_REQUIRED); } @@ -1774,7 +1797,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 * +@@ -700,7 +857,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1784,7 +1807,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_ +@@ -714,14 +872,15 @@ memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1805,7 +1828,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_ +@@ -732,19 +891,19 @@ * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1829,7 +1852,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_ +@@ -756,8 +915,8 @@ goto fail; } @@ -1840,7 +1863,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_ +@@ -768,13 +927,13 @@ goto fail; } @@ -1857,7 +1880,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_ +@@ -791,7 +950,7 @@ goto fail; } @@ -1866,7 +1889,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_ +@@ -807,7 +966,7 @@ ec = NULL; /* now owned by key */ fail: @@ -1875,7 +1898,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 * +@@ -824,7 +983,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj) { @@ -1885,7 +1908,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 +@@ -835,14 +995,15 @@ memset(&key_attr, 0, sizeof(key_attr)); key_attr[0].type = CKA_ID; @@ -1906,7 +1929,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 +@@ -853,19 +1014,19 @@ * ensure that none of the others are zero length. * XXX assumes CKA_ID is always first. */ @@ -1930,7 +1953,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 +@@ -877,8 +1038,8 @@ goto fail; } @@ -1941,7 +1964,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 +@@ -887,7 +1048,7 @@ fatal_f("set key"); rsa_n = rsa_e = NULL; /* transferred */ @@ -1950,7 +1973,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 +@@ -902,7 +1063,7 @@ rsa = NULL; /* now owned by key */ fail: @@ -1959,7 +1982,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 +@@ -913,7 +1074,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) { @@ -1969,7 +1992,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 +@@ -937,14 +1099,15 @@ memset(&cert_attr, 0, sizeof(cert_attr)); cert_attr[0].type = CKA_ID; @@ -1990,7 +2013,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 +@@ -956,18 +1119,19 @@ * XXX assumes CKA_ID is always first. */ if (cert_attr[1].ulValueLen == 0 || @@ -2013,7 +2036,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 +@@ -981,8 +1145,8 @@ subject = xstrdup("invalid subject"); X509_NAME_free(x509_name); @@ -2024,7 +2047,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 +@@ -1002,7 +1166,7 @@ goto out; } @@ -2033,7 +2056,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 +@@ -1032,7 +1196,7 @@ goto out; } @@ -2042,7 +2065,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 +@@ -1052,7 +1216,7 @@ goto out; } out: @@ -2051,7 +2074,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 +@@ -1103,11 +1267,12 @@ */ static int pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2066,12 +2089,13 @@ 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 +@@ -1124,10 +1289,24 @@ 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; @@ -2084,16 +2108,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: +@@ -1208,11 +1387,12 @@ */ static int pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, @@ -2108,7 +2132,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 +@@ -1228,10 +1408,23 @@ key_attr[0].pValue = &key_class; key_attr[0].ulValueLen = sizeof(key_class); @@ -2126,16 +2150,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 +@@ -1500,16 +1693,10 @@ } #endif /* WITH_PKCS11_KEYGEN */ @@ -2154,7 +2178,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,298 @@ pkcs11_register_provider(char *provider_ +@@ -1518,162 +1705,304 @@ CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; @@ -2179,6 +2203,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c - *keyp = NULL; - if (labelsp != NULL) - *labelsp = NULL; ++ + p = xcalloc(1, sizeof(*p)); + p->name = pkcs11_uri_get(uri); @@ -2202,7 +2227,6 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + 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()); @@ -2210,10 +2234,8 @@ 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; @@ -2240,20 +2262,12 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c 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 && -+ strcmp(uri->lib_manuf, m->info.manufacturerID)) { -+ debug_f("Skipping provider %s not matching library_manufacturer", -+ m->info.manufacturerID); goto fail; } - rmspace(p->info.manufacturerID, sizeof(p->info.manufacturerID)); - rmspace(p->info.libraryDescription, sizeof(p->info.libraryDescription)); -+ rmspace(m->info.libraryDescription, sizeof(m->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, - p->info.cryptokiVersion.major, @@ -2262,6 +2276,16 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c - 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, @@ -2318,6 +2342,9 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c 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", +- provider_id, (unsigned long)i, + } + m->module_path = provider_module; + provider_module = NULL; @@ -2386,22 +2413,28 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + continue; + } + if (uri->token != NULL && -+ strcmp(token->label, uri->token) != 0) { -+ debug2_f("ignoring token not matching label (%s) " ++ 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 && -+ strcmp(token->manufacturerID, uri->manuf) != 0) { ++ strncmp(token->manufacturerID, uri->manuf, 32) != 0) { + debug2_f("ignoring token not matching requrested " -+ "manufacturerID (%s) specified by PKCS#11 URI in " ++ "manufacturerID (%.32s) specified by PKCS#11 URI in " + "slot %lu", token->manufacturerID, (unsigned long)i); + continue; + } - debug("provider %s slot %lu: label <%s> manufacturerID <%s> " - "model <%s> serial <%s> flags 0x%lx", -- provider_id, (unsigned long)i, ++ 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); @@ -2440,7 +2473,7 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c + pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); + } + if (nkeys == 0 && uri->object != NULL) { -+ debug3_f("No keys found. Retrying without label (%s) ", ++ debug3_f("No keys found. Retrying without label (%.32s) ", + uri->object); + /* Try once more without the label filter */ + char *label = uri->object; @@ -2457,8 +2490,8 @@ diff -up openssh-8.7p1/ssh-pkcs11.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11.c - 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) @@ -2528,7 +2561,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) { -@@ -1683,7 +2002,37 @@ pkcs11_add_provider(char *provider_id, c +@@ -1682,7 +2011,37 @@ pkcs11_provider_unref(p); } if (nkeys == 0) @@ -2567,9 +2600,29 @@ 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 -Naur a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c +--- a/ssh-pkcs11-client.c 2023-07-19 12:31:34.000000000 +0600 ++++ b/ssh-pkcs11-client.c 2023-10-20 19:11:41.817164413 +0600 +@@ -323,6 +323,8 @@ + u_int nkeys, i; + struct sshbuf *msg; + ++ debug_f("called, name = %s", name); ++ + if (fd < 0 && pkcs11_start_helper() < 0) + return (-1); + +@@ -342,6 +344,7 @@ + *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); + if (labelsp) + *labelsp = xcalloc(nkeys, sizeof(char *)); ++ debug_f("nkeys = %u", nkeys); + for (i = 0; i < nkeys; i++) { + /* XXX clean up properly instead of fatal() */ + if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || +diff -Naur a/ssh-pkcs11.h b/ssh-pkcs11.h +--- a/ssh-pkcs11.h 2023-07-19 12:31:34.000000000 +0600 ++++ b/ssh-pkcs11.h 2023-10-20 19:11:41.817164413 +0600 @@ -22,10 +22,14 @@ #define SSH_PKCS11_ERR_PIN_REQUIRED 4 #define SSH_PKCS11_ERR_PIN_LOCKED 5 @@ -2585,10 +2638,10 @@ 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 -@@ -0,0 +1,419 @@ +diff -Naur a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c +--- a/ssh-pkcs11-uri.c 1970-01-01 06:00:00.000000000 +0600 ++++ b/ssh-pkcs11-uri.c 2023-10-20 19:11:41.817164413 +0600 +@@ -0,0 +1,437 @@ +/* + * Copyright (c) 2017 Red Hat + * @@ -2631,13 +2684,14 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. +#define PKCS11_URI_OBJECT "object" +#define PKCS11_URI_LIB_MANUF "library-manufacturer" +#define PKCS11_URI_MANUF "manufacturer" ++#define PKCS11_URI_SERIAL "serial" +#define PKCS11_URI_MODULE_PATH "module-path" +#define PKCS11_URI_PIN_VALUE "pin-value" + +/* Keyword tokens. */ +typedef enum { -+ pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pModulePath, -+ pPinValue, pBadOption ++ pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pSerial, ++ pModulePath, pPinValue, pBadOption +} pkcs11uriOpCodes; + +/* Textual representation of the tokens. */ @@ -2650,6 +2704,7 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. + { PKCS11_URI_OBJECT, pObject }, + { PKCS11_URI_LIB_MANUF, pLibraryManufacturer }, + { PKCS11_URI_MANUF, pManufacturer }, ++ { PKCS11_URI_SERIAL, pSerial }, + { PKCS11_URI_MODULE_PATH, pModulePath }, + { PKCS11_URI_PIN_VALUE, pPinValue }, + { NULL, pBadOption } @@ -2808,6 +2863,16 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. + goto err; + } + ++ /* Write serial */ ++ if (uri->serial) { ++ struct sshbuf *serial = percent_encode(uri->serial, ++ strlen(uri->serial), PKCS11_URI_WHITELIST); ++ path = pkcs11_uri_append(path, PKCS11_URI_PATH_SEPARATOR, ++ PKCS11_URI_SERIAL, serial); ++ if (path == NULL) ++ goto err; ++ } ++ + /* Write module_path */ + if (uri->module_path) { + struct sshbuf *module = percent_encode(uri->module_path, @@ -2850,6 +2915,7 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. + free(pkcs11->object); + free(pkcs11->lib_manuf); + free(pkcs11->manuf); ++ free(pkcs11->serial); + if (pkcs11->pin) + freezero(pkcs11->pin, strlen(pkcs11->pin)); + free(pkcs11); @@ -2945,6 +3011,11 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.c.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. + charptr = &pkcs11->manuf; + goto parse_string; + ++ case pSerial: ++ /* CK_TOKEN_INFO -> serialNumber */ ++ charptr = &pkcs11->serial; ++ goto parse_string; ++ + case pLibraryManufacturer: + /* CK_INFO -> manufacturerID */ + charptr = &pkcs11->lib_manuf; @@ -3008,9 +3079,10 @@ 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 -Naur a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h +--- a/ssh-pkcs11-uri.h 1970-01-01 06:00:00.000000000 +0600 ++++ b/ssh-pkcs11-uri.h 2023-10-20 19:11:41.818164406 +0600 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017 Red Hat @@ -3043,6 +3115,7 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. + char *object; + char *lib_manuf; + char *manuf; ++ char *serial; + /* query */ + char *module_path; + char *pin; /* Only parsed, but not printed */ @@ -3053,4 +3126,3 @@ diff -up openssh-8.7p1/ssh-pkcs11-uri.h.pkcs11-uri openssh-8.7p1/ssh-pkcs11-uri. +int pkcs11_uri_parse(const char *, struct pkcs11_uri *); +struct pkcs11_uri *pkcs11_uri_init(); +char *pkcs11_uri_get(struct pkcs11_uri *uri); -+ diff --git a/openssh/openssh-server-systemd-sysusers.conf b/openssh/openssh-server-systemd-sysusers.conf new file mode 100644 index 0000000..419c529 --- /dev/null +++ b/openssh/openssh-server-systemd-sysusers.conf @@ -0,0 +1,2 @@ +#Type Name ID GECOS Home directory Shell +u sshd 74 "Privilege-separated SSH" /usr/share/empty.sshd - diff --git a/openssh/openssh.pam b/openssh/openssh.pam new file mode 100644 index 0000000..0f5c061 --- /dev/null +++ b/openssh/openssh.pam @@ -0,0 +1,20 @@ +#%PAM-1.0 +auth required pam_sepermit.so +auth substack password-auth +auth include postlogin +# Used with polkit to reauthorize users in remote sessions +-auth optional pam_reauthorize.so prepare +account required pam_nologin.so +account include password-auth +password include password-auth +# pam_selinux.so close should be the first session rule +session required pam_selinux.so close +session required pam_loginuid.so +# pam_selinux.so open should only be followed by sessions to be executed in the user context +session required pam_selinux.so open env_params +session required pam_namespace.so +session optional pam_keyinit.so force revoke +session include password-auth +session include postlogin +# Used with polkit to reauthorize users in remote sessions +-session optional pam_reauthorize.so prepare diff --git a/openssh/openssh.spec b/openssh/openssh.spec index c6d0a1a..bb98d1d 100644 --- a/openssh/openssh.spec +++ b/openssh/openssh.spec @@ -1,8 +1,8 @@ -%bcond_with systemd -%bcond_with X11 -%bcond_with seccomp_filter - # Do we want SELinux & Audit +%if 0%{?rhel} < 7 +%global noselinux 1 +%endif + %if 0%{?!noselinux:1} %global WITH_SELINUX 1 %else @@ -11,18 +11,14 @@ %global _hardened_build 1 -# OpenSSH privilege separation requires a user & group ID -%global sshd_uid 74 -%global sshd_gid 74 - # Do we want to disable building of gnome-askpass? (1=yes 0=no) %global no_gnome_askpass 0 # Do we want to link against a static libcrypto? (1=yes 0=no) %global static_libcrypto 0 -# Use GTK2 instead of GNOME in gnome-ssh-askpass -%global gtk2 1 +# Use GTK2 in gnome-ssh-askpass +%global gtk3 0 # Build position-independent executables (requires toolchain support)? %global pie 1 @@ -33,9 +29,6 @@ # Do we want libedit support %global libedit 1 -# Do we want NSS tokens support -%define nss 1 - # Whether to build pam_ssh_agent_auth %if 0%{?!nopam:1} %global pam_ssh_agent 1 @@ -43,24 +36,30 @@ %global pam_ssh_agent 0 %endif +%if 0%{?fedora} || 0%{?rhel} >= 8 +%global _emptydir %{_datadir}/empty.sshd +%else +%global _emptydir %{_localstatedir}/empty/sshd +%endif + # Reserve options to override askpass settings with: # rpm -ba|--rebuild --define 'skip_xxx 1' %{?skip_gnome_askpass:%global no_gnome_askpass 1} # Add option to build without GTK2 for older platforms with only GTK+. # Red Hat Linux <= 7.2 and Red Hat Advanced Server 2.1 are examples. -# rpm -ba|--rebuild --define 'no_gtk2 1' -%{?no_gtk2:%global gtk2 0} +# rpm -ba|--rebuild --define 'no_gtk3 1' +%{?no_gtk3:%global gtk3 0} # Options for static OpenSSL link: # 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 8.8p1 -%global openssh_rel 8 +%global openssh_ver 9.3p2 +%global openssh_rel 2 %global pam_ssh_agent_ver 0.10.4 -%global pam_ssh_agent_rel 8 +%global pam_ssh_agent_rel 11 Summary: An open source implementation of SSH protocol version 2 Name: openssh @@ -70,7 +69,15 @@ 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 +%if 0%{?rhel} >= 8 Source2: sshd.pam +%else +%if 0%{?rhel} == 7 +Source2: sshd.pam.el7 +%else +Source2: sshd.pam.el6 +%endif +%endif 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 @@ -81,12 +88,17 @@ Source10: sshd.socket Source11: sshd.service Source12: sshd-keygen@.service Source13: sshd-keygen -Source14: sshd.init Source15: sshd-keygen.target Source16: ssh-agent.service +Source17: ssh-agent.socket +Source19: openssh-server-systemd-sysusers.conf +Source20: ssh-host-keys-migration.sh +Source21: ssh-host-keys-migration.service -Source20: openssh.ssh_config -Source21: openssh.sshd_config +Source22: openssh.pam +Source23: openssh.ssh_config +Source24: openssh.sshd_config +Source25: sshd.init #https://bugzilla.mindrot.org/show_bug.cgi?id=2581 Patch100: openssh-6.7p1-coverity.patch @@ -117,6 +129,7 @@ Patch306: pam_ssh_agent_auth-0.10.2-compat.patch 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 @@ -127,8 +140,6 @@ Patch502: openssh-6.6p1-keycat.patch #https://bugzilla.mindrot.org/show_bug.cgi?id=1644 Patch601: openssh-6.6p1-allow-ip-opts.patch -#https://bugzilla.mindrot.org/show_bug.cgi?id=1893 (WONTFIX) -Patch604: openssh-6.6p1-keyperm.patch #(drop?) https://bugzilla.mindrot.org/show_bug.cgi?id=1925 Patch606: openssh-5.9p1-ipv6man.patch #? @@ -146,12 +157,14 @@ Patch703: openssh-4.3p2-askpass-grab-info.patch Patch707: openssh-7.7p1-redhat.patch # warn users for unsupported UsePAM=no (#757545) Patch711: openssh-7.8p1-UsePAM-warning.patch -# make aes-ctr ciphers use EVP engines such as AES-NI from OpenSSL -Patch712: openssh-6.3p1-ctr-evp-fast.patch # GSSAPI Key Exchange (RFC 4462 + RFC 8732) # from https://github.com/openssh-gsskex/openssh-gsskex/tree/fedora/master -Patch800: openssh-8.0p1-gssapi-keyex.patch +# and +# Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures +# upstream MR: +# https://github.com/openssh-gsskex/openssh-gsskex/pull/21 +Patch800: openssh-9.3p1-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) @@ -191,13 +204,15 @@ Patch950: 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 +Patch951: openssh-9.3p2-pkcs11-uri.patch # Unbreak scp between two IPv6 hosts (#1620333) 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) -Patch963: openssh-8.0p1-openssl-evp.patch +# 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 @@ -208,16 +223,10 @@ Patch966: openssh-8.2p1-x11-without-ipv6.patch Patch974: openssh-8.0p1-keygen-strip-doseol.patch # sshd provides PAM an incorrect error code (#1879503) Patch975: openssh-8.0p1-preserve-pam-errors.patch -# Use SFTP protocol by default for scp command -Patch976: openssh-8.7p1-sftp-default-protocol.patch + # Implement kill switch for SCP protocol Patch977: openssh-8.7p1-scp-kill-switch.patch -# Create non-existent directories when scp works in sftp mode and some more minor fixes -# upstream commits: -# ba61123eef9c6356d438c90c1199a57a0d7bcb0a -# 63670d4e9030bcee490d5a9cce561373ac5b3b23 -# ac7c9ec894ed0825d04ef69c55babb49bab1d32e -Patch980: openssh-8.7p1-sftpscp-dir-create.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 @@ -225,62 +234,36 @@ Patch980: openssh-8.7p1-sftpscp-dir-create.patch Patch981: openssh-8.7p1-recursive-scp.patch # https://github.com/djmdjm/openssh-wip/pull/13 Patch982: openssh-8.7p1-minrsabits.patch -# downstream only -Patch983: openssh-8.7p1-evpgenkey.patch # downstream only, IBMCA tentative fix # From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14 Patch984: openssh-8.7p1-ibmca.patch -# Minimize the use of SHA1 as a proof of possession for RSA key (#2031868) -# upstream commits: -# 291721bc7c840d113a49518f3fca70e86248b8e8 -# 0fa33683223c76289470a954404047bc762be84c -Patch1000: openssh-8.7p1-minimize-sha1-use.patch -# Fix for scp clearing file when src and dest are the same (#2056884) -# upstream commits: -# 7b1cbcb7599d9f6a3bbad79d412604aa1203b5ee -Patch1001: openssh-8.7p1-scp-clears-file.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 -# Always return allocated strings from the kex filtering so that we can free them -# upstream commits: -# 486c4dc3b83b4b67d663fb0fa62bc24138ec3946 -# 6c31ba10e97b6953c4f325f526f3e846dfea647a -# 322964f8f2e9c321e77ebae1e4d2cd0ccc5c5a0b -Patch1003: openssh-8.7p1-mem-leak.patch -# Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures -# upstream MR: -# https://github.com/openssh-gsskex/openssh-gsskex/pull/21 -Patch1004: openssh-8.7p1-gssapi-auth.patch -# Fix host-based authentication with rsa keys -# upstream commits: -# 7aa7b096cf2bafe2777085abdeed5ce00581f641 -# d9dbb5d9a0326e252d3c7bc13beb9c2434f59409 -# fdb1d58d0d3888b042e5a500f6ce524486aaf782 -Patch1005: openssh-8.7p1-host-based-auth.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 -# CVE-2023-25136 -Patch1007: openssh-8.7p1-CVE-2023-25136.patch -# downstream only -# we skip some ssh-rsa/ssh-dss tests to make native test suite pass -Patch1100: openssh-8.8p1-skip-some-tests.patch -Patch1015: openssh-9.3p1-upstream-cve-2023-38408.patch +Patch1012: openssh-9.0p1-evp-fips-dh.patch +Patch1013: openssh-9.0p1-evp-fips-ecdh.patch +Patch1014: openssh-8.7p1-nohostsha1proof.patch -License: BSD +# 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 %if ! %{no_gnome_askpass} -%if %{gtk2} -BuildRequires: gtk2-devel BuildRequires: libX11-devel +%if %{gtk3} +BuildRequires: gtk3-devel %else -BuildRequires: gnome-libs-devel +BuildRequires: gtk2-devel %endif %endif @@ -288,25 +271,26 @@ BuildRequires: autoconf, automake, perl-interpreter, perl-generators, zlib-devel BuildRequires: audit-libs-devel >= 2.0.5 BuildRequires: util-linux, groff BuildRequires: pam-devel -BuildRequires: openssl3-devel -%if 0%{?rhel} < 7 -BuildRequires: perl -%else +BuildRequires: openssl3-devel >= 0.9.8j +%if 0%{?fedora} || 0%{?rhel} >= 7 BuildRequires: perl-podlators -%endif -%if %{with systemd} BuildRequires: systemd-devel BuildRequires: systemd-rpm-macros +%else +BuildRequires: perl +%endif +%if 0%{?fedora} || 0%{?rhel} >= 7 +BuildRequires: gcc +%else +BuildRequires: devtoolset-8-gcc devtoolset-8-build +%if 0%{?rhel} < 7 +BuildRequires: autoconf2.69 automake1.16 m4_next +%endif %endif BuildRequires: make -%if 0%{?rhel} <= 6 -BuildRequires: devtoolset-8-gcc devtoolset-8-gcc-c++ devtoolset-8-build -BuildRequires: autoconf automake1.16 m4 -%else -BuildRequires: gcc -%endif BuildRequires: p11-kit-devel BuildRequires: libfido2-devel +Requires: p11-kit Obsoletes: openssh-ldap < 8.3p1-4 Obsoletes: openssh-cavs < 8.4p1-5 @@ -318,26 +302,23 @@ BuildRequires: krb5-devel BuildRequires: libedit-devel ncurses-devel %endif -%if %{nss} -BuildRequires: nss-devel -%endif - %if %{WITH_SELINUX} Requires: libselinux BuildRequires: libselinux-devel Requires: audit-libs >= 1.0.8 BuildRequires: audit-libs >= 1.0.8 +BuildRequires: pkgconfig(libseccomp) %endif BuildRequires: xauth # for tarball signature verification BuildRequires: gnupg2 -Requires: openssh-clients = %{version}-%{release} %package clients Summary: An open source SSH client applications -%if 0%{?fedora} || 0%{?rhel} >= 8 -Requires: crypto-policies >= 20200610-1 +Requires: openssh = %{version}-%{release} +%if 0%{?rhel} >= 8 +Requires: crypto-policies >= 20220824-1 %endif %package server @@ -345,21 +326,15 @@ Summary: An open source SSH server daemon Requires: openssh = %{version}-%{release} Requires(pre): /usr/sbin/useradd Requires: pam >= 1.0.1-3 -%if 0%{?fedora} || 0%{?rhel} >= 8 -Requires: crypto-policies >= 20200610-1 +%if 0%{?rhel} >= 8 +Requires: crypto-policies >= 20220824-1 %endif -%if %{without systemd} -Requires(post): chkconfig >= 0.9, /sbin/service -%else +%if 0%{?fedora} || 0%{?rhel} >= 7 %{?systemd_requires} - -%package server-sysvinit -Summary: The SysV initscript to manage the OpenSSH server. -Group: System Environment/Daemons -Requires: %{name}-server%{?_isa} = %{version}-%{release} +%else +Requires(post): chkconfig >= 0.9, /sbin/service %endif - %package keycat Summary: A mls keycat backend for openssh Requires: openssh = %{version}-%{release} @@ -368,11 +343,15 @@ Requires: openssh = %{version}-%{release} Summary: A passphrase dialog for OpenSSH and X Requires: openssh = %{version}-%{release} +%package sk-dummy +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} -License: BSD +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 @@ -399,17 +378,6 @@ into and executing commands on a remote machine. This package contains the secure shell daemon (sshd). The sshd daemon allows SSH clients to securely connect to your SSH server. -%if %{with systemd} -%description server-sysvinit -OpenSSH is a free version of SSH (Secure SHell), a program for logging -into and executing commands on a remote machine. This package contains -the SysV init script to manage the OpenSSH server when running a legacy -SysV-compatible init system. - -It is not required when the init system used is systemd. -%endif - - %description keycat OpenSSH mls keycat is backend for using the authorized keys in the openssh in the mls mode. @@ -419,6 +387,9 @@ OpenSSH is a free version of SSH (Secure SHell), a program for logging into and executing commands on a remote machine. This package contains 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 @@ -439,6 +410,8 @@ pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} %patch306 -p2 -b .psaa-compat %patch305 -p2 -b .psaa-agent %patch307 -p2 -b .psaa-deref +%patch308 -p2 -b .rsasha2 +%patch309 -p1 -b .psaa-configure-c99 # Remove duplicate headers and library files rm -f $(cat %{SOURCE5}) popd @@ -450,7 +423,6 @@ popd %patch502 -p1 -b .keycat %patch601 -p1 -b .ip-opts -%patch604 -p1 -b .keyperm %patch606 -p1 -b .ipv6man %patch607 -p1 -b .sigpipe %patch609 -p1 -b .x11 @@ -458,7 +430,6 @@ popd %patch703 -p1 -b .grab-info %patch707 -p1 -b .redhat %patch711 -p1 -b .log-usepam-no -%patch712 -p1 -b .evp-ctr # %patch800 -p1 -b .gsskex %patch801 -p1 -b .force_krb @@ -480,42 +451,38 @@ popd %patch950 -p1 -b .sandbox %patch951 -p1 -b .pkcs11-uri %patch953 -p1 -b .scp-ipv6 -%if 0%{?fedora} || 0%{?rhel} >= 8 +%if 0%{?rhel} >= 8 %patch962 -p1 -b .crypto-policies -%if ! 0%{?rhel} == 8 +%endif %patch963 -p1 -b .openssl-evp -%endif -%endif %patch964 -p1 -b .openssl-kdf %patch965 -p1 -b .visibility %patch966 -p1 -b .x11-ipv6 %patch974 -p1 -b .keygen-strip-doseol %patch975 -p1 -b .preserve-pam-errors -%patch976 -p1 -b .sftp-by-default + %patch977 -p1 -b .kill-scp +%patch981 -p1 -b .scp-sftpdirs +%patch982 -p1 -b .minrsabits +%patch984 -p1 -b .ibmca + %patch200 -p1 -b .audit %patch201 -p1 -b .audit-race -#patch700 -p1 -b .fips -%patch1000 -p1 -b .minimize-sha1-use -%patch1001 -p1 -b .scp-clears-file -%patch1002 -p1 -b .ssh-manpage -%patch1003 -p1 -b .mem-leak -%patch1004 -p1 -b .gssapi-auth -%patch1005 -p1 -b .host-based-auth -%patch1006 -p1 -b .negotiate-supported-algs -%patch1007 -p1 -b .cve-2023-25136 +%patch202 -p1 -b .audit-log +%patch700 -p1 -b .fips -%patch1100 -p1 -b .skipsshrsadsstests +%patch1002 -p1 -b .ssh-manpage + +%patch1006 -p1 -b .negotiate-supported-algs + +%patch1012 -p1 -b .evp-fips-dh +%patch1013 -p1 -b .evp-fips-ecdh +%patch1014 -p1 -b .nosha1hostproof +%patch1016 -p1 -b .ossl-version %patch100 -p1 -b .coverity -%patch1015 -p1 -b .cve-2023-38408 - -%build -%if 0%{?rhel} < 8 -%enable_devtoolset8 -%endif %if 0%{?rhel} < 7 . /etc/profile.d/modules.sh module load autoconf @@ -528,17 +495,32 @@ pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} autoreconf popd +%build +%if 0%{?rhel} < 8 +%enable_devtoolset8 +%endif +%if 0%{?rhel} < 7 +. /etc/profile.d/modules.sh +module load autoconf +module load automake +module load m4 +%endif +%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="$RPM_OPT_FLAGS -I%{_includedir}/openssl3 -fvisibility=hidden"; export CFLAGS +CFLAGS="$CFLAGS -I%{_includedir}/openssl3 -fvisibility=hidden"; export CFLAGS %if %{pie} %ifarch s390 s390x sparc sparcv9 sparc64 CFLAGS="$CFLAGS -fPIC" %else CFLAGS="$CFLAGS -fpic" %endif -SAVE_LDFLAGS="$LDFLAGS -lrt" -LDFLAGS="$LDFLAGS -lrt -pie -z relro -z now" +SAVE_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS -pie -z relro -z now" + +%if 0%{?rhel} < 7 +LDFLAGS="$LDFLAGS -lrt" +%endif export CFLAGS export LDFLAGS @@ -564,33 +546,30 @@ fi --sysconfdir=%{_sysconfdir}/ssh \ --libexecdir=%{_libexecdir}/openssh \ --datadir=%{_datadir}/openssh \ + --enable-vendor-patchlevel="RHEL10-%{openssh_ver}-%{openssh_rel}" \ +%if 0%{?fedora} || 0%{?rhel} >= 7 + --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 \ +%else --with-default-path=/usr/local/bin:/bin:/usr/bin \ --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ - --with-privsep-path=%{_var}/empty/sshd \ - --enable-vendor-patchlevel="RHEL9-%{openssh_ver}-%{openssh_rel}" \ +%endif + --with-privsep-path=%{_emptydir} \ --disable-strip \ - --with-tcp-wrappers \ --without-zlib-version-check \ --with-ssl-engine \ --with-ipaddr-display \ --with-pie=no \ --without-hardening `# The hardening flags are configured by system` \ -%if %{nss} - --with-nss \ -%endif -%if %{with systemd} +%if 0%{?fedora} || 0%{?rhel} >= 7 --with-systemd \ %endif --with-default-pkcs11-provider=yes \ --with-security-key-builtin=yes \ --with-pam \ %if %{WITH_SELINUX} - --with-selinux --with-audit=linux \ -%if %{with seccomp_filter} - --with-sandbox=seccomp_filter \ -%else - --with-sandbox=rlimit \ -%endif + --with-selinux --with-audit=linux \ + --with-sandbox=seccomp_filter \ %endif %if %{kerberos5} --with-kerberos5${krb5_prefix:+=${krb5_prefix}} \ @@ -608,32 +587,38 @@ perl -pi -e "s|-lcrypto|%{_libdir}/libcrypto.a|g" Makefile %endif %make_build +make regress/misc/sk-dummy/sk-dummy.so -# Define a variable to toggle gnome1/gtk2 building. This is necessary +# Define a variable to toggle gtk2/gtk3 building. This is necessary # because RPM doesn't handle nested %%if statements. -%if %{gtk2} - gtk2=yes +%if %{gtk3} + gtk3=yes %else - gtk2=no + gtk3=no %endif %if ! %{no_gnome_askpass} pushd contrib -if [ $gtk2 = yes ] ; then +if [ $gtk3 = yes ] ; then + CFLAGS="$CFLAGS %{?__global_ldflags}" \ + make gnome-ssh-askpass3 + mv gnome-ssh-askpass3 gnome-ssh-askpass +else CFLAGS="$CFLAGS %{?__global_ldflags}" \ make gnome-ssh-askpass2 mv gnome-ssh-askpass2 gnome-ssh-askpass -else - CFLAGS="$CFLAGS %{?__global_ldflags}" - make gnome-ssh-askpass1 - mv gnome-ssh-askpass1 gnome-ssh-askpass fi popd %endif %if %{pam_ssh_agent} pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver} -LDFLAGS="$SAVE_LDFLAGS" +LDFLAGS="$SAVE_LDFLAGS -ldl" + +%if 0%{?rhel} < 7 +LDFLAGS="$LDFLAGS -lrt" +%endif + %configure --with-selinux \ --libexecdir=/%{_libdir}/security \ --with-mantype=man \ @@ -651,29 +636,29 @@ make tests %install rm -rf $RPM_BUILD_ROOT mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh -%if 0%{?fedora} || 0%{?rhel} >= 8 mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config.d mkdir -p -m755 $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config.d -%endif mkdir -p -m755 $RPM_BUILD_ROOT%{_libexecdir}/openssh %make_install install -d $RPM_BUILD_ROOT/etc/pam.d/ install -d $RPM_BUILD_ROOT/etc/sysconfig/ install -d $RPM_BUILD_ROOT%{_libexecdir}/openssh +install -m644 %{SOURCE2} $RPM_BUILD_ROOT/etc/pam.d/sshd +install -m644 %{SOURCE6} $RPM_BUILD_ROOT/etc/pam.d/ssh-keycat install -m644 %{SOURCE7} $RPM_BUILD_ROOT/etc/sysconfig/sshd %if 0%{?fedora} || 0%{?rhel} >= 8 -install -m644 ssh_config_redhat $RPM_BUILD_ROOT/etc/ssh/ssh_config.d/50-redhat.conf -install -m644 sshd_config_redhat $RPM_BUILD_ROOT/etc/ssh/sshd_config.d/50-redhat.conf +install -m644 ssh_config_redhat $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config.d/50-redhat.conf +install -m644 sshd_config_redhat_cp $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config.d/40-redhat-crypto-policies.conf +install -m644 sshd_config_redhat $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config.d/50-redhat.conf +install -m644 %{SOURCE2} $RPM_BUILD_ROOT/etc/pam.d/sshd %else -install -m 644 %{SOURCE20} $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config -install -m 644 %{SOURCE21} $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config +install -m 644 %{SOURCE23} $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ssh_config +install -m 644 %{SOURCE24} $RPM_BUILD_ROOT%{_sysconfdir}/ssh/sshd_config %endif -install -m 644 %{SOURCE2} $RPM_BUILD_ROOT/etc/pam.d/sshd -install -m644 %{SOURCE6} $RPM_BUILD_ROOT/etc/pam.d/ssh-keycat -install -d $RPM_BUILD_ROOT/etc/rc.d/init.d -install -m755 %{SOURCE14} $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd -%if %{with systemd} +install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT%{_bindir}/ +install contrib/ssh-copy-id.1 $RPM_BUILD_ROOT%{_mandir}/man1/ +%if 0%{?rhel} >= 7 install -d -m755 $RPM_BUILD_ROOT/%{_unitdir} install -m644 %{SOURCE9} $RPM_BUILD_ROOT/%{_unitdir}/sshd@.service install -m644 %{SOURCE10} $RPM_BUILD_ROOT/%{_unitdir}/sshd.socket @@ -682,11 +667,21 @@ install -m644 %{SOURCE12} $RPM_BUILD_ROOT/%{_unitdir}/sshd-keygen@.service install -m644 %{SOURCE15} $RPM_BUILD_ROOT/%{_unitdir}/sshd-keygen.target install -d -m755 $RPM_BUILD_ROOT/%{_userunitdir} install -m644 %{SOURCE16} $RPM_BUILD_ROOT/%{_userunitdir}/ssh-agent.service -%endif +install -m644 %{SOURCE17} $RPM_BUILD_ROOT/%{_userunitdir}/ssh-agent.socket install -m744 %{SOURCE13} $RPM_BUILD_ROOT/%{_libexecdir}/openssh/sshd-keygen -install -m755 contrib/ssh-copy-id $RPM_BUILD_ROOT%{_bindir}/ -install contrib/ssh-copy-id.1 $RPM_BUILD_ROOT%{_mandir}/man1/ -install -d -m711 ${RPM_BUILD_ROOT}/%{_var}/empty/sshd +install -d -m711 ${RPM_BUILD_ROOT}/%{_emptydir} +install -p -D -m 0644 %{SOURCE19} %{buildroot}%{_sysusersdir}/openssh-server.conf +# Migration service/script for Fedora 38 change to remove group ownership for standard host keys +# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +install -m744 %{SOURCE20} $RPM_BUILD_ROOT/%{_libexecdir}/openssh/ssh-host-keys-migration.sh +# Pulled-in via a `Wants=` in `sshd.service` & `sshd@.service` +install -m644 %{SOURCE21} $RPM_BUILD_ROOT/%{_unitdir}/ssh-host-keys-migration.service +install -d $RPM_BUILD_ROOT/%{_localstatedir}/lib +touch $RPM_BUILD_ROOT/%{_localstatedir}/lib/.ssh-host-keys-migration +%else +install -d $RPM_BUILD_ROOT/etc/rc.d/init.d +install -m755 %{SOURCE25} $RPM_BUILD_ROOT/etc/rc.d/init.d/sshd +%endif %if ! %{no_gnome_askpass} install contrib/gnome-ssh-askpass $RPM_BUILD_ROOT%{_libexecdir}/openssh/gnome-ssh-askpass @@ -710,6 +705,10 @@ 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 + %pre getent group ssh_keys >/dev/null || groupadd -r ssh_keys || : @@ -717,48 +716,68 @@ getent group ssh_keys >/dev/null || groupadd -r ssh_keys || : getent group sshd >/dev/null || groupadd -g %{sshd_uid} -r sshd || : getent passwd sshd >/dev/null || \ useradd -c "Privilege-separated SSH" -u %{sshd_uid} -g sshd \ - -s /sbin/nologin -r -d %{_var}/empty/sshd sshd 2> /dev/null || : + -s /sbin/nologin -r -d %{_emptydir} sshd 2> /dev/null || : -%if %{with systemd} %post server +%if 0%{?fedora} || 0%{?rhel} >= 7 %systemd_post sshd.service sshd.socket - -%preun server -%systemd_preun sshd.service sshd.socket - -%postun server -%systemd_postun_with_restart sshd.service - -%post clients -%systemd_user_post ssh-agent.service - -%preun clients -%systemd_user_preun ssh-agent.service %else -%post server /sbin/chkconfig --add sshd +%else -%postun server -/sbin/service sshd condrestart > /dev/null 2>&1 || : +%endif +%if 0%{?fedora} || 0%{?rhel} >= 8 +# Migration scriptlet for Fedora 31 and 32 installations to sshd_config +# drop-in directory (in F32+). +# Do this only if the file generated by anaconda exists, contains our config +# directive and sshd_config contains include directive as shipped in our package +%global sysconfig_anaconda /etc/sysconfig/sshd-permitrootlogin +test -f %{sysconfig_anaconda} && \ + test ! -f /etc/ssh/sshd_config.d/01-permitrootlogin.conf && \ + grep -q '^PERMITROOTLOGIN="-oPermitRootLogin=yes"' %{sysconfig_anaconda} && \ + grep -q '^Include /etc/ssh/sshd_config.d/\*.conf' /etc/ssh/sshd_config && \ + echo "PermitRootLogin yes" >> /etc/ssh/sshd_config.d/25-permitrootlogin.conf && \ + rm %{sysconfig_anaconda} || : +%endif %preun server +%if 0%{?fedora} || 0%{?rhel} >= 7 +%systemd_preun sshd.service sshd.socket +%else if [ "$1" = 0 ] then /sbin/service sshd stop > /dev/null 2>&1 || : /sbin/chkconfig --del sshd fi +%endif +%postun server +%if 0%{?fedora} || 0%{?rhel} >= 7 +%systemd_postun_with_restart sshd.service +%else +/sbin/service sshd condrestart > /dev/null 2>&1 || : +%endif + +%post clients +%if 0%{?fedora} || 0%{?rhel} >= 7 +%systemd_user_post ssh-agent.service +%systemd_user_post ssh-agent.socket +%endif + +%preun clients +%if 0%{?fedora} || 0%{?rhel} >= 7 +%systemd_user_preun ssh-agent.service +%systemd_user_preun ssh-agent.socket %endif %files -%doc LICENCE -%doc CREDITS ChangeLog OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns TODO +%doc CREDITS ChangeLog OVERVIEW PROTOCOL* README README.platform README.privsep README.tun README.dns TODO LICENCE %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli %attr(0755,root,root) %{_bindir}/ssh-keygen %attr(0644,root,root) %{_mandir}/man1/ssh-keygen.1* %attr(0755,root,root) %dir %{_libexecdir}/openssh -%attr(2555,root,ssh_keys) %{_libexecdir}/openssh/ssh-keysign +%attr(4555,root,root) %{_libexecdir}/openssh/ssh-keysign %attr(0644,root,root) %{_mandir}/man8/ssh-keysign.8* %files clients @@ -767,8 +786,8 @@ fi %attr(0755,root,root) %{_bindir}/scp %attr(0644,root,root) %{_mandir}/man1/scp.1* %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config -%if 0%{?fedora} || 0%{?rhel} >= 8 %dir %attr(0755,root,root) %{_sysconfdir}/ssh/ssh_config.d/ +%if 0%{?fedora} || 0%{?rhel} >= 8 %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config.d/50-redhat.conf %endif %attr(0644,root,root) %{_mandir}/man5/ssh_config.5* @@ -786,38 +805,40 @@ fi %attr(0644,root,root) %{_mandir}/man1/ssh-copy-id.1* %attr(0644,root,root) %{_mandir}/man8/ssh-pkcs11-helper.8* %attr(0644,root,root) %{_mandir}/man8/ssh-sk-helper.8* -%if %{with systemd} +%if 0%{?fedora} || 0%{?rhel} >= 7 %attr(0644,root,root) %{_userunitdir}/ssh-agent.service +%attr(0644,root,root) %{_userunitdir}/ssh-agent.socket %endif %files server -%dir %attr(0711,root,root) %{_var}/empty/sshd +%dir %attr(0711,root,root) %{_emptydir} %attr(0755,root,root) %{_sbindir}/sshd %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* %attr(0644,root,root) %{_mandir}/man5/moduli.5* %attr(0644,root,root) %{_mandir}/man8/sshd.8* %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config -%if 0%{?fedora} || 0%{?rhel} >= 8 %dir %attr(0700,root,root) %{_sysconfdir}/ssh/sshd_config.d/ +%if 0%{?fedora} || 0%{?rhel} >= 8 +%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config.d/40-redhat-crypto-policies.conf %attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config.d/50-redhat.conf %endif %attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd %attr(0640,root,root) %config(noreplace) /etc/sysconfig/sshd -%if %{without systemd} -%attr(0755,root,root) /etc/rc.d/init.d/sshd -%else +%if 0%{?fedora} || 0%{?rhel} >= 7 %attr(0644,root,root) %{_unitdir}/sshd.service %attr(0644,root,root) %{_unitdir}/sshd@.service %attr(0644,root,root) %{_unitdir}/sshd.socket %attr(0644,root,root) %{_unitdir}/sshd-keygen@.service %attr(0644,root,root) %{_unitdir}/sshd-keygen.target - -%files server-sysvinit -%defattr(-,root,root) +%attr(0644,root,root) %{_sysusersdir}/openssh-server.conf +%attr(0644,root,root) %{_unitdir}/ssh-host-keys-migration.service +%attr(0744,root,root) %{_libexecdir}/openssh/ssh-host-keys-migration.sh +%attr(0755,root,root) %{_libexecdir}/openssh/sshd-keygen +%ghost %attr(0644,root,root) %{_localstatedir}/lib/.ssh-host-keys-migration +%else %attr(0755,root,root) /etc/rc.d/init.d/sshd %endif @@ -833,19 +854,29 @@ fi %attr(0755,root,root) %{_libexecdir}/openssh/ssh-askpass %endif +%files sk-dummy +%attr(0755,root,root) %{_libdir}/sshtest/sk-dummy.so + %if %{pam_ssh_agent} %files -n pam_ssh_agent_auth +%if 0%{?fedora} || 0%{?rhel} >= 8 +%license pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}/OPENSSH_LICENSE +%else %doc pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}/OPENSSH_LICENSE +%endif %attr(0755,root,root) %{_libdir}/security/pam_ssh_agent_auth.so %attr(0644,root,root) %{_mandir}/man8/pam_ssh_agent_auth.8* %endif %changelog -* Fri Oct 6 2023 Raven - 8.8p1-8 -- Use /var/empty/sshd instead of /usr/share/emty.sshd +* Fri Oct 20 2023 Raven - 9.3p2-1 +- add pam config ported from proper rhel versions -* Fri Oct 6 2023 Raven - 8.8p1-6 -- add /bin and /sbin to PATH +* Fri Oct 20 2023 Raven - 9.3p2-1 +- New upstream release + +* Thu Oct 19 2023 Raven - 9.3p1-1 +- New upstream release * Tue Apr 12 2022 Raven - 8.8p1-4 - import ciphers and keyring settings from crypto-policies @@ -860,59 +891,37 @@ fi * Tue Apr 12 2022 Raven - 8.8p1-1 - New upstream release -* Mon Oct 25 2021 Dmitry Belyavskiy - 8.7p1-4 -- Fix memory leaks introduced in OpenSSH 8.7 - Related: rhbz#2001002 +* Wed Sep 29 2021 Dmitry Belyavskiy - 8.7p1-3 +- CVE-2021-41617 fix (#2008292) -* Tue Oct 19 2021 Dmitry Belyavskiy - 8.7p1-3 -- Disable locale forwarding in default configurations - Related: rhbz#2002734 +* Thu Sep 16 2021 Dmitry Belyavskiy - 8.7p1-2 +- Use SFTP protocol for scp by default (#2004956) -* Fri Oct 01 2021 Dmitry Belyavskiy - 8.7p1-2 -- Upstream fix for CVE-2021-41617 - Related: rhbz#2008886 +* Tue Sep 14 2021 Sahana Prasad - 8.7p1-1.1 +- Rebuilt with OpenSSL 3.0.0 -* Fri Sep 24 2021 Dmitry Belyavskiy - 8.7p1-1 + 0.10.4-4 -- New upstream release -- Switch to SFTP protocol in scp utility by default -- Enable SCP protocol kill switch - Related: rhbz#2001002 +* Wed Sep 01 2021 Dmitry Belyavskiy - 8.7p1-1 + 0.10.4-4 +- New upstream release (#1995893) -* Mon Aug 09 2021 Mohan Boddu - 8.6p1-7.1 -- Rebuilt for IMA sigs, glibc 2.34, aarch64 flags - Related: rhbz#1991688 +* Thu Jul 22 2021 Fedora Release Engineering - 8.6p1-5.1 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild -* Wed Jul 28 2021 Florian Weimer - 8.6p1-7 -- Rebuild to pick up OpenSSL 3.0 Beta ABI (#1984097) +* Mon Jun 21 2021 Dmitry Belyavskiy - 8.6p1-5 +- restore the blocking mode on standard output (#1942901) - upstream -* Mon Jun 21 2021 Dmitry Belyavskiy - 8.6p1-6 -- rebuilt - -* Wed Jun 16 2021 Mohan Boddu - 8.6p1-5.1 -- Rebuilt for RHEL 9 BETA for openssl 3.0 - Related: rhbz#1971065 - -* Thu Jun 03 2021 Dmitry Belyavskiy - 8.6p1-5 -- Remove recommendation of p11-kit (#1947904) - -* Tue Jun 01 2021 Dmitry Belyavskiy - 8.6p1-4 -- rebuilt +* Tue May 25 2021 Timm Bäder - 8.6p1-4 +- Use %%set_build_flags to set all builds flags * Fri May 21 2021 Dmitry Belyavskiy - 8.6p1-3 -- Hostbased ssh authentication fails if session ID contains a '/' (#1963058) +- Hostbased ssh authentication fails if session ID contains a '/' (#1963059) * Mon May 10 2021 Dmitry Belyavskiy - 8.6p1-2 -- rebuilt +- restore the blocking mode on standard output (#1942901) -* Thu May 06 2021 Dmitry Belyavskiy - 8.6p1-1 + 0.10.4-3 -- New upstream release (#1952957) -- GSS KEX broken beginning with (GSI-)OpenSSH 8.0p1 (#1957306) - -* Fri Apr 16 2021 Mohan Boddu - 8.5p1-3.1 -- Rebuilt for RHEL 9 BETA on Apr 15th 2021. Related: rhbz#1947937 - -* Tue Apr 13 2021 Dmitry Belyavskiy - 8.5p1-3 -- Coverity fixes for 8.5p1 (#1938831) +* Mon Apr 19 2021 Dmitry Belyavskiy - 8.6p1-1 + 0.10.4-3 +- New upstream release (#1950819) +- ssh-keygen printing fingerprint issue with Windows keys (#1901518) +- sshd provides PAM an incorrect error code (#1879503) * Tue Mar 09 2021 Rex Dieter - 8.5p1-2 - ssh-agent.serivce is user unit (#1761817#27) diff --git a/openssh/openssh.sshd_config b/openssh/openssh.sshd_config index 340d8bf..2faac88 100644 --- a/openssh/openssh.sshd_config +++ b/openssh/openssh.sshd_config @@ -3,7 +3,7 @@ # This is the sshd server system-wide configuration file. See # sshd_config(5) for more information. -# This sshd was compiled with PATH=/usr/local/bin:/usr/bin:/bin +# This sshd was compiled with PATH=/usr/local/bin:/usr/bin # The strategy used for options in the default sshd_config shipped with # OpenSSH is to specify options with their default value where @@ -36,14 +36,13 @@ CASignatureAlgorithms=ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp52 # Logging -#SyslogFacility AUTH SyslogFacility AUTHPRIV #LogLevel INFO # Authentication: #LoginGraceTime 2m -PermitRootLogin yes +#PermitRootLogin yes #StrictModes yes #MaxAuthTries 6 #MaxSessions 10 @@ -73,7 +72,6 @@ AuthorizedKeysFile .ssh/authorized_keys PasswordAuthentication yes # Change to no to disable s/key passwords -#ChallengeResponseAuthentication yes ChallengeResponseAuthentication no # Kerberos options @@ -110,7 +108,7 @@ X11Forwarding yes #X11DisplayOffset 10 #X11UseLocalhost yes #PermitTTY yes -#PrintMotd yes +PrintMotd no #PrintLastLog yes #TCPKeepAlive yes #UseLogin no diff --git a/openssh/pam_ssh_agent-configure-c99.patch b/openssh/pam_ssh_agent-configure-c99.patch new file mode 100644 index 0000000..bc40434 --- /dev/null +++ b/openssh/pam_ssh_agent-configure-c99.patch @@ -0,0 +1,249 @@ +configure.ac: Improve C99 compatibility + +Future compilers will not support implicit declarations and implicit +ints by default. This means that configure probes which rely on them +will fail unconditionally, without actually testing anything. + +The changes mostly mirror what has been implemented in the openssh +repository, but had to be adapted somewhat because of drift between +the two versions of configure.ac. + +Sam James has submitted similar fixes upstream: + + + +diff --git a/configure.ac b/configure.ac +index 6496679..d927b62 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -500,10 +500,10 @@ int main(void) { exit(0); } + AC_DEFINE(HAVE_BUNDLE, 1, [Define if your system uses bundles instead of ELF shared objects]) + AC_MSG_CHECKING(if we have working getaddrinfo) + AC_TRY_RUN([#include +-main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) +- exit(0); ++int main(void) { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) ++ return 0; + else +- exit(1); ++ return 1; + }], [AC_MSG_RESULT(working)], + [AC_MSG_RESULT(buggy) + AC_DEFINE(BROKEN_GETADDRINFO, 1, [getaddrinfo is broken (if present)])], +@@ -917,8 +917,8 @@ AC_SUBST(LDFLAGS_SHARED) + AC_MSG_CHECKING(compiler and flags for sanity) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([ +-#include +-int main(){exit(0);} ++#include ++int main(void){exit(0);} + ])], + [ AC_MSG_RESULT(yes) ], + [ +@@ -951,9 +951,9 @@ int main(int argc, char **argv) { + strncpy(buf,"/etc", 32); + s = dirname(buf); + if (!s || strncmp(s, "/", 32) != 0) { +- exit(1); ++ return 1; + } else { +- exit(0); ++ return 0; + } + } + ]])], +@@ -1102,7 +1102,7 @@ AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include + #include +-int main(void){struct dirent d;exit(sizeof(d.d_name)<=sizeof(char));} ++int main(void){struct dirent d;return sizeof(d.d_name)<=sizeof(char);} + ]])], + [AC_MSG_RESULT(yes)], + [ +@@ -1327,8 +1327,10 @@ AC_CHECK_FUNCS(setresuid, [ + AC_MSG_CHECKING(if setresuid seems to work) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ ++#define _GNU_SOURCE + #include + #include ++#include + int main(){errno=0; setresuid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0);} + ]])], + [AC_MSG_RESULT(yes)], +@@ -1344,8 +1346,10 @@ AC_CHECK_FUNCS(setresgid, [ + AC_MSG_CHECKING(if setresgid seems to work) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ ++#define _GNU_SOURCE + #include + #include ++#include + int main(){errno=0; setresgid(0,0,0); if (errno==ENOSYS) exit(1); else exit(0);} + ]])], + [AC_MSG_RESULT(yes)], +@@ -1384,7 +1388,7 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include +-int main(void){char b[5];snprintf(b,5,"123456789");exit(b[4]!='\0');} ++int main(void){char b[5];snprintf(b,5,"123456789");return b[4]!='\0';} + ]])], + [AC_MSG_RESULT(yes)], + [ +@@ -1418,7 +1422,7 @@ int x_snprintf(char *str,size_t count,const char *fmt,...) + int main(void) + { + char x[1]; +- exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1); ++ return x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1; + } ]])], + [AC_MSG_RESULT(yes)], + [ +@@ -1467,7 +1471,8 @@ AC_MSG_CHECKING([for (overly) strict mkstemp]) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include +-main() { char template[]="conftest.mkstemp-test"; ++#include ++int main(void) { char template[]="conftest.mkstemp-test"; + if (mkstemp(template) == -1) + exit(1); + unlink(template); exit(0); +@@ -1492,10 +1497,14 @@ if test ! -z "$check_for_openpty_ctty_bug"; then + AC_MSG_CHECKING(if openpty correctly handles controlling tty) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ ++#include + #include + #include + #include + #include ++#ifdef HAVE_PTY_H ++#include ++#endif + + int + main() +@@ -1543,6 +1552,7 @@ if test "x$ac_cv_func_getaddrinfo" = "xyes" && \ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include ++#include + #include + #include + #include +@@ -1748,6 +1758,7 @@ AC_TRY_LINK_FUNC(RAND_add, AC_DEFINE(HAVE_OPENSSL, 1, + AC_MSG_CHECKING([OpenSSL header version]) + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ ++#include + #include + #include + #include +@@ -1794,12 +1805,12 @@ int main(void) { + + fd = fopen(DATA,"w"); + if(fd == NULL) +- exit(1); ++ return 1; + + if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0) +- exit(1); ++ return 1; + +- exit(0); ++ return 0; + } + ]])], + [ +@@ -1829,7 +1840,7 @@ AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ + #include + #include +-int main(void) { exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1); } ++int main(void) { return SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1; } + ]])], + [ + AC_MSG_RESULT(yes) +@@ -2598,7 +2609,7 @@ dnl test snprintf (broken on SCO w/gcc) + #include + #include + #ifdef HAVE_SNPRINTF +-main() ++int main(void) + { + char buf[50]; + char expected_out[50]; +@@ -2611,11 +2622,11 @@ main() + strcpy(expected_out, "9223372036854775807"); + snprintf(buf, mazsize, "%lld", num); + if(strcmp(buf, expected_out) != 0) +- exit(1); +- exit(0); ++ return 1; ++ return 0; + } + #else +-main() { exit(0); } ++int main(void) { return 0; } + #endif + ]])], [ true ], [ AC_DEFINE(BROKEN_SNPRINTF) ], + AC_MSG_WARN([cross compiling: Assuming working snprintf()]) +@@ -2746,11 +2757,11 @@ AC_CACHE_CHECK([for msg_accrights field in struct msghdr], + int main() { + #ifdef msg_accrights + #error "msg_accrights is a macro" +-exit(1); ++return 1; + #endif + struct msghdr m; + m.msg_accrights = 0; +-exit(0); ++return 0; + } + ])], + [ ac_cv_have_accrights_in_msghdr="yes" ], +@@ -2773,11 +2784,11 @@ AC_CACHE_CHECK([for msg_control field in struct msghdr], + int main() { + #ifdef msg_control + #error "msg_control is a macro" +-exit(1); ++return 1; + #endif + struct msghdr m; + m.msg_control = 0; +-exit(0); ++return 0; + } + ])], + [ ac_cv_have_control_in_msghdr="yes" ], +@@ -2791,7 +2802,7 @@ if test "x$ac_cv_have_control_in_msghdr" = "xyes" ; then + fi + + AC_CACHE_CHECK([if libc defines __progname], ac_cv_libc_defines___progname, [ +- AC_TRY_LINK([], ++ AC_TRY_LINK([#include ], + [ extern char *__progname; printf("%s", __progname); ], + [ ac_cv_libc_defines___progname="yes" ], + [ ac_cv_libc_defines___progname="no" ] +@@ -2871,7 +2882,7 @@ if test "x$ac_cv_have_getopt_optreset" = "xyes" ; then + fi + + AC_CACHE_CHECK([if libc defines sys_errlist], ac_cv_libc_defines_sys_errlist, [ +- AC_TRY_LINK([], ++ AC_TRY_LINK([#include ], + [ extern const char *const sys_errlist[]; printf("%s", sys_errlist[0]);], + [ ac_cv_libc_defines_sys_errlist="yes" ], + [ ac_cv_libc_defines_sys_errlist="no" ] +@@ -2884,7 +2895,7 @@ fi + + + AC_CACHE_CHECK([if libc defines sys_nerr], ac_cv_libc_defines_sys_nerr, [ +- AC_TRY_LINK([], ++ AC_TRY_LINK([#include ], + [ extern int sys_nerr; printf("%i", sys_nerr);], + [ ac_cv_libc_defines_sys_nerr="yes" ], + [ ac_cv_libc_defines_sys_nerr="no" ] diff --git a/openssh/ssh-agent.service b/openssh/ssh-agent.service index c215022..812303c 100644 --- a/openssh/ssh-agent.service +++ b/openssh/ssh-agent.service @@ -5,10 +5,15 @@ ConditionEnvironment=!SSH_AGENT_PID Description=OpenSSH key agent Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1) +Requires=ssh-agent.socket [Service] Environment=SSH_AUTH_SOCK=%t/ssh-agent.socket -ExecStart=/usr/bin/ssh-agent -a $SSH_AUTH_SOCK +ExecStartPre=/usr/bin/rm -f $SSH_AUTH_SOCK +ExecStart=/usr/bin/ssh-agent -D -a $SSH_AUTH_SOCK PassEnvironment=SSH_AGENT_PID SuccessExitStatus=2 -Type=forking +Type=simple + +[Install] +Also=ssh-agent.socket diff --git a/openssh/ssh-agent.socket b/openssh/ssh-agent.socket new file mode 100644 index 0000000..d589cbc --- /dev/null +++ b/openssh/ssh-agent.socket @@ -0,0 +1,14 @@ +[Unit] +Description=OpenSSH key agent +Documentation=man:ssh-agent(1) man:ssh-add(1) man:ssh(1) + +[Socket] +ListenStream=%t/ssh-agent.socket +Service=ssh-agent.service +Priority=6 +Backlog=5 +SocketMode=0600 +DirectoryMode=0700 + +[Install] +WantedBy=sockets.target diff --git a/openssh/ssh-host-keys-migration.service b/openssh/ssh-host-keys-migration.service new file mode 100644 index 0000000..41e2c6b --- /dev/null +++ b/openssh/ssh-host-keys-migration.service @@ -0,0 +1,15 @@ +[Unit] +Description=Update OpenSSH host key permissions +Documentation=https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +Before=sshd.service +After=ssh-keygen.target +ConditionPathExists=!/var/lib/.ssh-host-keys-migration + +[Service] +Type=oneshot +ExecStart=-/usr/libexec/openssh/ssh-host-keys-migration.sh +ExecStart=touch /var/lib/.ssh-host-keys-migration +RemainAfterExit=yes + +[Install] +WantedBy=sshd.service diff --git a/openssh/ssh-host-keys-migration.sh b/openssh/ssh-host-keys-migration.sh new file mode 100644 index 0000000..083326e --- /dev/null +++ b/openssh/ssh-host-keys-migration.sh @@ -0,0 +1,36 @@ +#!/usr/bin/bash +set -eu -o pipefail +# Detect existing non-conforming host keys and perform the permissions migration +# https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +# +# Example output looks like: +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# Permissions 0640 for '/etc/ssh/ssh_host_rsa_key' are too open. +# It is required that your private key files are NOT accessible by others. +# This private key will be ignored. +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# Permissions 0640 for '/etc/ssh/ssh_host_ecdsa_key' are too open. +# It is required that your private key files are NOT accessible by others. +# This private key will be ignored. +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# @ WARNING: UNPROTECTED PRIVATE KEY FILE! @ +# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +# Permissions 0640 for '/etc/ssh/ssh_host_ed25519_key' are too open. +# It is required that your private key files are NOT accessible by others. +# This private key will be ignored. +# sshd: no hostkeys available -- exiting. +# +output="$(sshd -T 2>&1 || true)" # expected to fail +while read line; do + if [[ $line =~ ^Permissions\ [0-9]+\ for\ \'(.*)\'\ are\ too\ open. ]]; then + keyfile=${BASH_REMATCH[1]} + echo $line + echo -e "\t-> changing permissions on $keyfile" + chmod --verbose g-r $keyfile + chown --verbose root:root $keyfile + fi +done <<< "$output" diff --git a/openssh/sshd-keygen b/openssh/sshd-keygen index 141814c..170ada0 100644 --- a/openssh/sshd-keygen +++ b/openssh/sshd-keygen @@ -30,8 +30,7 @@ if ! $KEYGEN -q -t $KEYTYPE -f $KEY -C '' -N '' >&/dev/null; then fi # sanitize permissions -/usr/bin/chgrp ssh_keys $KEY -/usr/bin/chmod 640 $KEY +/usr/bin/chmod 600 $KEY /usr/bin/chmod 644 $KEY.pub if [[ -x /usr/sbin/restorecon ]]; then /usr/sbin/restorecon $KEY{,.pub} diff --git a/openssh/sshd.pam b/openssh/sshd.pam.el6 similarity index 100% rename from openssh/sshd.pam rename to openssh/sshd.pam.el6 diff --git a/openssh/sshd.service b/openssh/sshd.service index e8afb86..0cb2a26 100644 --- a/openssh/sshd.service +++ b/openssh/sshd.service @@ -3,6 +3,9 @@ Description=OpenSSH server daemon Documentation=man:sshd(8) man:sshd_config(5) After=network.target sshd-keygen.target Wants=sshd-keygen.target +# Migration for Fedora 38 change to remove group ownership for standard host keys +# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +Wants=ssh-host-keys-migration.service [Service] Type=notify diff --git a/openssh/sshd.sysconfig b/openssh/sshd.sysconfig index cdc3d39..a217ce7 100644 --- a/openssh/sshd.sysconfig +++ b/openssh/sshd.sysconfig @@ -1,16 +1,7 @@ # Configuration file for the sshd service. -# The server keys are automatically generated if they ommited -# to change the automatic creation uncomment the approprite -# line. - -# AUTOCREATE_SERVER_KEYS=RSAONLY -# AUTOCREATE_SERVER_KEYS=NO -AUTOCREATE_SERVER_KEYS=YES - -# Do not change this option unless you have hardware random -# generator and you REALLY know what you are doing/ - -export SSH_USE_STRONG_RNG=0 -# export SSH_USE_STRONG_RNG=1 - +# The server keys are automatically generated if they are missing. +# To change the automatic creation, adjust sshd.service options for +# 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. diff --git a/openssh/sshd@.service b/openssh/sshd@.service index 196c555..be6d3b9 100644 --- a/openssh/sshd@.service +++ b/openssh/sshd@.service @@ -3,6 +3,9 @@ Description=OpenSSH per-connection server daemon Documentation=man:sshd(8) man:sshd_config(5) Wants=sshd-keygen.target After=sshd-keygen.target +# Migration for Fedora 38 change to remove group ownership for standard host keys +# See https://fedoraproject.org/wiki/Changes/SSHKeySignSuidBit +Wants=ssh-host-keys-migration.service [Service] EnvironmentFile=-/etc/sysconfig/sshd