Compare commits
No commits in common. 'c9' and 'c10-beta' have entirely different histories.
@ -1,3 +1,2 @@
|
|||||||
SOURCES/gpgkey-736060BA.gpg
|
SOURCES/gpgkey-736060BA.gpg
|
||||||
SOURCES/openssh-8.7p1.tar.gz
|
SOURCES/openssh-9.8p1.tar.gz
|
||||||
SOURCES/pam_ssh_agent_auth-0.10.4.tar.gz
|
|
||||||
|
@ -1,3 +1,2 @@
|
|||||||
dbb35b4e9ae3f72b930a82c6fd5e83e9dcd7b193 SOURCES/gpgkey-736060BA.gpg
|
dbb35b4e9ae3f72b930a82c6fd5e83e9dcd7b193 SOURCES/gpgkey-736060BA.gpg
|
||||||
8719032c1e47732c8fdb14adfb24b5e9e71de802 SOURCES/openssh-8.7p1.tar.gz
|
a0bb501b11349f5c5c33a269351be091dc2c2727 SOURCES/openssh-9.8p1.tar.gz
|
||||||
66dd8274346fd006ff40f525c082cfb701085b5f SOURCES/pam_ssh_agent_auth-0.10.4.tar.gz
|
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
diff -up openssh-5.8p2/ssh-keyscan.c.sigpipe openssh-5.8p2/ssh-keyscan.c
|
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.sigpipe 2011-08-23 18:30:33.873025916 +0200
|
||||||
+++ openssh-5.8p2/ssh-keyscan.c 2011-08-23 18:32:24.574025362 +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);
|
fdlim_set(maxfd);
|
||||||
fdcon = xcalloc(maxfd, sizeof(con));
|
fdcon = xcalloc(maxfd, sizeof(con));
|
||||||
|
+
|
||||||
+ signal(SIGPIPE, SIG_IGN);
|
+ signal(SIGPIPE, SIG_IGN);
|
||||||
+
|
+
|
||||||
read_wait_nfdset = howmany(maxfd, NFDBITS);
|
read_wait = xcalloc(maxfd, sizeof(struct pollfd));
|
||||||
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));
|
for (j = 0; j < maxfd; j++)
|
||||||
|
read_wait[j].fd = -1;
|
||||||
|
|
||||||
|
@ -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);
|
|
@ -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 <errno.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
+#include <grp.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
@@ -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("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
|
|
@ -1,98 +0,0 @@
|
|||||||
commit 0e22b79bfde45a7cf7a2e51a68ec11c4285f3b31
|
|
||||||
Author: Jakub Jelen <jjelen@redhat.com>
|
|
||||||
Date: Mon Nov 21 15:04:06 2016 +0100
|
|
||||||
|
|
||||||
systemd stuff
|
|
||||||
|
|
||||||
diff --git a/configure.ac b/configure.ac
|
|
||||||
index 2ffc369..162ce92 100644
|
|
||||||
--- a/configure.ac
|
|
||||||
+++ b/configure.ac
|
|
||||||
@@ -4265,6 +4265,30 @@ AC_ARG_WITH([kerberos5],
|
|
||||||
AC_SUBST([GSSLIBS])
|
|
||||||
AC_SUBST([K5LIBS])
|
|
||||||
|
|
||||||
+# Check whether user wants systemd support
|
|
||||||
+SYSTEMD_MSG="no"
|
|
||||||
+AC_ARG_WITH(systemd,
|
|
||||||
+ [ --with-systemd Enable systemd support],
|
|
||||||
+ [ if test "x$withval" != "xno" ; then
|
|
||||||
+ AC_PATH_TOOL([PKGCONFIG], [pkg-config], [no])
|
|
||||||
+ if test "$PKGCONFIG" != "no"; then
|
|
||||||
+ AC_MSG_CHECKING([for libsystemd])
|
|
||||||
+ if $PKGCONFIG --exists libsystemd; then
|
|
||||||
+ SYSTEMD_CFLAGS=`$PKGCONFIG --cflags libsystemd`
|
|
||||||
+ SYSTEMD_LIBS=`$PKGCONFIG --libs libsystemd`
|
|
||||||
+ CPPFLAGS="$CPPFLAGS $SYSTEMD_CFLAGS"
|
|
||||||
+ SSHDLIBS="$SSHDLIBS $SYSTEMD_LIBS"
|
|
||||||
+ AC_MSG_RESULT([yes])
|
|
||||||
+ AC_DEFINE(HAVE_SYSTEMD, 1, [Define if you want systemd support.])
|
|
||||||
+ SYSTEMD_MSG="yes"
|
|
||||||
+ else
|
|
||||||
+ AC_MSG_RESULT([no])
|
|
||||||
+ fi
|
|
||||||
+ fi
|
|
||||||
+ fi ]
|
|
||||||
+)
|
|
||||||
+
|
|
||||||
+
|
|
||||||
# Looking for programs, paths and files
|
|
||||||
|
|
||||||
PRIVSEP_PATH=/var/empty
|
|
||||||
@@ -5097,6 +5121,7 @@ echo " libedit support: $LIBEDIT_MSG"
|
|
||||||
echo " Solaris process contract support: $SPC_MSG"
|
|
||||||
echo " Solaris project support: $SP_MSG"
|
|
||||||
echo " Solaris privilege support: $SPP_MSG"
|
|
||||||
+echo " systemd support: $SYSTEMD_MSG"
|
|
||||||
echo " IP address in \$DISPLAY hack: $DISPLAY_HACK_MSG"
|
|
||||||
echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
|
|
||||||
echo " BSD Auth support: $BSD_AUTH_MSG"
|
|
||||||
diff --git a/contrib/sshd.service b/contrib/sshd.service
|
|
||||||
new file mode 100644
|
|
||||||
index 0000000..e0d4923
|
|
||||||
--- /dev/null
|
|
||||||
+++ b/contrib/sshd.service
|
|
||||||
@@ -0,0 +1,16 @@
|
|
||||||
+[Unit]
|
|
||||||
+Description=OpenSSH server daemon
|
|
||||||
+Documentation=man:sshd(8) man:sshd_config(5)
|
|
||||||
+After=network.target
|
|
||||||
+
|
|
||||||
+[Service]
|
|
||||||
+Type=notify
|
|
||||||
+ExecStart=/usr/sbin/sshd -D $OPTIONS
|
|
||||||
+ExecReload=/bin/kill -HUP $MAINPID
|
|
||||||
+KillMode=process
|
|
||||||
+Restart=on-failure
|
|
||||||
+RestartPreventExitStatus=255
|
|
||||||
+
|
|
||||||
+[Install]
|
|
||||||
+WantedBy=multi-user.target
|
|
||||||
+
|
|
||||||
diff --git a/sshd.c b/sshd.c
|
|
||||||
index 816611c..b8b9d13 100644
|
|
||||||
--- a/sshd.c
|
|
||||||
+++ b/sshd.c
|
|
||||||
@@ -85,6 +85,10 @@
|
|
||||||
#include <prot.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+#ifdef HAVE_SYSTEMD
|
|
||||||
+#include <systemd/sd-daemon.h>
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "ssh.h"
|
|
||||||
#include "ssh2.h"
|
|
||||||
@@ -1888,6 +1892,11 @@ main(int ac, char **av)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+#ifdef HAVE_SYSTEMD
|
|
||||||
+ /* Signal systemd that we are ready to accept connections */
|
|
||||||
+ sd_notify(0, "READY=1");
|
|
||||||
+#endif
|
|
||||||
+
|
|
||||||
/* Accept a connection and return in a forked child */
|
|
||||||
server_accept_loop(&sock_in, &sock_out,
|
|
||||||
&newsock, config_s);
|
|
File diff suppressed because it is too large
Load Diff
@ -1,720 +0,0 @@
|
|||||||
From ed7ec0cdf577ffbb0b15145340cf51596ca3eb89 Mon Sep 17 00:00:00 2001
|
|
||||||
From: Jakub Jelen <jjelen@redhat.com>
|
|
||||||
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 <openssl/evp.h>
|
|
||||||
+/* 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 **);
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,323 +0,0 @@
|
|||||||
diff --git a/misc.c b/misc.c
|
|
||||||
index a8e87430..f2135803 100644
|
|
||||||
--- a/misc.c
|
|
||||||
+++ b/misc.c
|
|
||||||
@@ -2399,15 +2399,26 @@ parse_absolute_time(const char *s, uint64_t *tp)
|
|
||||||
struct tm tm;
|
|
||||||
time_t tt;
|
|
||||||
char buf[32], *fmt;
|
|
||||||
+ const char *cp;
|
|
||||||
+ size_t l;
|
|
||||||
+ int is_utc = 0;
|
|
||||||
|
|
||||||
*tp = 0;
|
|
||||||
|
|
||||||
+ l = strlen(s);
|
|
||||||
+ if (l > 1 && strcasecmp(s + l - 1, "Z") == 0) {
|
|
||||||
+ is_utc = 1;
|
|
||||||
+ l--;
|
|
||||||
+ } else if (l > 3 && strcasecmp(s + l - 3, "UTC") == 0) {
|
|
||||||
+ is_utc = 1;
|
|
||||||
+ l -= 3;
|
|
||||||
+ }
|
|
||||||
/*
|
|
||||||
* POSIX strptime says "The application shall ensure that there
|
|
||||||
* is white-space or other non-alphanumeric characters between
|
|
||||||
* any two conversion specifications" so arrange things this way.
|
|
||||||
*/
|
|
||||||
- switch (strlen(s)) {
|
|
||||||
+ switch (l) {
|
|
||||||
case 8: /* YYYYMMDD */
|
|
||||||
fmt = "%Y-%m-%d";
|
|
||||||
snprintf(buf, sizeof(buf), "%.4s-%.2s-%.2s", s, s + 4, s + 6);
|
|
||||||
@@ -2427,10 +2438,15 @@ parse_absolute_time(const char *s, uint64_t *tp)
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&tm, 0, sizeof(tm));
|
|
||||||
- if (strptime(buf, fmt, &tm) == NULL)
|
|
||||||
- return SSH_ERR_INVALID_FORMAT;
|
|
||||||
- if ((tt = mktime(&tm)) < 0)
|
|
||||||
+ if ((cp = strptime(buf, fmt, &tm)) == NULL || *cp != '\0')
|
|
||||||
return SSH_ERR_INVALID_FORMAT;
|
|
||||||
+ if (is_utc) {
|
|
||||||
+ if ((tt = timegm(&tm)) < 0)
|
|
||||||
+ return SSH_ERR_INVALID_FORMAT;
|
|
||||||
+ } else {
|
|
||||||
+ if ((tt = mktime(&tm)) < 0)
|
|
||||||
+ return SSH_ERR_INVALID_FORMAT;
|
|
||||||
+ }
|
|
||||||
/* success */
|
|
||||||
*tp = (uint64_t)tt;
|
|
||||||
return 0;
|
|
||||||
diff --git a/regress/unittests/misc/test_convtime.c b/regress/unittests/misc/test_convtime.c
|
|
||||||
index ef6fd77d..4794dbd9 100644
|
|
||||||
--- a/regress/unittests/misc/test_convtime.c
|
|
||||||
+++ b/regress/unittests/misc/test_convtime.c
|
|
||||||
@@ -20,6 +20,7 @@
|
|
||||||
|
|
||||||
#include "log.h"
|
|
||||||
#include "misc.h"
|
|
||||||
+#include "ssherr.h"
|
|
||||||
|
|
||||||
void test_convtime(void);
|
|
||||||
|
|
||||||
@@ -27,6 +28,7 @@ void
|
|
||||||
test_convtime(void)
|
|
||||||
{
|
|
||||||
char buf[1024];
|
|
||||||
+ uint64_t t;
|
|
||||||
|
|
||||||
TEST_START("misc_convtime");
|
|
||||||
ASSERT_INT_EQ(convtime("0"), 0);
|
|
||||||
@@ -56,4 +58,64 @@ test_convtime(void)
|
|
||||||
ASSERT_INT_EQ(convtime("3550w5d3h14m8s"), -1);
|
|
||||||
#endif
|
|
||||||
TEST_DONE();
|
|
||||||
+
|
|
||||||
+ /* XXX timezones/DST make verification of this tricky */
|
|
||||||
+ /* XXX maybe setenv TZ and tzset() to make it unambiguous? */
|
|
||||||
+ TEST_START("misc_parse_absolute_time");
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101", &t), 0);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("200001011223", &t), 0);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101122345", &t), 0);
|
|
||||||
+
|
|
||||||
+ /* forced UTC TZ */
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101Z", &t), 0);
|
|
||||||
+ ASSERT_U64_EQ(t, 946684800);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("200001011223Z", &t), 0);
|
|
||||||
+ ASSERT_U64_EQ(t, 946729380);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101122345Z", &t), 0);
|
|
||||||
+ ASSERT_U64_EQ(t, 946729425);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101UTC", &t), 0);
|
|
||||||
+ ASSERT_U64_EQ(t, 946684800);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("200001011223UTC", &t), 0);
|
|
||||||
+ ASSERT_U64_EQ(t, 946729380);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101122345UTC", &t), 0);
|
|
||||||
+ ASSERT_U64_EQ(t, 946729425);
|
|
||||||
+
|
|
||||||
+ /* Bad month */
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20001301", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000001", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ /* Incomplete */
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("2", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("2000", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("200001", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("2000010", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("200001010", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ /* Bad day, hour, minute, second */
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000199", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("200001019900", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("200001010099", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101000099", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ /* Invalid TZ specifier */
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101ZZ", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101PDT", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101U", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+ ASSERT_INT_EQ(parse_absolute_time("20000101UTCUTC", &t),
|
|
||||||
+ SSH_ERR_INVALID_FORMAT);
|
|
||||||
+
|
|
||||||
+ TEST_DONE();
|
|
||||||
}
|
|
||||||
diff --git a/ssh-keygen.1 b/ssh-keygen.1
|
|
||||||
index 5f429813..6aeab1cb 100644
|
|
||||||
--- a/ssh-keygen.1
|
|
||||||
+++ b/ssh-keygen.1
|
|
||||||
@@ -511,8 +511,11 @@ Print the full public key to standard output after signature verification.
|
|
||||||
.It Cm verify-time Ns = Ns Ar timestamp
|
|
||||||
Specifies a time to use when validating signatures instead of the current
|
|
||||||
time.
|
|
||||||
-The time may be specified as a date in YYYYMMDD format or a time
|
|
||||||
-in YYYYMMDDHHMM[SS] format.
|
|
||||||
+The time may be specified as a date or time in the YYYYMMDD[Z] or
|
|
||||||
+in YYYYMMDDHHMM[SS][Z] formats.
|
|
||||||
+Dates and times will be interpreted in the current system time zone unless
|
|
||||||
+suffixed with a Z character, which causes them to be interpreted in the
|
|
||||||
+UTC time zone.
|
|
||||||
.El
|
|
||||||
.Pp
|
|
||||||
The
|
|
||||||
@@ -603,31 +606,67 @@ A validity interval may consist of a single time, indicating that the
|
|
||||||
certificate is valid beginning now and expiring at that time, or may consist
|
|
||||||
of two times separated by a colon to indicate an explicit time interval.
|
|
||||||
.Pp
|
|
||||||
-The start time may be specified as the string
|
|
||||||
+The start time may be specified as:
|
|
||||||
+.Bl -bullet -compact
|
|
||||||
+.It
|
|
||||||
+The string
|
|
||||||
.Dq always
|
|
||||||
-to indicate the certificate has no specified start time,
|
|
||||||
-a date in YYYYMMDD format, a time in YYYYMMDDHHMM[SS] format,
|
|
||||||
-a relative time (to the current time) consisting of a minus sign followed by
|
|
||||||
-an interval in the format described in the
|
|
||||||
+to indicate the certificate has no specified start time.
|
|
||||||
+.It
|
|
||||||
+A date or time in the system time zone formatted as YYYYMMDD or
|
|
||||||
+YYYYMMDDHHMM[SS].
|
|
||||||
+.It
|
|
||||||
+A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMDDHHMM[SS]Z.
|
|
||||||
+.It
|
|
||||||
+A relative time before the current system time consisting of a minus sign
|
|
||||||
+followed by an interval in the format described in the
|
|
||||||
TIME FORMATS section of
|
|
||||||
.Xr sshd_config 5 .
|
|
||||||
+.It
|
|
||||||
+A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a hexadecimal
|
|
||||||
+number beginning with
|
|
||||||
+.Dq 0x .
|
|
||||||
+.El
|
|
||||||
.Pp
|
|
||||||
-The end time may be specified as a YYYYMMDD date, a YYYYMMDDHHMM[SS] time,
|
|
||||||
-a relative time starting with a plus character or the string
|
|
||||||
+The end time may be specified similarly to the start time:
|
|
||||||
+.Bl -bullet -compact
|
|
||||||
+.It
|
|
||||||
+The string
|
|
||||||
.Dq forever
|
|
||||||
-to indicate that the certificate has no expiry date.
|
|
||||||
+to indicate the certificate has no specified end time.
|
|
||||||
+.It
|
|
||||||
+A date or time in the system time zone formatted as YYYYMMDD or
|
|
||||||
+YYYYMMDDHHMM[SS].
|
|
||||||
+.It
|
|
||||||
+A date or time in the UTC time zone as YYYYMMDDZ or YYYYMMDDHHMM[SS]Z.
|
|
||||||
+.It
|
|
||||||
+A relative time after the current system time consisting of a plus sign
|
|
||||||
+followed by an interval in the format described in the
|
|
||||||
+TIME FORMATS section of
|
|
||||||
+.Xr sshd_config 5 .
|
|
||||||
+.It
|
|
||||||
+A raw seconds since epoch (Jan 1 1970 00:00:00 UTC) as a hexadecimal
|
|
||||||
+number beginning with
|
|
||||||
+.Dq 0x .
|
|
||||||
+.El
|
|
||||||
.Pp
|
|
||||||
For example:
|
|
||||||
-.Dq +52w1d
|
|
||||||
-(valid from now to 52 weeks and one day from now),
|
|
||||||
-.Dq -4w:+4w
|
|
||||||
-(valid from four weeks ago to four weeks from now),
|
|
||||||
-.Dq 20100101123000:20110101123000
|
|
||||||
-(valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011),
|
|
||||||
-.Dq -1d:20110101
|
|
||||||
-(valid from yesterday to midnight, January 1st, 2011),
|
|
||||||
-.Dq -1m:forever
|
|
||||||
-(valid from one minute ago and never expiring).
|
|
||||||
+.Bl -tag -width Ds
|
|
||||||
+.It +52w1d
|
|
||||||
+Valid from now to 52 weeks and one day from now.
|
|
||||||
+.It -4w:+4w
|
|
||||||
+Valid from four weeks ago to four weeks from now.
|
|
||||||
+.It 20100101123000:20110101123000
|
|
||||||
+Valid from 12:30 PM, January 1st, 2010 to 12:30 PM, January 1st, 2011.
|
|
||||||
+.It 20100101123000Z:20110101123000Z
|
|
||||||
+Similar, but interpreted in the UTC time zone rather than the system time zone.
|
|
||||||
+.It -1d:20110101
|
|
||||||
+Valid from yesterday to midnight, January 1st, 2011.
|
|
||||||
+.It 0x1:0x2000000000
|
|
||||||
+Valid from roughly early 1970 to May 2033.
|
|
||||||
+.It -1m:forever
|
|
||||||
+Valid from one minute ago and never expiring.
|
|
||||||
+.El
|
|
||||||
.It Fl v
|
|
||||||
Verbose mode.
|
|
||||||
Causes
|
|
||||||
@@ -1206,7 +1245,10 @@ signature object and presented on the verification command-line must
|
|
||||||
match the specified list before the key will be considered acceptable.
|
|
||||||
.It Cm valid-after Ns = Ns "timestamp"
|
|
||||||
Indicates that the key is valid for use at or after the specified timestamp,
|
|
||||||
-which may be a date in YYYYMMDD format or a time in YYYYMMDDHHMM[SS] format.
|
|
||||||
+which may be a date or time in the YYYYMMDD[Z] or YYYYMMDDHHMM[SS][Z] formats.
|
|
||||||
+Dates and times will be interpreted in the current system time zone unless
|
|
||||||
+suffixed with a Z character, which causes them to be interpreted in the UTC
|
|
||||||
+time zone.
|
|
||||||
.It Cm valid-before Ns = Ns "timestamp"
|
|
||||||
Indicates that the key is valid for use at or before the specified timestamp.
|
|
||||||
.El
|
|
||||||
diff --git a/ssh-keygen.c b/ssh-keygen.c
|
|
||||||
index 20b321cc..9b2beda0 100644
|
|
||||||
--- a/ssh-keygen.c
|
|
||||||
+++ b/ssh-keygen.c
|
|
||||||
@@ -1916,6 +1916,21 @@ parse_relative_time(const char *s, time_t now)
|
|
||||||
return now + (u_int64_t)(secs * mul);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static void
|
|
||||||
+parse_hex_u64(const char *s, uint64_t *up)
|
|
||||||
+{
|
|
||||||
+ char *ep;
|
|
||||||
+ unsigned long long ull;
|
|
||||||
+
|
|
||||||
+ errno = 0;
|
|
||||||
+ ull = strtoull(s, &ep, 16);
|
|
||||||
+ if (*s == '\0' || *ep != '\0')
|
|
||||||
+ fatal("Invalid certificate time: not a number");
|
|
||||||
+ if (errno == ERANGE && ull == ULONG_MAX)
|
|
||||||
+ fatal_fr(SSH_ERR_SYSTEM_ERROR, "Invalid certificate time");
|
|
||||||
+ *up = (uint64_t)ull;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
static void
|
|
||||||
parse_cert_times(char *timespec)
|
|
||||||
{
|
|
||||||
@@ -1938,8 +1953,8 @@ parse_cert_times(char *timespec)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* from:to, where
|
|
||||||
- * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "always"
|
|
||||||
- * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | "forever"
|
|
||||||
+ * from := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "always"
|
|
||||||
+ * to := [+-]timespec | YYYYMMDD | YYYYMMDDHHMMSS | 0x... | "forever"
|
|
||||||
*/
|
|
||||||
from = xstrdup(timespec);
|
|
||||||
to = strchr(from, ':');
|
|
||||||
@@ -1951,6 +1966,8 @@ parse_cert_times(char *timespec)
|
|
||||||
cert_valid_from = parse_relative_time(from, now);
|
|
||||||
else if (strcmp(from, "always") == 0)
|
|
||||||
cert_valid_from = 0;
|
|
||||||
+ else if (strncmp(from, "0x", 2) == 0)
|
|
||||||
+ parse_hex_u64(from, &cert_valid_from);
|
|
||||||
else if (parse_absolute_time(from, &cert_valid_from) != 0)
|
|
||||||
fatal("Invalid from time \"%s\"", from);
|
|
||||||
|
|
||||||
@@ -1958,6 +1975,8 @@ parse_cert_times(char *timespec)
|
|
||||||
cert_valid_to = parse_relative_time(to, now);
|
|
||||||
else if (strcmp(to, "forever") == 0)
|
|
||||||
cert_valid_to = ~(u_int64_t)0;
|
|
||||||
+ else if (strncmp(to, "0x", 2) == 0)
|
|
||||||
+ parse_hex_u64(to, &cert_valid_to);
|
|
||||||
else if (parse_absolute_time(to, &cert_valid_to) != 0)
|
|
||||||
fatal("Invalid to time \"%s\"", to);
|
|
||||||
|
|
||||||
diff --git a/sshd.8 b/sshd.8
|
|
||||||
index 2b50514e..8ccc5bc0 100644
|
|
||||||
--- a/sshd.8
|
|
||||||
+++ b/sshd.8
|
|
||||||
@@ -533,8 +533,9 @@ controlled via the
|
|
||||||
option.
|
|
||||||
.It Cm expiry-time="timespec"
|
|
||||||
Specifies a time after which the key will not be accepted.
|
|
||||||
-The time may be specified as a YYYYMMDD date or a YYYYMMDDHHMM[SS] time
|
|
||||||
-in the system time-zone.
|
|
||||||
+The time may be specified as a YYYYMMDD[Z] date or a YYYYMMDDHHMM[SS][Z] time.
|
|
||||||
+Dates and times will be interpreted in the system time zone unless suffixed
|
|
||||||
+by a Z character, in which case they will be interpreted in the UTC time zone.
|
|
||||||
.It Cm from="pattern-list"
|
|
||||||
Specifies that in addition to public key authentication, either the canonical
|
|
||||||
name of the remote host or its IP address must be present in the
|
|
@ -0,0 +1,106 @@
|
|||||||
|
diff --color -ruNp a/audit-linux.c b/audit-linux.c
|
||||||
|
--- a/audit-linux.c 2024-05-09 12:38:08.843017319 +0200
|
||||||
|
+++ b/audit-linux.c 2024-05-09 12:47:05.162267634 +0200
|
||||||
|
@@ -52,7 +52,7 @@ extern u_int utmp_len;
|
||||||
|
const char *audit_username(void);
|
||||||
|
|
||||||
|
static void
|
||||||
|
-linux_audit_user_logxxx(int uid, const char *username,
|
||||||
|
+linux_audit_user_logxxx(int uid, const char *username, const char *hostname,
|
||||||
|
const char *ip, const char *ttyn, int success, int event)
|
||||||
|
{
|
||||||
|
int audit_fd, rc, saved_errno;
|
||||||
|
@@ -66,7 +66,7 @@ linux_audit_user_logxxx(int uid, const c
|
||||||
|
}
|
||||||
|
rc = audit_log_acct_message(audit_fd, event,
|
||||||
|
NULL, "login", username ? username : "(unknown)",
|
||||||
|
- username == NULL ? uid : -1, NULL, ip, ttyn, success);
|
||||||
|
+ username == NULL ? uid : -1, hostname, ip, ttyn, success);
|
||||||
|
saved_errno = errno;
|
||||||
|
close(audit_fd);
|
||||||
|
|
||||||
|
@@ -181,9 +181,11 @@ audit_run_command(struct ssh *ssh, const
|
||||||
|
{
|
||||||
|
if (!user_login_count++)
|
||||||
|
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
|
||||||
|
+ options.use_dns ? remote_hostname(ssh) : NULL,
|
||||||
|
ssh_remote_ipaddr(ssh),
|
||||||
|
"ssh", 1, AUDIT_USER_LOGIN);
|
||||||
|
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
|
||||||
|
+ options.use_dns ? remote_hostname(ssh) : NULL,
|
||||||
|
ssh_remote_ipaddr(ssh),
|
||||||
|
"ssh", 1, AUDIT_USER_START);
|
||||||
|
return 0;
|
||||||
|
@@ -193,10 +195,12 @@ void
|
||||||
|
audit_end_command(struct ssh *ssh, int handle, const char *command)
|
||||||
|
{
|
||||||
|
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
|
||||||
|
+ options.use_dns ? remote_hostname(ssh) : NULL,
|
||||||
|
ssh_remote_ipaddr(ssh),
|
||||||
|
"ssh", 1, AUDIT_USER_END);
|
||||||
|
if (user_login_count && !--user_login_count)
|
||||||
|
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
|
||||||
|
+ options.use_dns ? remote_hostname(ssh) : NULL,
|
||||||
|
ssh_remote_ipaddr(ssh),
|
||||||
|
"ssh", 1, AUDIT_USER_LOGOUT);
|
||||||
|
}
|
||||||
|
@@ -211,19 +215,27 @@ void
|
||||||
|
audit_session_open(struct logininfo *li)
|
||||||
|
{
|
||||||
|
if (!user_login_count++)
|
||||||
|
- linux_audit_user_logxxx(li->uid, NULL, li->hostname,
|
||||||
|
+ linux_audit_user_logxxx(li->uid, NULL,
|
||||||
|
+ options.use_dns ? li->hostname : NULL,
|
||||||
|
+ options.use_dns ? NULL : li->hostname,
|
||||||
|
li->line, 1, AUDIT_USER_LOGIN);
|
||||||
|
- linux_audit_user_logxxx(li->uid, NULL, li->hostname,
|
||||||
|
+ linux_audit_user_logxxx(li->uid, NULL,
|
||||||
|
+ options.use_dns ? li->hostname : NULL,
|
||||||
|
+ options.use_dns ? NULL : li->hostname,
|
||||||
|
li->line, 1, AUDIT_USER_START);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
audit_session_close(struct logininfo *li)
|
||||||
|
{
|
||||||
|
- linux_audit_user_logxxx(li->uid, NULL, li->hostname,
|
||||||
|
+ linux_audit_user_logxxx(li->uid, NULL,
|
||||||
|
+ options.use_dns ? li->hostname : NULL,
|
||||||
|
+ options.use_dns ? NULL : li->hostname,
|
||||||
|
li->line, 1, AUDIT_USER_END);
|
||||||
|
if (user_login_count && !--user_login_count)
|
||||||
|
- linux_audit_user_logxxx(li->uid, NULL, li->hostname,
|
||||||
|
+ linux_audit_user_logxxx(li->uid, NULL,
|
||||||
|
+ options.use_dns ? li->hostname : NULL,
|
||||||
|
+ options.use_dns ? NULL : li->hostname,
|
||||||
|
li->line, 1, AUDIT_USER_LOGOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -236,6 +248,7 @@ audit_event(struct ssh *ssh, ssh_audit_e
|
||||||
|
linux_audit_user_auth(-1, audit_username(),
|
||||||
|
ssh_remote_ipaddr(ssh), "ssh", 0, event);
|
||||||
|
linux_audit_user_logxxx(-1, audit_username(),
|
||||||
|
+ options.use_dns ? remote_hostname(ssh) : NULL,
|
||||||
|
ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN);
|
||||||
|
break;
|
||||||
|
case SSH_AUTH_FAIL_PASSWD:
|
||||||
|
@@ -254,9 +267,11 @@ audit_event(struct ssh *ssh, ssh_audit_e
|
||||||
|
if (user_login_count) {
|
||||||
|
while (user_login_count--)
|
||||||
|
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
|
||||||
|
+ options.use_dns ? remote_hostname(ssh) : NULL,
|
||||||
|
ssh_remote_ipaddr(ssh),
|
||||||
|
"ssh", 1, AUDIT_USER_END);
|
||||||
|
linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL,
|
||||||
|
+ options.use_dns ? remote_hostname(ssh) : NULL,
|
||||||
|
ssh_remote_ipaddr(ssh),
|
||||||
|
"ssh", 1, AUDIT_USER_LOGOUT);
|
||||||
|
}
|
||||||
|
@@ -265,6 +280,7 @@ audit_event(struct ssh *ssh, ssh_audit_e
|
||||||
|
case SSH_CONNECTION_ABANDON:
|
||||||
|
case SSH_INVALID_USER:
|
||||||
|
linux_audit_user_logxxx(-1, audit_username(),
|
||||||
|
+ options.use_dns ? remote_hostname(ssh) : NULL,
|
||||||
|
ssh_remote_ipaddr(ssh), "ssh", 0, AUDIT_USER_LOGIN);
|
||||||
|
break;
|
||||||
|
default:
|
@ -1,468 +0,0 @@
|
|||||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../../openssh-8.7p1/ssh-dss.c ./ssh-dss.c
|
|
||||||
--- ../../openssh-8.7p1/ssh-dss.c 2023-03-08 15:35:14.669943335 +0100
|
|
||||||
+++ ./ssh-dss.c 2023-03-08 15:34:33.508578129 +0100
|
|
||||||
@@ -32,6 +32,8 @@
|
|
||||||
#include <openssl/bn.h>
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
+#include <openssl/core_names.h>
|
|
||||||
+#include <openssl/param_build.h>
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
@@ -72,9 +74,8 @@
|
|
||||||
sshkey_type_plain(key->type) != KEY_DSA)
|
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
- if ((pkey = EVP_PKEY_new()) == NULL ||
|
|
||||||
- EVP_PKEY_set1_DSA(pkey, key->dsa) != 1)
|
|
||||||
- return SSH_ERR_ALLOC_FAIL;
|
|
||||||
+ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0)
|
|
||||||
+ return ret;
|
|
||||||
ret = sshkey_calculate_signature(pkey, SSH_DIGEST_SHA1, &sigb, &len,
|
|
||||||
data, datalen);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
@@ -201,11 +202,8 @@
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if ((pkey = EVP_PKEY_new()) == NULL ||
|
|
||||||
- EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) {
|
|
||||||
- ret = SSH_ERR_ALLOC_FAIL;
|
|
||||||
+ if ((ret = ssh_create_evp_dss(key, &pkey)) != 0)
|
|
||||||
goto out;
|
|
||||||
- }
|
|
||||||
ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, datalen,
|
|
||||||
sigb, slen);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
@@ -221,4 +219,63 @@
|
|
||||||
freezero(sigblob, len);
|
|
||||||
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;
|
|
||||||
+}
|
|
||||||
#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-8.7p1/ssh-ecdsa.c ./ssh-ecdsa.c
|
|
||||||
--- ../../openssh-8.7p1/ssh-ecdsa.c 2023-03-08 15:35:14.669943335 +0100
|
|
||||||
+++ ./ssh-ecdsa.c 2023-03-08 15:40:52.628201267 +0100
|
|
||||||
@@ -34,6 +34,8 @@
|
|
||||||
#include <openssl/ec.h>
|
|
||||||
#include <openssl/ecdsa.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
+#include <openssl/core_names.h>
|
|
||||||
+#include <openssl/param_build.h>
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
@@ -72,9 +74,8 @@
|
|
||||||
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
|
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
|
||||||
|
|
||||||
- if ((pkey = EVP_PKEY_new()) == NULL ||
|
|
||||||
- EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1)
|
|
||||||
- return SSH_ERR_ALLOC_FAIL;
|
|
||||||
+ if ((ret = ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey)) != 0)
|
|
||||||
+ return ret;
|
|
||||||
ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data,
|
|
||||||
datalen);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
@@ -193,11 +194,8 @@
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if ((pkey = EVP_PKEY_new()) == NULL ||
|
|
||||||
- EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) {
|
|
||||||
- ret = SSH_ERR_ALLOC_FAIL;
|
|
||||||
+ if (ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey) != 0)
|
|
||||||
goto out;
|
|
||||||
- }
|
|
||||||
ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, sigb, len);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
|
|
||||||
@@ -212,4 +210,76 @@
|
|
||||||
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;
|
|
||||||
+}
|
|
||||||
#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
|
|
||||||
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/sshkey.c ./sshkey.c
|
|
||||||
--- ../../openssh-8.7p1/sshkey.c 2023-03-08 15:35:14.702943628 +0100
|
|
||||||
+++ ./sshkey.c 2023-03-08 15:39:03.354082015 +0100
|
|
||||||
@@ -35,6 +35,8 @@
|
|
||||||
#include <openssl/err.h>
|
|
||||||
#include <openssl/pem.h>
|
|
||||||
#include <openssl/fips.h>
|
|
||||||
+#include <openssl/core_names.h>
|
|
||||||
+#include <openssl/param_build.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "crypto_api.h"
|
|
||||||
@@ -492,13 +494,14 @@
|
|
||||||
{
|
|
||||||
EVP_MD_CTX *ctx = NULL;
|
|
||||||
u_char *sig = NULL;
|
|
||||||
- int ret, slen, len;
|
|
||||||
+ int ret, slen;
|
|
||||||
+ size_t len;
|
|
||||||
|
|
||||||
if (sigp == NULL || lenp == NULL) {
|
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
- slen = EVP_PKEY_size(pkey);
|
|
||||||
+ slen = EVP_PKEY_get_size(pkey);
|
|
||||||
if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
|
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
|
||||||
|
|
||||||
@@ -511,9 +514,10 @@
|
|
||||||
ret = SSH_ERR_ALLOC_FAIL;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
- if (EVP_SignInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 ||
|
|
||||||
- EVP_SignUpdate(ctx, data, datalen) <= 0 ||
|
|
||||||
- EVP_SignFinal(ctx, sig, &len, pkey) <= 0) {
|
|
||||||
+ if (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;
|
|
||||||
}
|
|
||||||
@@ -540,12 +544,13 @@
|
|
||||||
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) {
|
|
||||||
+ 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_VerifyFinal(ctx, sigbuf, siglen, pkey);
|
|
||||||
+ ret = EVP_DigestVerifyFinal(ctx, sigbuf, siglen);
|
|
||||||
switch (ret) {
|
|
||||||
case 1:
|
|
||||||
ret = 0;
|
|
||||||
@@ -5038,3 +5043,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-8.7p1/sshkey.h ./sshkey.h
|
|
||||||
--- ../../openssh-8.7p1/sshkey.h 2023-03-08 15:35:14.702943628 +0100
|
|
||||||
+++ ./sshkey.h 2023-03-08 15:34:33.509578138 +0100
|
|
||||||
@@ -31,6 +31,9 @@
|
|
||||||
#ifdef WITH_OPENSSL
|
|
||||||
#include <openssl/rsa.h>
|
|
||||||
#include <openssl/dsa.h>
|
|
||||||
+#include <openssl/evp.h>
|
|
||||||
+#include <openssl/param_build.h>
|
|
||||||
+#include <openssl/core_names.h>
|
|
||||||
# ifdef OPENSSL_HAS_ECC
|
|
||||||
# include <openssl/ec.h>
|
|
||||||
# include <openssl/ecdsa.h>
|
|
||||||
@@ -293,6 +295,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 ssh_rsa_sign(const struct sshkey *key,
|
|
||||||
u_char **sigp, size_t *lenp, const u_char *data, size_t datalen,
|
|
||||||
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/ssh-rsa.c ./ssh-rsa.c
|
|
||||||
--- ../../openssh-8.7p1/ssh-rsa.c 2023-03-08 15:35:14.669943335 +0100
|
|
||||||
+++ ./ssh-rsa.c 2023-03-08 15:34:33.509578138 +0100
|
|
||||||
@@ -23,6 +23,8 @@
|
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include <openssl/err.h>
|
|
||||||
+#include <openssl/core_names.h>
|
|
||||||
+#include <openssl/param_build.h>
|
|
||||||
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <string.h>
|
|
||||||
@@ -172,9 +174,8 @@
|
|
||||||
if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
|
|
||||||
return SSH_ERR_KEY_LENGTH;
|
|
||||||
|
|
||||||
- if ((pkey = EVP_PKEY_new()) == NULL ||
|
|
||||||
- EVP_PKEY_set1_RSA(pkey, key->rsa) != 1)
|
|
||||||
- return SSH_ERR_ALLOC_FAIL;
|
|
||||||
+ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0)
|
|
||||||
+ return ret;
|
|
||||||
ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data,
|
|
||||||
datalen);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
@@ -285,11 +286,8 @@
|
|
||||||
len = modlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
- if ((pkey = EVP_PKEY_new()) == NULL ||
|
|
||||||
- EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) {
|
|
||||||
- ret = SSH_ERR_ALLOC_FAIL;
|
|
||||||
+ if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0)
|
|
||||||
goto out;
|
|
||||||
- }
|
|
||||||
ret = openssh_RSA_verify(hash_alg, data, datalen, sigblob, len, pkey);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
|
|
||||||
@@ -306,11 +304,9 @@
|
|
||||||
u_char *sigbuf, size_t siglen, EVP_PKEY *pkey)
|
|
||||||
{
|
|
||||||
size_t rsasize = 0;
|
|
||||||
- const RSA *rsa;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
- rsa = EVP_PKEY_get0_RSA(pkey);
|
|
||||||
- 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;
|
|
||||||
@@ -323,4 +319,87 @@
|
|
||||||
done:
|
|
||||||
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;
|
|
||||||
+}
|
|
||||||
#endif /* WITH_OPENSSL */
|
|
@ -1,131 +0,0 @@
|
|||||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh-ecdsa.c openssh-8.7p1-patched/ssh-ecdsa.c
|
|
||||||
--- openssh-8.7p1/ssh-ecdsa.c 2023-05-24 09:39:45.002631174 +0200
|
|
||||||
+++ openssh-8.7p1-patched/ssh-ecdsa.c 2023-05-24 09:09:34.400853951 +0200
|
|
||||||
@@ -74,8 +74,18 @@
|
|
||||||
if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1)
|
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
|
||||||
|
|
||||||
- if ((ret = ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey)) != 0)
|
|
||||||
- return ret;
|
|
||||||
+#ifdef ENABLE_PKCS11
|
|
||||||
+ if (is_ecdsa_pkcs11(key->ecdsa)) {
|
|
||||||
+ if ((pkey = EVP_PKEY_new()) == NULL ||
|
|
||||||
+ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1)
|
|
||||||
+ return SSH_ERR_ALLOC_FAIL;
|
|
||||||
+ } else {
|
|
||||||
+#endif
|
|
||||||
+ if ((ret = ssh_create_evp_ec(key->ecdsa, key->ecdsa_nid, &pkey)) != 0)
|
|
||||||
+ return ret;
|
|
||||||
+#ifdef ENABLE_PKCS11
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data,
|
|
||||||
datalen);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
||||||
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/ssh-pkcs11.c openssh-8.7p1-patched/ssh-pkcs11.c
|
|
||||||
--- openssh-8.7p1/ssh-pkcs11.c 2023-05-24 09:39:44.950630607 +0200
|
|
||||||
+++ openssh-8.7p1-patched/ssh-pkcs11.c 2023-05-24 09:33:59.153866357 +0200
|
|
||||||
@@ -775,8 +775,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 /* HAVE_EC_KEY_METHOD_NEW */
|
|
||||||
|
|
||||||
+int
|
|
||||||
+is_rsa_pkcs11(RSA *rsa)
|
|
||||||
+{
|
|
||||||
+ if (RSA_get_ex_data(rsa, rsa_idx) != NULL)
|
|
||||||
+ return 1;
|
|
||||||
+ return 0;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/* remove trailing spaces */
|
|
||||||
static void
|
|
||||||
rmspace(u_char *buf, size_t len)
|
|
||||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh-pkcs11-client.c openssh-8.7p1-patched/ssh-pkcs11-client.c
|
|
||||||
--- openssh-8.7p1/ssh-pkcs11-client.c 2023-05-24 09:39:44.950630607 +0200
|
|
||||||
+++ openssh-8.7p1-patched/ssh-pkcs11-client.c 2023-05-24 09:31:16.139092673 +0200
|
|
||||||
@@ -225,8 +225,36 @@
|
|
||||||
static RSA_METHOD *helper_rsa;
|
|
||||||
#ifdef 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 /* 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-8.7p1/ssh-pkcs11.h openssh-8.7p1-patched/ssh-pkcs11.h
|
|
||||||
--- openssh-8.7p1/ssh-pkcs11.h 2023-05-24 09:39:44.950630607 +0200
|
|
||||||
+++ openssh-8.7p1-patched/ssh-pkcs11.h 2023-05-24 09:36:49.055714975 +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-8.7p1/ssh-rsa.c openssh-8.7p1-patched/ssh-rsa.c
|
|
||||||
--- openssh-8.7p1/ssh-rsa.c 2023-05-24 09:39:45.003631184 +0200
|
|
||||||
+++ openssh-8.7p1-patched/ssh-rsa.c 2023-05-24 09:31:37.019319860 +0200
|
|
||||||
@@ -174,8 +174,18 @@
|
|
||||||
if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE)
|
|
||||||
return SSH_ERR_KEY_LENGTH;
|
|
||||||
|
|
||||||
- if ((ret = ssh_create_evp_rsa(key, &pkey)) != 0)
|
|
||||||
- return ret;
|
|
||||||
+#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
|
|
||||||
+ }
|
|
||||||
+#endif
|
|
||||||
ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data,
|
|
||||||
datalen);
|
|
||||||
EVP_PKEY_free(pkey);
|
|
@ -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 */
|
|
@ -1,13 +0,0 @@
|
|||||||
diff -up openssh-8.7p1/ssh-keygen.c.find-princ openssh-8.7p1/ssh-keygen.c
|
|
||||||
--- openssh-8.7p1/ssh-keygen.c.find-princ 2021-11-29 15:27:03.032070863 +0100
|
|
||||||
+++ openssh-8.7p1/ssh-keygen.c 2021-11-29 15:27:34.736342968 +0100
|
|
||||||
@@ -2700,7 +2700,8 @@ sig_process_opts(char * const *opts, siz
|
|
||||||
time_t now;
|
|
||||||
|
|
||||||
*verify_timep = 0;
|
|
||||||
- *print_pubkey = 0;
|
|
||||||
+ if (print_pubkey)
|
|
||||||
+ *print_pubkey = 0;
|
|
||||||
for (i = 0; i < nopts; i++) {
|
|
||||||
if (strncasecmp(opts[i], "verify-time=", 12) == 0) {
|
|
||||||
if (parse_absolute_time(opts[i] + 12,
|
|
@ -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);
|
|
@ -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);
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
|||||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/ssh_config.5 openssh-8.7p1-patched/ssh_config.5
|
|
||||||
--- openssh-8.7p1/ssh_config.5 2023-06-02 09:14:40.279373577 +0200
|
|
||||||
+++ openssh-8.7p1-patched/ssh_config.5 2023-05-30 16:01:04.533848172 +0200
|
|
||||||
@@ -989,6 +989,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
|
|
||||||
@@ -1564,6 +1575,9 @@
|
|
||||||
.Pp
|
|
||||||
The list of available signature algorithms may also be obtained using
|
|
||||||
.Qq ssh -Q PubkeyAcceptedAlgorithms .
|
|
||||||
+.Pp
|
|
||||||
+This option affects also
|
|
||||||
+.Cm HostKeyAlgorithms
|
|
||||||
.It Cm PubkeyAuthentication
|
|
||||||
Specifies whether to try public key authentication.
|
|
||||||
The argument to this keyword must be
|
|
@ -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");
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
@ -1,446 +1,22 @@
|
|||||||
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
|
diff --git a/readconf.c b/readconf.c
|
||||||
index 7f26c680..42be690b 100644
|
--- a/readconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
--- a/readconf.c
|
+++ b/readconf.c (date 1703169891147)
|
||||||
+++ b/readconf.c
|
@@ -326,6 +326,7 @@
|
||||||
@@ -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 },
|
|
||||||
{ "securitykeyprovider", oSecurityKeyProvider },
|
{ "securitykeyprovider", oSecurityKeyProvider },
|
||||||
{ "knownhostscommand", oKnownHostsCommand },
|
{ "knownhostscommand", oKnownHostsCommand },
|
||||||
+ { "requiredrsasize", oRequiredRSASize },
|
{ "requiredrsasize", oRequiredRSASize },
|
||||||
+ { "rsaminsize", oRequiredRSASize }, /* alias */
|
+ { "rsaminsize", oRequiredRSASize }, /* alias */
|
||||||
|
{ "enableescapecommandline", oEnableEscapeCommandline },
|
||||||
{ NULL, oBadOption }
|
{ "obscurekeystroketiming", oObscureKeystrokeTiming },
|
||||||
};
|
{ "channeltimeout", oChannelTimeout },
|
||||||
@@ -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
|
diff --git a/servconf.c b/servconf.c
|
||||||
index 29df0463..423772b1 100644
|
--- a/servconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||||
--- a/servconf.c
|
+++ b/servconf.c (date 1703169891148)
|
||||||
+++ b/servconf.c
|
@@ -691,6 +691,7 @@
|
||||||
@@ -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 },
|
|
||||||
{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
|
{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
|
||||||
{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
|
{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
|
||||||
+ { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
|
{ "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
|
||||||
+ { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */
|
+ { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */
|
||||||
{ NULL, sBadOption, 0 }
|
{ "channeltimeout", sChannelTimeout, SSHCFG_ALL },
|
||||||
};
|
{ "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL },
|
||||||
|
{ "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL },
|
||||||
@@ -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
|
|
||||||
|
@ -1,63 +1,118 @@
|
|||||||
diff --color -rup a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh
|
diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostkey-agent.sh
|
||||||
--- a/regress/hostkey-agent.sh 2021-08-20 06:03:49.000000000 +0200
|
--- openssh-9.3p1/regress/hostkey-agent.sh.xxx 2023-05-29 18:15:56.311236887 +0200
|
||||||
+++ b/regress/hostkey-agent.sh 2022-07-14 11:58:12.172786060 +0200
|
+++ openssh-9.3p1/regress/hostkey-agent.sh 2023-05-29 18:16:07.598503551 +0200
|
||||||
@@ -13,8 +13,12 @@ r=$?
|
@@ -17,8 +17,21 @@ trace "make CA key"
|
||||||
grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
|
|
||||||
echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig
|
${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA"
|
||||||
|
|
||||||
+PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \
|
+PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \
|
||||||
+ grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"`
|
+ grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"`
|
||||||
+SSH_ACCEPTED_KEYTYPES=`echo "$SSH_KEYTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"`
|
+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"
|
trace "load hostkeys"
|
||||||
-for k in $SSH_KEYTYPES ; do
|
-for k in $SSH_KEYTYPES ; do
|
||||||
+for k in $SSH_ACCEPTED_KEYTYPES ; do
|
+for k in $SSH_ACCEPTED_KEYTYPES ; do
|
||||||
${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
|
${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
|
||||||
(
|
${SSHKEYGEN} -s $OBJ/agent-ca -qh -n localhost-with-alias \
|
||||||
printf 'localhost-with-alias,127.0.0.1,::1 '
|
-I localhost-with-alias $OBJ/agent-key.$k.pub || \
|
||||||
@@ -31,7 +35,7 @@ cp $OBJ/known_hosts.orig $OBJ/known_host
|
@@ -32,12 +48,16 @@ rm $OBJ/agent-ca # Don't need CA private
|
||||||
|
|
||||||
unset SSH_AUTH_SOCK
|
unset SSH_AUTH_SOCK
|
||||||
|
|
||||||
for ps in yes; do
|
|
||||||
-for k in $SSH_KEYTYPES ; do
|
-for k in $SSH_KEYTYPES ; do
|
||||||
+for k in $SSH_ACCEPTED_KEYTYPES ; do
|
+for k in $SSH_ACCEPTED_KEYTYPES ; do
|
||||||
verbose "key type $k privsep=$ps"
|
verbose "key type $k"
|
||||||
|
+ hka=$k
|
||||||
|
+ if [ $k = "ssh-rsa" ]; then
|
||||||
|
+ hka="rsa-sha2-512"
|
||||||
|
+ fi
|
||||||
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
|
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
|
||||||
echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
|
- echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy
|
||||||
diff --color -rup a/sshconnect2.c b/sshconnect2.c
|
+ echo "HostKeyAlgorithms $hka" >> $OBJ/sshd_proxy
|
||||||
--- a/sshconnect2.c 2022-07-14 10:10:07.262975710 +0200
|
echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy
|
||||||
+++ b/sshconnect2.c 2022-07-14 10:10:32.068452067 +0200
|
- opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy"
|
||||||
@@ -222,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
+ 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 *myproposal[PROPOSAL_MAX];
|
||||||
char *s, *all_key;
|
- char *all_key, *hkalgs = NULL;
|
||||||
+ char *hostkeyalgs = NULL, *pkalg = NULL;
|
+ char *all_key, *hkalgs = NULL, *filtered_algs = NULL;
|
||||||
char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
|
|
||||||
int r, use_known_hosts_order = 0;
|
int r, use_known_hosts_order = 0;
|
||||||
|
|
||||||
@@ -264,14 +265,19 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
#if defined(GSSAPI) && defined(WITH_OPENSSL)
|
||||||
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
|
@@ -260,10 +260,22 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||||
if (use_known_hosts_order) {
|
if (use_known_hosts_order)
|
||||||
/* Query known_hosts and prefer algorithms that appear there */
|
hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo);
|
||||||
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
|
|
||||||
- compat_pkalg_proposal(ssh,
|
+ filtered_algs = hkalgs ? match_filter_allowlist(hkalgs, options.pubkey_accepted_algos)
|
||||||
- order_hostkeyalgs(host, hostaddr, port, cinfo));
|
+ : match_filter_allowlist(options.hostkeyalgorithms,
|
||||||
+ if ((hostkeyalgs = order_hostkeyalgs(host, hostaddr, port, cinfo)) == NULL)
|
+ options.pubkey_accepted_algos);
|
||||||
+ fatal_f("order_hostkeyalgs");
|
+ if (filtered_algs == NULL) {
|
||||||
+ pkalg = match_filter_allowlist(hostkeyalgs, options.pubkey_accepted_algos);
|
+ if (hkalgs)
|
||||||
+ free(hostkeyalgs);
|
+ fatal_f("No match between algorithms for %s (host %s) and pubkey accepted algorithms %s",
|
||||||
} else {
|
+ hkalgs, host, options.pubkey_accepted_algos);
|
||||||
- /* Use specified HostkeyAlgorithms exactly */
|
+ else
|
||||||
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
|
+ fatal_f("No match between host key algorithms %s and pubkey accepted algorithms %s",
|
||||||
- compat_pkalg_proposal(ssh, options.hostkeyalgorithms);
|
+ options.hostkeyalgorithms, options.pubkey_accepted_algos);
|
||||||
+ /* Use specified HostkeyAlgorithms */
|
+ }
|
||||||
+ pkalg = match_filter_allowlist(options.hostkeyalgorithms, options.pubkey_accepted_algos);
|
+
|
||||||
}
|
kex_proposal_populate_entries(ssh, myproposal,
|
||||||
+ if (pkalg == NULL)
|
options.kex_algorithms, options.ciphers, options.macs,
|
||||||
+ fatal_f("match_filter_allowlist");
|
compression_alg_list(options.compression),
|
||||||
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
|
- hkalgs ? hkalgs : options.hostkeyalgorithms);
|
||||||
+ compat_pkalg_proposal(ssh, pkalg);
|
+ filtered_algs);
|
||||||
+ free(pkalg);
|
|
||||||
|
|
||||||
#if defined(GSSAPI) && defined(WITH_OPENSSL)
|
#if defined(GSSAPI) && defined(WITH_OPENSSL)
|
||||||
if (options.gss_keyex) {
|
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)
|
||||||
|
@ -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
|
|
@ -1,129 +0,0 @@
|
|||||||
diff --git a/scp.1 b/scp.1
|
|
||||||
index 68aac04b..a96e95ad 100644
|
|
||||||
--- a/scp.1
|
|
||||||
+++ b/scp.1
|
|
||||||
@@ -8,9 +8,9 @@
|
|
||||||
.\"
|
|
||||||
.\" Created: Sun May 7 00:14:37 1995 ylo
|
|
||||||
.\"
|
|
||||||
-.\" $OpenBSD: scp.1,v 1.100 2021/08/11 14:07:54 naddy Exp $
|
|
||||||
+.\" $OpenBSD: scp.1,v 1.101 2021/09/08 23:31:39 djm Exp $
|
|
||||||
.\"
|
|
||||||
-.Dd $Mdocdate: August 11 2021 $
|
|
||||||
+.Dd $Mdocdate: September 8 2021 $
|
|
||||||
.Dt SCP 1
|
|
||||||
.Os
|
|
||||||
.Sh NAME
|
|
||||||
@@ -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
|
|
||||||
@@ -37,9 +37,6 @@ It uses
|
|
||||||
.Xr ssh 1
|
|
||||||
for data transfer, and uses the same authentication and provides the
|
|
||||||
same security as a login session.
|
|
||||||
-The scp protocol requires execution of the remote user's shell to perform
|
|
||||||
-.Xr glob 3
|
|
||||||
-pattern matching.
|
|
||||||
.Pp
|
|
||||||
.Nm
|
|
||||||
will ask for passwords or passphrases if they are needed for
|
|
||||||
@@ -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 legacy SCP protocol (the default), this option
|
|
||||||
+Note that, when using the legacy 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,9 +145,10 @@ Limits the used bandwidth, specified in Kbit/s.
|
|
||||||
.It Fl O
|
|
||||||
Use the legacy SCP protocol for file transfers instead of the SFTP protocol.
|
|
||||||
Forcing the use of the SCP protocol may be necessary for servers that do
|
|
||||||
-not implement SFTP or for backwards-compatibility for particular filename
|
|
||||||
-wildcard patterns.
|
|
||||||
-This mode is the default.
|
|
||||||
+not implement SFTP, for backwards-compatibility for particular filename
|
|
||||||
+wildcard patterns and for expanding paths with a
|
|
||||||
+.Sq ~
|
|
||||||
+prefix for older SFTP servers.
|
|
||||||
.It Fl o Ar ssh_option
|
|
||||||
Can be used to pass options to
|
|
||||||
.Nm ssh
|
|
||||||
@@ -258,16 +258,6 @@ to use for the encrypted connection.
|
|
||||||
The program must understand
|
|
||||||
.Xr ssh 1
|
|
||||||
options.
|
|
||||||
-.It Fl s
|
|
||||||
-Use the SFTP protocol for file transfers instead of the legacy SCP protocol.
|
|
||||||
-Using SFTP avoids invoking a shell on the remote side and provides
|
|
||||||
-more predictable filename handling, as the SCP protocol
|
|
||||||
-relied on the remote shell for expanding
|
|
||||||
-.Xr glob 3
|
|
||||||
-wildcards.
|
|
||||||
-.Pp
|
|
||||||
-A near-future release of OpenSSH will make the SFTP protocol the default.
|
|
||||||
-This option will be deleted before the end of 2022.
|
|
||||||
.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
|
|
||||||
@@ -1,4 +1,4 @@
|
|
||||||
-/* $OpenBSD: scp.c,v 1.232 2021/08/11 14:07:54 naddy Exp $ */
|
|
||||||
+/* $OpenBSD: scp.c,v 1.233 2021/09/08 23:31:39 djm Exp $ */
|
|
||||||
/*
|
|
||||||
* scp - secure remote copy. This is basically patched BSD rcp which
|
|
||||||
* uses ssh to do the data transfer (instead of using rcmd).
|
|
||||||
@@ -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);
|
|
@ -1,167 +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"
|
|
||||||
@@ -660,7 +661,7 @@ main(int argc, char **argv)
|
|
||||||
* Finally check the exit status of the ssh process, if one was forked
|
|
||||||
* and no error has occurred yet
|
|
||||||
*/
|
|
||||||
- if (do_cmd_pid != -1 && errs == 0) {
|
|
||||||
+ if (do_cmd_pid != -1 && (mode == MODE_SFTP || errs == 0)) {
|
|
||||||
if (remin != -1)
|
|
||||||
(void) close(remin);
|
|
||||||
if (remout != -1)
|
|
||||||
@@ -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,14 +1322,17 @@ 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) {
|
|
||||||
- fatal("failed to upload directory %s to %s",
|
|
||||||
+ 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)
|
|
||||||
- fatal("failed to upload file %s to %s", src, abs_dst);
|
|
||||||
+ } else if (do_upload(conn, src, abs_dst, pflag, 0, 0) != 0) {
|
|
||||||
+ error("failed to upload file %s to %s", src, abs_dst);
|
|
||||||
+ errs = 1;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
free(abs_dst);
|
|
||||||
free(target);
|
|
||||||
@@ -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);
|
|
||||||
@@ -1551,7 +1584,8 @@ out:
|
|
||||||
free(tmp);
|
|
||||||
globfree(&g);
|
|
||||||
if (err == -1) {
|
|
||||||
- fatal("Failed to download file '%s'", src);
|
|
||||||
+ error("Failed to download '%s'", src);
|
|
||||||
+ errs = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
|||||||
diff --git a/misc.c b/misc.c
|
|
||||||
index b8d1040d..0134d694 100644
|
|
||||||
--- a/misc.c
|
|
||||||
+++ b/misc.c
|
|
||||||
@@ -56,6 +56,7 @@
|
|
||||||
#ifdef HAVE_PATHS_H
|
|
||||||
# include <paths.h>
|
|
||||||
#include <pwd.h>
|
|
||||||
+#include <grp.h>
|
|
||||||
#endif
|
|
||||||
#ifdef SSH_TUN_OPENBSD
|
|
||||||
#include <net/if.h>
|
|
||||||
@@ -2695,6 +2696,12 @@ subprocess(const char *tag, const char *command,
|
|
||||||
}
|
|
||||||
closefrom(STDERR_FILENO + 1);
|
|
||||||
|
|
||||||
+ if (geteuid() == 0 &&
|
|
||||||
+ initgroups(pw->pw_name, pw->pw_gid) == -1) {
|
|
||||||
+ error("%s: initgroups(%s, %u): %s", tag,
|
|
||||||
+ pw->pw_name, (u_int)pw->pw_gid, strerror(errno));
|
|
||||||
+ _exit(1);
|
|
||||||
+ }
|
|
||||||
if (setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) == -1) {
|
|
||||||
error("%s: setresgid %u: %s", tag, (u_int)pw->pw_gid,
|
|
||||||
strerror(errno));
|
|
@ -1,16 +0,0 @@
|
|||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
|
|
||||||
iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmEfKn8ACgkQKj9BTnNg
|
|
||||||
YLo2qQ/9EHkk64DFIOZz9xmKdogiVvuYue9LE1ex52rgLhxkeAmXQ0Ta2VjK0S81
|
|
||||||
9/oWJP5N+gcHLO01Og2bVuUPim/S1Op69a5hmFWaYvIlKCeCBONwE1O+n6IIhf+p
|
|
||||||
HUXkY9cFXOoSEHhQ1D+/f8axv7WtZ4ZtHlxejqcsjyyIDqG+i4kReiZJP0D06dUk
|
|
||||||
cv2U6YsQ9hTvXBTeUANCgLzH6DvEoyQyy7LOpaHsO1VKMlctslrVWdWRiAn7V934
|
|
||||||
8TuhZB0NoHAGZIgFFCINSfFAxnqxPyZtLdTxSF5EwPXqdnwFfGk4nprLZA1vT2yT
|
|
||||||
HeZiXhx919L+trDVmCycqcSCj8vOlNWl9A8VaodTW01SG75D7b1f5XqLGmSP4ujf
|
|
||||||
+9UnYKVm0OAU8jpbGXd1D2REuXRspRU6NPNW/3MkO2I46sG+KHhD6OMipOaiY8p2
|
|
||||||
WrCsryadBThUqSKAo/zdIAJgVVt23Y7ykIIkhxebaRBIS4v6fdXg4aIjHfOjlsDX
|
|
||||||
Mh2JFEbP93bKC0wCJWcR7NXFR4nN2ddTen1jLC+m+ABMae0AoMCFy7VW4FK33ZAJ
|
|
||||||
+Plovu62bBUXeVhXhLC76vdQo7geRpBs0RQV0gtj6HlZL5BReEKwApPEVce8K9F5
|
|
||||||
+ZYbmF5ZQNMcdR9zZ+QV+ykv6y4SG1+rPI9/Ufo/ZZp5jRnsq+M=
|
|
||||||
=xI/+
|
|
||||||
-----END PGP SIGNATURE-----
|
|
@ -0,0 +1,119 @@
|
|||||||
|
diff -up openssh-9.0p1/audit-bsm.c.patch openssh-9.0p1/audit-bsm.c
|
||||||
|
--- openssh-9.0p1/audit-bsm.c.patch 2022-10-24 15:02:16.544858331 +0200
|
||||||
|
+++ openssh-9.0p1/audit-bsm.c 2022-10-24 14:51:43.685766639 +0200
|
||||||
|
@@ -405,7 +405,7 @@ audit_session_close(struct logininfo *li
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)
|
||||||
|
+audit_keyusage(struct ssh *ssh, int host_user, char *key_fp, const struct sshkey_cert *cert, const char *issuer_fp, int rv)
|
||||||
|
{
|
||||||
|
/* not implemented */
|
||||||
|
}
|
||||||
|
diff -up openssh-9.0p1/audit.c.patch openssh-9.0p1/audit.c
|
||||||
|
--- openssh-9.0p1/audit.c.patch 2022-10-24 15:02:16.544858331 +0200
|
||||||
|
+++ openssh-9.0p1/audit.c 2022-10-24 15:20:38.854548226 +0200
|
||||||
|
@@ -116,12 +116,22 @@ audit_event_lookup(ssh_audit_event_t ev)
|
||||||
|
void
|
||||||
|
audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key)
|
||||||
|
{
|
||||||
|
- char *fp;
|
||||||
|
+ char *key_fp = NULL;
|
||||||
|
+ char *issuer_fp = NULL;
|
||||||
|
+ struct sshkey_cert *cert = NULL;
|
||||||
|
|
||||||
|
- fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX);
|
||||||
|
- if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0)
|
||||||
|
+ key_fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX);
|
||||||
|
+ if (sshkey_is_cert(key) && key->cert != NULL && key->cert->signature_key != NULL) {
|
||||||
|
+ cert = key->cert;
|
||||||
|
+ issuer_fp = sshkey_fingerprint(cert->signature_key,
|
||||||
|
+ options.fingerprint_hash, SSH_FP_DEFAULT);
|
||||||
|
+ }
|
||||||
|
+ if (audit_keyusage(ssh, host_user, key_fp, cert, issuer_fp, (*rv == 0)) == 0)
|
||||||
|
*rv = -SSH_ERR_INTERNAL_ERROR;
|
||||||
|
- free(fp);
|
||||||
|
+ if (key_fp)
|
||||||
|
+ free(key_fp);
|
||||||
|
+ if (issuer_fp)
|
||||||
|
+ free(issuer_fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
diff -up openssh-9.0p1/audit.h.patch openssh-9.0p1/audit.h
|
||||||
|
--- openssh-9.0p1/audit.h.patch 2022-10-24 15:02:16.544858331 +0200
|
||||||
|
+++ openssh-9.0p1/audit.h 2022-10-24 14:58:20.887565518 +0200
|
||||||
|
@@ -64,7 +64,7 @@ void audit_session_close(struct logininf
|
||||||
|
int audit_run_command(struct ssh *, const char *);
|
||||||
|
void audit_end_command(struct ssh *, int, const char *);
|
||||||
|
ssh_audit_event_t audit_classify_auth(const char *);
|
||||||
|
-int audit_keyusage(struct ssh *, int, char *, int);
|
||||||
|
+int audit_keyusage(struct ssh *, int, const char *, const struct sshkey_cert *, const char *, int);
|
||||||
|
void audit_key(struct ssh *, int, int *, const struct sshkey *);
|
||||||
|
void audit_unsupported(struct ssh *, int);
|
||||||
|
void audit_kex(struct ssh *, int, char *, char *, char *, char *);
|
||||||
|
diff -up openssh-9.0p1/audit-linux.c.patch openssh-9.0p1/audit-linux.c
|
||||||
|
--- openssh-9.0p1/audit-linux.c.patch 2022-10-24 15:02:16.544858331 +0200
|
||||||
|
+++ openssh-9.0p1/audit-linux.c 2022-10-24 15:21:58.165303951 +0200
|
||||||
|
@@ -137,10 +137,12 @@ fatal_report:
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
-audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv)
|
||||||
|
+audit_keyusage(struct ssh *ssh, int host_user, const char *key_fp, const struct sshkey_cert *cert, const char *issuer_fp, int rv)
|
||||||
|
{
|
||||||
|
char buf[AUDIT_LOG_SIZE];
|
||||||
|
int audit_fd, rc, saved_errno;
|
||||||
|
+ const char *rip;
|
||||||
|
+ u_int i;
|
||||||
|
|
||||||
|
audit_fd = audit_open();
|
||||||
|
if (audit_fd < 0) {
|
||||||
|
@@ -150,14 +152,44 @@ audit_keyusage(struct ssh *ssh, int host
|
||||||
|
else
|
||||||
|
return 0; /* Must prevent login */
|
||||||
|
}
|
||||||
|
+ rip = ssh_remote_ipaddr(ssh);
|
||||||
|
snprintf(buf, sizeof(buf), "%s_auth grantors=auth-key", host_user ? "pubkey" : "hostbased");
|
||||||
|
rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
|
||||||
|
- buf, audit_username(), -1, NULL, ssh_remote_ipaddr(ssh), NULL, rv);
|
||||||
|
+ buf, audit_username(), -1, NULL, rip, NULL, rv);
|
||||||
|
if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
|
||||||
|
goto out;
|
||||||
|
- snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", fp);
|
||||||
|
+ snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", key_fp);
|
||||||
|
rc = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, buf, NULL,
|
||||||
|
- ssh_remote_ipaddr(ssh), NULL, rv);
|
||||||
|
+ rip, NULL, rv);
|
||||||
|
+ if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ if (cert) {
|
||||||
|
+ char *pbuf;
|
||||||
|
+
|
||||||
|
+ pbuf = audit_encode_nv_string("key_id", cert->key_id, 0);
|
||||||
|
+ if (pbuf == NULL)
|
||||||
|
+ goto out;
|
||||||
|
+ snprintf(buf, sizeof(buf), "cert %s cert_serial=%llu cert_issuer_alg=\"%s\" cert_issuer_fp=\"%s\"",
|
||||||
|
+ pbuf, (unsigned long long)cert->serial, sshkey_type(cert->signature_key), issuer_fp);
|
||||||
|
+ free(pbuf);
|
||||||
|
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
|
||||||
|
+ buf, audit_username(), -1, NULL, rip, NULL, rv);
|
||||||
|
+ if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ for (i = 0; cert->principals != NULL && i < cert->nprincipals; i++) {
|
||||||
|
+ pbuf = audit_encode_nv_string("cert_principal", cert->principals[i], 0);
|
||||||
|
+ if (pbuf == NULL)
|
||||||
|
+ goto out;
|
||||||
|
+ snprintf(buf, sizeof(buf), "principal %s", pbuf);
|
||||||
|
+ free(pbuf);
|
||||||
|
+ rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL,
|
||||||
|
+ buf, audit_username(), -1, NULL, rip, NULL, rv);
|
||||||
|
+ if ((rc < 0) && ((rc != -1) || (getuid() == 0)))
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
out:
|
||||||
|
saved_errno = errno;
|
||||||
|
audit_close(audit_fd);
|
@ -1,57 +0,0 @@
|
|||||||
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
|
|
||||||
index d29a03b4..d7283136 100644
|
|
||||||
--- a/ssh-keyscan.c
|
|
||||||
+++ b/ssh-keyscan.c
|
|
||||||
@@ -490,6 +490,15 @@ congreet(int s)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
+ /*
|
|
||||||
+ * Read the server banner as per RFC4253 section 4.2. The "SSH-"
|
|
||||||
+ * protocol identification string may be preceeded by an arbitarily
|
|
||||||
+ * large banner which we must read and ignore. Loop while reading
|
|
||||||
+ * newline-terminated lines until we have one starting with "SSH-".
|
|
||||||
+ * The ID string cannot be longer than 255 characters although the
|
|
||||||
+ * preceeding banner lines may (in which case they'll be discarded
|
|
||||||
+ * in multiple iterations of the outer loop).
|
|
||||||
+ */
|
|
||||||
for (;;) {
|
|
||||||
memset(buf, '\0', sizeof(buf));
|
|
||||||
bufsiz = sizeof(buf);
|
|
||||||
@@ -517,6 +526,11 @@ congreet(int s)
|
|
||||||
conrecycle(s);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
+ if (cp >= buf + sizeof(buf)) {
|
|
||||||
+ error("%s: greeting exceeds allowable length", c->c_name);
|
|
||||||
+ confree(s);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
if (*cp != '\n' && *cp != '\r') {
|
|
||||||
error("%s: bad greeting", c->c_name);
|
|
||||||
confree(s);
|
|
||||||
diff --git a/sshsig.c b/sshsig.c
|
|
||||||
index 1e3b6398..eb2a931e 100644
|
|
||||||
--- a/sshsig.c
|
|
||||||
+++ b/sshsig.c
|
|
||||||
@@ -491,7 +491,7 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
|
|
||||||
{
|
|
||||||
char *hex, rbuf[8192], hash[SSH_DIGEST_MAX_LENGTH];
|
|
||||||
ssize_t n, total = 0;
|
|
||||||
- struct ssh_digest_ctx *ctx;
|
|
||||||
+ struct ssh_digest_ctx *ctx = NULL;
|
|
||||||
int alg, oerrno, r = SSH_ERR_INTERNAL_ERROR;
|
|
||||||
struct sshbuf *b = NULL;
|
|
||||||
|
|
||||||
@@ -549,9 +548,11 @@ hash_file(int fd, const char *hashalg, struct sshbuf **bp)
|
|
||||||
/* success */
|
|
||||||
r = 0;
|
|
||||||
out:
|
|
||||||
+ oerrno = errno;
|
|
||||||
sshbuf_free(b);
|
|
||||||
ssh_digest_free(ctx);
|
|
||||||
explicit_bzero(hash, sizeof(hash));
|
|
||||||
+ errno = oerrno;
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
@ -1,52 +0,0 @@
|
|||||||
--- openssh-9.3p1/openbsd-compat/openssl-compat.c 2023-03-15 22:28:19.000000000 +0100
|
|
||||||
+++ /home/dbelyavs/work/upstream/openssh-portable/openbsd-compat/openssl-compat.c 2023-05-25 14:19:42.870841944 +0200
|
|
||||||
@@ -33,10 +33,10 @@
|
|
||||||
|
|
||||||
/*
|
|
||||||
* OpenSSL version numbers: MNNFFPPS: major minor fix patch status
|
|
||||||
- * We match major, minor, fix and status (not patch) for <1.0.0.
|
|
||||||
- * After that, we acceptable compatible fix versions (so we
|
|
||||||
- * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed
|
|
||||||
- * within a patch series.
|
|
||||||
+ * Versions >=3 require only major versions to match.
|
|
||||||
+ * For versions <3, we accept compatible fix versions (so we allow 1.0.1
|
|
||||||
+ * to work with 1.0.0). Going backwards is only allowed within a patch series.
|
|
||||||
+ * See https://www.openssl.org/policies/releasestrat.html
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
@@ -48,15 +48,17 @@
|
|
||||||
if (headerver == libver)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
- /* for versions < 1.0.0, major,minor,fix,status must match */
|
|
||||||
- if (headerver < 0x1000000f) {
|
|
||||||
- mask = 0xfffff00fL; /* major,minor,fix,status */
|
|
||||||
+ /*
|
|
||||||
+ * For versions >= 3.0, only the major and status must match.
|
|
||||||
+ */
|
|
||||||
+ if (headerver >= 0x3000000f) {
|
|
||||||
+ mask = 0xf000000fL; /* major,status */
|
|
||||||
return (headerver & mask) == (libver & mask);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
- * For versions >= 1.0.0, major,minor,status must match and library
|
|
||||||
- * fix version must be equal to or newer than the header.
|
|
||||||
+ * For versions >= 1.0.0, but <3, major,minor,status must match and
|
|
||||||
+ * library fix version must be equal to or newer than the header.
|
|
||||||
*/
|
|
||||||
mask = 0xfff0000fL; /* major,minor,status */
|
|
||||||
hfix = (headerver & 0x000ff000) >> 12;
|
|
||||||
diff -up openssh-8.7p1/configure.ac.check openssh-8.7p1/configure.ac
|
|
||||||
--- openssh-8.7p1/configure.ac.check 2023-11-27 14:54:32.959113758 +0100
|
|
||||||
+++ openssh-8.7p1/configure.ac 2023-11-27 14:54:49.467500523 +0100
|
|
||||||
@@ -2821,7 +2821,7 @@ if test "x$openssl" = "xyes" ; then
|
|
||||||
;;
|
|
||||||
101*) ;; # 1.1.x
|
|
||||||
200*) ;; # LibreSSL
|
|
||||||
- 300*) ;; # OpenSSL development branch.
|
|
||||||
+ 30*) ;; # OpenSSL 3.x series
|
|
||||||
*)
|
|
||||||
AC_MSG_ERROR([Unknown/unsupported OpenSSL version ("$ssl_library_ver")])
|
|
||||||
;;
|
|
@ -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 */
|
|
@ -1,33 +0,0 @@
|
|||||||
diff -u -p -r1.166 auth2.c
|
|
||||||
--- a/auth2.c 8 Mar 2023 04:43:12 -0000 1.166
|
|
||||||
+++ b/auth2.c 28 Aug 2023 08:32:44 -0000
|
|
||||||
@@ -208,6 +208,7 @@ input_service_request(int type, u_int32_
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MIN_FAIL_DELAY_SECONDS 0.005
|
|
||||||
+#define MAX_FAIL_DELAY_SECONDS 5.0
|
|
||||||
static double
|
|
||||||
user_specific_delay(const char *user)
|
|
||||||
{
|
|
||||||
@@ -233,6 +234,12 @@ ensure_minimum_time_since(double start,
|
|
||||||
struct timespec ts;
|
|
||||||
double elapsed = monotime_double() - start, req = seconds, remain;
|
|
||||||
|
|
||||||
+ if (elapsed > MAX_FAIL_DELAY_SECONDS) {
|
|
||||||
+ debug3_f("elapsed %0.3lfms exceeded the max delay "
|
|
||||||
+ "requested %0.3lfms)", elapsed*1000, req*1000);
|
|
||||||
+ return;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
/* if we've already passed the requested time, scale up */
|
|
||||||
while ((remain = seconds - elapsed) < 0.0)
|
|
||||||
seconds *= 2;
|
|
||||||
@@ -317,7 +324,7 @@ input_userauth_request(int type, u_int32
|
|
||||||
debug2("input_userauth_request: try method %s", method);
|
|
||||||
authenticated = m->userauth(ssh);
|
|
||||||
}
|
|
||||||
- if (!authctxt->authenticated)
|
|
||||||
+ if (!authctxt->authenticated && strcmp(method, "none") != 0)
|
|
||||||
ensure_minimum_time_since(tstart,
|
|
||||||
user_specific_delay(authctxt->user));
|
|
||||||
userauth_finish(ssh, authenticated, method, NULL);
|
|
@ -1,447 +0,0 @@
|
|||||||
diff --git a/PROTOCOL b/PROTOCOL
|
|
||||||
index d453c779..ded935eb 100644
|
|
||||||
--- a/PROTOCOL
|
|
||||||
+++ b/PROTOCOL
|
|
||||||
@@ -137,6 +137,32 @@ than as a named global or channel request to allow pings with very
|
|
||||||
described at:
|
|
||||||
http://git.libssh.org/users/aris/libssh.git/plain/doc/curve25519-sha256@libssh.org.txt?h=curve25519
|
|
||||||
|
|
||||||
+1.9 transport: strict key exchange extension
|
|
||||||
+
|
|
||||||
+OpenSSH supports a number of transport-layer hardening measures under
|
|
||||||
+a "strict KEX" feature. This feature is signalled similarly to the
|
|
||||||
+RFC8308 ext-info feature: by including a additional algorithm in the
|
|
||||||
+initiial SSH2_MSG_KEXINIT kex_algorithms field. The client may append
|
|
||||||
+"kex-strict-c-v00@openssh.com" to its kex_algorithms and the server
|
|
||||||
+may append "kex-strict-s-v00@openssh.com". These pseudo-algorithms
|
|
||||||
+are only valid in the initial SSH2_MSG_KEXINIT and MUST be ignored
|
|
||||||
+if they are present in subsequent SSH2_MSG_KEXINIT packets.
|
|
||||||
+
|
|
||||||
+When an endpoint that supports this extension observes this algorithm
|
|
||||||
+name in a peer's KEXINIT packet, it MUST make the following changes to
|
|
||||||
+the the protocol:
|
|
||||||
+
|
|
||||||
+a) During initial KEX, terminate the connection if any unexpected or
|
|
||||||
+ out-of-sequence packet is received. This includes terminating the
|
|
||||||
+ connection if the first packet received is not SSH2_MSG_KEXINIT.
|
|
||||||
+ Unexpected packets for the purpose of strict KEX include messages
|
|
||||||
+ that are otherwise valid at any time during the connection such as
|
|
||||||
+ SSH2_MSG_DEBUG and SSH2_MSG_IGNORE.
|
|
||||||
+b) After sending or receiving a SSH2_MSG_NEWKEYS message, reset the
|
|
||||||
+ packet sequence number to zero. This behaviour persists for the
|
|
||||||
+ duration of the connection (i.e. not just the first
|
|
||||||
+ SSH2_MSG_NEWKEYS).
|
|
||||||
+
|
|
||||||
2. Connection protocol changes
|
|
||||||
|
|
||||||
2.1. connection: Channel write close extension "eow@openssh.com"
|
|
||||||
diff --git a/kex.c b/kex.c
|
|
||||||
index aa5e792d..d478ff6e 100644
|
|
||||||
--- a/kex.c
|
|
||||||
+++ b/kex.c
|
|
||||||
@@ -65,7 +65,7 @@
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* prototype */
|
|
||||||
-static int kex_choose_conf(struct ssh *);
|
|
||||||
+static int kex_choose_conf(struct ssh *, uint32_t seq);
|
|
||||||
static int kex_input_newkeys(int, u_int32_t, struct ssh *);
|
|
||||||
|
|
||||||
static const char *proposal_names[PROPOSAL_MAX] = {
|
|
||||||
@@ -177,6 +177,18 @@ kex_names_valid(const char *names)
|
|
||||||
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;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Concatenate algorithm names, avoiding duplicates in the process.
|
|
||||||
* Caller must free returned string.
|
|
||||||
@@ -184,7 +196,7 @@ kex_names_valid(const char *names)
|
|
||||||
char *
|
|
||||||
kex_names_cat(const char *a, const char *b)
|
|
||||||
{
|
|
||||||
- char *ret = NULL, *tmp = NULL, *cp, *p, *m;
|
|
||||||
+ char *ret = NULL, *tmp = NULL, *cp, *p;
|
|
||||||
size_t len;
|
|
||||||
|
|
||||||
if (a == NULL || *a == '\0')
|
|
||||||
@@ -201,10 +213,8 @@ kex_names_cat(const char *a, const char *b)
|
|
||||||
}
|
|
||||||
strlcpy(ret, a, len);
|
|
||||||
for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) {
|
|
||||||
- if ((m = match_list(ret, p, NULL)) != NULL) {
|
|
||||||
- free(m);
|
|
||||||
+ if (has_any_alg(ret, p))
|
|
||||||
continue; /* Algorithm already present */
|
|
||||||
- }
|
|
||||||
if (strlcat(ret, ",", len) >= len ||
|
|
||||||
strlcat(ret, p, len) >= len) {
|
|
||||||
free(tmp);
|
|
||||||
@@ -466,7 +485,12 @@ kex_protocol_error(int type, u_int32_t seq, struct ssh *ssh)
|
|
||||||
{
|
|
||||||
int r;
|
|
||||||
|
|
||||||
- error("kex protocol error: type %d seq %u", type, seq);
|
|
||||||
+ /* If in strict mode, any unexpected message is an error */
|
|
||||||
+ if ((ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict) {
|
|
||||||
+ ssh_packet_disconnect(ssh, "strict KEX violation: "
|
|
||||||
+ "unexpected packet type %u (seqnr %u)", type, seq);
|
|
||||||
+ }
|
|
||||||
+ error_f("type %u seq %u", type, seq);
|
|
||||||
if ((r = sshpkt_start(ssh, SSH2_MSG_UNIMPLEMENTED)) != 0 ||
|
|
||||||
(r = sshpkt_put_u32(ssh, seq)) != 0 ||
|
|
||||||
(r = sshpkt_send(ssh)) != 0)
|
|
||||||
@@ -548,6 +572,11 @@ kex_input_ext_info(int type, u_int32_t seq, struct ssh *ssh)
|
|
||||||
ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &kex_protocol_error);
|
|
||||||
if ((r = sshpkt_get_u32(ssh, &ninfo)) != 0)
|
|
||||||
return r;
|
|
||||||
+ if (ninfo >= 1024) {
|
|
||||||
+ error("SSH2_MSG_EXT_INFO with too many entries, expected "
|
|
||||||
+ "<=1024, received %u", ninfo);
|
|
||||||
+ return dispatch_protocol_error(type, seq, ssh);
|
|
||||||
+ }
|
|
||||||
for (i = 0; i < ninfo; i++) {
|
|
||||||
if ((r = sshpkt_get_cstring(ssh, &name, NULL)) != 0)
|
|
||||||
return r;
|
|
||||||
@@ -681,7 +705,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
|
|
||||||
error_f("no kex");
|
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
|
||||||
}
|
|
||||||
- ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, NULL);
|
|
||||||
+ ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_protocol_error);
|
|
||||||
ptr = sshpkt_ptr(ssh, &dlen);
|
|
||||||
if ((r = sshbuf_put(kex->peer, ptr, dlen)) != 0)
|
|
||||||
return r;
|
|
||||||
@@ -717,7 +741,7 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
|
|
||||||
if (!(kex->flags & KEX_INIT_SENT))
|
|
||||||
if ((r = kex_send_kexinit(ssh)) != 0)
|
|
||||||
return r;
|
|
||||||
- if ((r = kex_choose_conf(ssh)) != 0)
|
|
||||||
+ if ((r = kex_choose_conf(ssh, seq)) != 0)
|
|
||||||
return r;
|
|
||||||
|
|
||||||
if (kex->kex_type < KEX_MAX && kex->kex[kex->kex_type] != NULL)
|
|
||||||
@@ -981,20 +1005,14 @@ proposals_match(char *my[PROPOSAL_MAX], char *peer[PROPOSAL_MAX])
|
|
||||||
return (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
-/* returns non-zero if proposal contains any algorithm from algs */
|
|
||||||
static int
|
|
||||||
-has_any_alg(const char *proposal, const char *algs)
|
|
||||||
+kexalgs_contains(char **peer, const char *ext)
|
|
||||||
{
|
|
||||||
- char *cp;
|
|
||||||
-
|
|
||||||
- if ((cp = match_list(proposal, algs, NULL)) == NULL)
|
|
||||||
- return 0;
|
|
||||||
- free(cp);
|
|
||||||
- return 1;
|
|
||||||
+ return has_any_alg(peer[PROPOSAL_KEX_ALGS], ext);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
-kex_choose_conf(struct ssh *ssh)
|
|
||||||
+kex_choose_conf(struct ssh *ssh, uint32_t seq)
|
|
||||||
{
|
|
||||||
struct kex *kex = ssh->kex;
|
|
||||||
struct newkeys *newkeys;
|
|
||||||
@@ -1019,13 +1037,23 @@ kex_choose_conf(struct ssh *ssh)
|
|
||||||
sprop=peer;
|
|
||||||
}
|
|
||||||
|
|
||||||
- /* Check whether client supports ext_info_c */
|
|
||||||
- if (kex->server && (kex->flags & KEX_INITIAL)) {
|
|
||||||
- char *ext;
|
|
||||||
-
|
|
||||||
- ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL);
|
|
||||||
- kex->ext_info_c = (ext != NULL);
|
|
||||||
- free(ext);
|
|
||||||
+ /* Check whether peer supports ext_info/kex_strict */
|
|
||||||
+ if ((kex->flags & KEX_INITIAL) != 0) {
|
|
||||||
+ if (kex->server) {
|
|
||||||
+ kex->ext_info_c = kexalgs_contains(peer, "ext-info-c");
|
|
||||||
+ kex->kex_strict = kexalgs_contains(peer,
|
|
||||||
+ "kex-strict-c-v00@openssh.com");
|
|
||||||
+ } else {
|
|
||||||
+ kex->kex_strict = kexalgs_contains(peer,
|
|
||||||
+ "kex-strict-s-v00@openssh.com");
|
|
||||||
+ }
|
|
||||||
+ if (kex->kex_strict) {
|
|
||||||
+ debug3_f("will use strict KEX ordering");
|
|
||||||
+ if (seq != 0)
|
|
||||||
+ ssh_packet_disconnect(ssh,
|
|
||||||
+ "strict KEX violation: "
|
|
||||||
+ "KEXINIT was not the first packet");
|
|
||||||
+ }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check whether client supports rsa-sha2 algorithms */
|
|
||||||
diff --git a/kex.h b/kex.h
|
|
||||||
index 5f7ef784..272ebb43 100644
|
|
||||||
--- a/kex.h
|
|
||||||
+++ b/kex.h
|
|
||||||
@@ -149,6 +149,7 @@ struct kex {
|
|
||||||
u_int kex_type;
|
|
||||||
char *server_sig_algs;
|
|
||||||
int ext_info_c;
|
|
||||||
+ int kex_strict;
|
|
||||||
struct sshbuf *my;
|
|
||||||
struct sshbuf *peer;
|
|
||||||
struct sshbuf *client_version;
|
|
||||||
diff --git a/packet.c b/packet.c
|
|
||||||
index 52017def..beb214f9 100644
|
|
||||||
--- a/packet.c
|
|
||||||
+++ b/packet.c
|
|
||||||
@@ -1207,8 +1207,13 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
|
|
||||||
sshbuf_dump(state->output, stderr);
|
|
||||||
#endif
|
|
||||||
/* increment sequence number for outgoing packets */
|
|
||||||
- if (++state->p_send.seqnr == 0)
|
|
||||||
+ if (++state->p_send.seqnr == 0) {
|
|
||||||
+ if ((ssh->kex->flags & KEX_INITIAL) != 0) {
|
|
||||||
+ ssh_packet_disconnect(ssh, "outgoing sequence number "
|
|
||||||
+ "wrapped during initial key exchange");
|
|
||||||
+ }
|
|
||||||
logit("outgoing seqnr wraps around");
|
|
||||||
+ }
|
|
||||||
if (++state->p_send.packets == 0)
|
|
||||||
if (!(ssh->compat & SSH_BUG_NOREKEY))
|
|
||||||
return SSH_ERR_NEED_REKEY;
|
|
||||||
@@ -1216,6 +1221,11 @@ ssh_packet_send2_wrapped(struct ssh *ssh)
|
|
||||||
state->p_send.bytes += len;
|
|
||||||
sshbuf_reset(state->outgoing_packet);
|
|
||||||
|
|
||||||
+ if (type == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) {
|
|
||||||
+ debug_f("resetting send seqnr %u", state->p_send.seqnr);
|
|
||||||
+ state->p_send.seqnr = 0;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
if (type == SSH2_MSG_NEWKEYS)
|
|
||||||
r = ssh_set_newkeys(ssh, MODE_OUT);
|
|
||||||
else if (type == SSH2_MSG_USERAUTH_SUCCESS && state->server_side)
|
|
||||||
@@ -1344,8 +1354,7 @@ ssh_packet_read_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
|
||||||
/* Stay in the loop until we have received a complete packet. */
|
|
||||||
for (;;) {
|
|
||||||
/* Try to read a packet from the buffer. */
|
|
||||||
- r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p);
|
|
||||||
- if (r != 0)
|
|
||||||
+ if ((r = ssh_packet_read_poll_seqnr(ssh, typep, seqnr_p)) != 0)
|
|
||||||
break;
|
|
||||||
/* If we got a packet, return it. */
|
|
||||||
if (*typep != SSH_MSG_NONE)
|
|
||||||
@@ -1629,10 +1615,16 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
|
||||||
if ((r = sshbuf_consume(state->input, mac->mac_len)) != 0)
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
+
|
|
||||||
if (seqnr_p != NULL)
|
|
||||||
*seqnr_p = state->p_read.seqnr;
|
|
||||||
- if (++state->p_read.seqnr == 0)
|
|
||||||
+ if (++state->p_read.seqnr == 0) {
|
|
||||||
+ if ((ssh->kex->flags & KEX_INITIAL) != 0) {
|
|
||||||
+ ssh_packet_disconnect(ssh, "incoming sequence number "
|
|
||||||
+ "wrapped during initial key exchange");
|
|
||||||
+ }
|
|
||||||
logit("incoming seqnr wraps around");
|
|
||||||
+ }
|
|
||||||
if (++state->p_read.packets == 0)
|
|
||||||
if (!(ssh->compat & SSH_BUG_NOREKEY))
|
|
||||||
return SSH_ERR_NEED_REKEY;
|
|
||||||
@@ -1698,6 +1690,10 @@ ssh_packet_read_poll2(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
|
||||||
#endif
|
|
||||||
/* reset for next packet */
|
|
||||||
state->packlen = 0;
|
|
||||||
+ if (*typep == SSH2_MSG_NEWKEYS && ssh->kex->kex_strict) {
|
|
||||||
+ debug_f("resetting read seqnr %u", state->p_read.seqnr);
|
|
||||||
+ state->p_read.seqnr = 0;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
if ((r = ssh_packet_check_rekey(ssh)) != 0)
|
|
||||||
return r;
|
|
||||||
@@ -1720,10 +1716,39 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
|
||||||
r = ssh_packet_read_poll2(ssh, typep, seqnr_p);
|
|
||||||
if (r != 0)
|
|
||||||
return r;
|
|
||||||
- if (*typep) {
|
|
||||||
- state->keep_alive_timeouts = 0;
|
|
||||||
- DBG(debug("received packet type %d", *typep));
|
|
||||||
+ if (*typep == 0) {
|
|
||||||
+ /* no message ready */
|
|
||||||
+ return 0;
|
|
||||||
}
|
|
||||||
+ state->keep_alive_timeouts = 0;
|
|
||||||
+ DBG(debug("received packet type %d", *typep));
|
|
||||||
+
|
|
||||||
+ /* Always process disconnect messages */
|
|
||||||
+ if (*typep == SSH2_MSG_DISCONNECT) {
|
|
||||||
+ if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
|
|
||||||
+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
|
|
||||||
+ return r;
|
|
||||||
+ /* Ignore normal client exit notifications */
|
|
||||||
+ do_log2(ssh->state->server_side &&
|
|
||||||
+ reason == SSH2_DISCONNECT_BY_APPLICATION ?
|
|
||||||
+ SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
|
|
||||||
+ "Received disconnect from %s port %d:"
|
|
||||||
+ "%u: %.400s", ssh_remote_ipaddr(ssh),
|
|
||||||
+ ssh_remote_port(ssh), reason, msg);
|
|
||||||
+ free(msg);
|
|
||||||
+ return SSH_ERR_DISCONNECTED;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Do not implicitly handle any messages here during initial
|
|
||||||
+ * KEX when in strict mode. They will be need to be allowed
|
|
||||||
+ * explicitly by the KEX dispatch table or they will generate
|
|
||||||
+ * protocol errors.
|
|
||||||
+ */
|
|
||||||
+ if (ssh->kex != NULL &&
|
|
||||||
+ (ssh->kex->flags & KEX_INITIAL) && ssh->kex->kex_strict)
|
|
||||||
+ return 0;
|
|
||||||
+ /* Implicitly handle transport-level messages */
|
|
||||||
switch (*typep) {
|
|
||||||
case SSH2_MSG_IGNORE:
|
|
||||||
debug3("Received SSH2_MSG_IGNORE");
|
|
||||||
@@ -1738,19 +1763,6 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
|
||||||
debug("Remote: %.900s", msg);
|
|
||||||
free(msg);
|
|
||||||
break;
|
|
||||||
- case SSH2_MSG_DISCONNECT:
|
|
||||||
- if ((r = sshpkt_get_u32(ssh, &reason)) != 0 ||
|
|
||||||
- (r = sshpkt_get_string(ssh, &msg, NULL)) != 0)
|
|
||||||
- return r;
|
|
||||||
- /* Ignore normal client exit notifications */
|
|
||||||
- do_log2(ssh->state->server_side &&
|
|
||||||
- reason == SSH2_DISCONNECT_BY_APPLICATION ?
|
|
||||||
- SYSLOG_LEVEL_INFO : SYSLOG_LEVEL_ERROR,
|
|
||||||
- "Received disconnect from %s port %d:"
|
|
||||||
- "%u: %.400s", ssh_remote_ipaddr(ssh),
|
|
||||||
- ssh_remote_port(ssh), reason, msg);
|
|
||||||
- free(msg);
|
|
||||||
- return SSH_ERR_DISCONNECTED;
|
|
||||||
case SSH2_MSG_UNIMPLEMENTED:
|
|
||||||
if ((r = sshpkt_get_u32(ssh, &seqnr)) != 0)
|
|
||||||
return r;
|
|
||||||
@@ -2242,6 +2254,7 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
|
|
||||||
(r = sshbuf_put_u32(m, kex->hostkey_type)) != 0 ||
|
|
||||||
(r = sshbuf_put_u32(m, kex->hostkey_nid)) != 0 ||
|
|
||||||
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_u32(m, kex->kex_strict)) != 0 ||
|
|
||||||
(r = sshbuf_put_stringb(m, kex->my)) != 0 ||
|
|
||||||
(r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
|
|
||||||
(r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
|
|
||||||
@@ -2404,6 +2417,7 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
|
|
||||||
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_type)) != 0 ||
|
|
||||||
(r = sshbuf_get_u32(m, (u_int *)&kex->hostkey_nid)) != 0 ||
|
|
||||||
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
|
|
||||||
+ (r = sshbuf_get_u32(m, &kex->kex_strict)) != 0 ||
|
|
||||||
(r = sshbuf_get_stringb(m, kex->my)) != 0 ||
|
|
||||||
(r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
|
|
||||||
(r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
|
|
||||||
@@ -2732,6 +2746,7 @@ sshpkt_disconnect(struct ssh *ssh, const char *fmt,...)
|
|
||||||
vsnprintf(buf, sizeof(buf), fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
+ debug2_f("sending SSH2_MSG_DISCONNECT: %s", buf);
|
|
||||||
if ((r = sshpkt_start(ssh, SSH2_MSG_DISCONNECT)) != 0 ||
|
|
||||||
(r = sshpkt_put_u32(ssh, SSH2_DISCONNECT_PROTOCOL_ERROR)) != 0 ||
|
|
||||||
(r = sshpkt_put_cstring(ssh, buf)) != 0 ||
|
|
||||||
diff --git a/sshconnect2.c b/sshconnect2.c
|
|
||||||
index df6caf81..0cccbcc4 100644
|
|
||||||
--- a/sshconnect2.c
|
|
||||||
+++ b/sshconnect2.c
|
|
||||||
@@ -253,7 +253,8 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
|
||||||
fatal_fr(r, "kex_assemble_namelist");
|
|
||||||
free(all_key);
|
|
||||||
|
|
||||||
- if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL)
|
|
||||||
+ if ((s = kex_names_cat(options.kex_algorithms,
|
|
||||||
+ "ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
|
|
||||||
fatal_f("kex_names_cat");
|
|
||||||
myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, s);
|
|
||||||
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
|
|
||||||
@@ -358,7 +358,6 @@ struct cauthmethod {
|
|
||||||
};
|
|
||||||
|
|
||||||
static int input_userauth_service_accept(int, u_int32_t, struct ssh *);
|
|
||||||
-static int input_userauth_ext_info(int, u_int32_t, struct ssh *);
|
|
||||||
static int input_userauth_success(int, u_int32_t, struct ssh *);
|
|
||||||
static int input_userauth_failure(int, u_int32_t, struct ssh *);
|
|
||||||
static int input_userauth_banner(int, u_int32_t, struct ssh *);
|
|
||||||
@@ -472,7 +471,7 @@ ssh_userauth2(struct ssh *ssh, const char *local_user,
|
|
||||||
|
|
||||||
ssh->authctxt = &authctxt;
|
|
||||||
ssh_dispatch_init(ssh, &input_userauth_error);
|
|
||||||
- ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, &input_userauth_ext_info);
|
|
||||||
+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, kex_input_ext_info);
|
|
||||||
ssh_dispatch_set(ssh, SSH2_MSG_SERVICE_ACCEPT, &input_userauth_service_accept);
|
|
||||||
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &authctxt.success); /* loop until success */
|
|
||||||
pubkey_cleanup(ssh);
|
|
||||||
@@ -531,12 +530,6 @@ input_userauth_service_accept(int type, u_int32_t seq, struct ssh *ssh)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ARGSUSED */
|
|
||||||
-static int
|
|
||||||
-input_userauth_ext_info(int type, u_int32_t seqnr, struct ssh *ssh)
|
|
||||||
-{
|
|
||||||
- return kex_input_ext_info(type, seqnr, ssh);
|
|
||||||
-}
|
|
||||||
-
|
|
||||||
void
|
|
||||||
userauth(struct ssh *ssh, char *authlist)
|
|
||||||
{
|
|
||||||
@@ -615,6 +608,7 @@ input_userauth_success(int type, u_int32_t seq, struct ssh *ssh)
|
|
||||||
free(authctxt->methoddata);
|
|
||||||
authctxt->methoddata = NULL;
|
|
||||||
authctxt->success = 1; /* break out */
|
|
||||||
+ ssh_dispatch_set(ssh, SSH2_MSG_EXT_INFO, dispatch_protocol_error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff -up openssh-8.7p1/sshd.c.kexstrict openssh-8.7p1/sshd.c
|
|
||||||
--- openssh-8.7p1/sshd.c.kexstrict 2023-11-27 13:19:18.855433602 +0100
|
|
||||||
+++ openssh-8.7p1/sshd.c 2023-11-27 13:28:10.441325314 +0100
|
|
||||||
@@ -2531,10 +2531,14 @@ do_ssh2_kex(struct ssh *ssh)
|
|
||||||
struct kex *kex;
|
|
||||||
char *hostkey_types = NULL;
|
|
||||||
char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
|
|
||||||
+ char *cp;
|
|
||||||
int r;
|
|
||||||
|
|
||||||
- myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh,
|
|
||||||
- options.kex_algorithms);
|
|
||||||
+ if ((cp = kex_names_cat(options.kex_algorithms,
|
|
||||||
+ "kex-strict-s-v00@openssh.com")) == NULL)
|
|
||||||
+ fatal_f("kex_names_cat");
|
|
||||||
+
|
|
||||||
+ myproposal[PROPOSAL_KEX_ALGS] = prop_kex = compat_kex_proposal(ssh, cp);
|
|
||||||
myproposal[PROPOSAL_ENC_ALGS_CTOS] =
|
|
||||||
myproposal[PROPOSAL_ENC_ALGS_STOC] = prop_enc =
|
|
||||||
compat_cipher_proposal(ssh, options.ciphers);
|
|
||||||
@@ -2586,7 +2586,7 @@ do_ssh2_kex(struct ssh *ssh)
|
|
||||||
if (gss && orig)
|
|
||||||
xasprintf(&newstr, "%s,%s", gss, orig);
|
|
||||||
else if (gss)
|
|
||||||
- newstr = gss;
|
|
||||||
+ xasprintf(&newstr, "%s,%s", gss, "kex-strict-s-v00@openssh.com");
|
|
||||||
else if (orig)
|
|
||||||
newstr = orig;
|
|
||||||
|
|
||||||
@@ -2650,6 +2654,7 @@ do_ssh2_kex(struct ssh *ssh)
|
|
||||||
#endif
|
|
||||||
free(prop_kex);
|
|
||||||
free(prop_enc);
|
|
||||||
+ free(cp);
|
|
||||||
free(prop_hostkey);
|
|
||||||
debug("KEX done");
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
diff --git a/ssh.c b/ssh.c
|
|
||||||
index 35c48e62..48d93ddf 100644
|
|
||||||
--- a/ssh.c
|
|
||||||
+++ b/ssh.c
|
|
||||||
@@ -626,6 +626,41 @@ ssh_conn_info_free(struct ssh_conn_info *cinfo)
|
|
||||||
free(cinfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
+static int
|
|
||||||
+valid_hostname(const char *s)
|
|
||||||
+{
|
|
||||||
+ size_t i;
|
|
||||||
+
|
|
||||||
+ if (*s == '-')
|
|
||||||
+ return 0;
|
|
||||||
+ for (i = 0; s[i] != 0; i++) {
|
|
||||||
+ if (strchr("'`\"$\\;&<>|(){}", s[i]) != NULL ||
|
|
||||||
+ isspace((u_char)s[i]) || iscntrl((u_char)s[i]))
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+static int
|
|
||||||
+valid_ruser(const char *s)
|
|
||||||
+{
|
|
||||||
+ size_t i;
|
|
||||||
+
|
|
||||||
+ if (*s == '-')
|
|
||||||
+ return 0;
|
|
||||||
+ for (i = 0; s[i] != 0; i++) {
|
|
||||||
+ if (strchr("'`\";&<>|(){}", s[i]) != NULL)
|
|
||||||
+ return 0;
|
|
||||||
+ /* Disallow '-' after whitespace */
|
|
||||||
+ if (isspace((u_char)s[i]) && s[i + 1] == '-')
|
|
||||||
+ return 0;
|
|
||||||
+ /* Disallow \ in last position */
|
|
||||||
+ if (s[i] == '\\' && s[i + 1] == '\0')
|
|
||||||
+ return 0;
|
|
||||||
+ }
|
|
||||||
+ return 1;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Main program for the ssh client.
|
|
||||||
*/
|
|
||||||
@@ -1118,6 +1153,10 @@ main(int ac, char **av)
|
|
||||||
if (!host)
|
|
||||||
usage();
|
|
||||||
|
|
||||||
+ if (!valid_hostname(host))
|
|
||||||
+ fatal("hostname contains invalid characters");
|
|
||||||
+ if (options.user != NULL && !valid_ruser(options.user))
|
|
||||||
+ fatal("remote username contains invalid characters");
|
|
||||||
host_arg = xstrdup(host);
|
|
||||||
|
|
||||||
/* Initialize the command to execute on remote host. */
|
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@
|
|||||||
|
From 26f366e263e575c4e1a18e2e64ba418f58878b37 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Daan De Meyer <daan.j.demeyer@gmail.com>
|
||||||
|
Date: Mon, 20 Mar 2023 20:22:14 +0100
|
||||||
|
Subject: [PATCH] Only set PAM_RHOST if the remote host is not "UNKNOWN"
|
||||||
|
|
||||||
|
When using sshd's -i option with stdio that is not a AF_INET/AF_INET6
|
||||||
|
socket, auth_get_canonical_hostname() returns "UNKNOWN" which is then
|
||||||
|
set as the value of PAM_RHOST, causing pam to try to do a reverse DNS
|
||||||
|
query of "UNKNOWN", which times out multiple times, causing a
|
||||||
|
substantial slowdown when logging in.
|
||||||
|
|
||||||
|
To fix this, let's only set PAM_RHOST if the hostname is not "UNKNOWN".
|
||||||
|
---
|
||||||
|
auth-pam.c | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/auth-pam.c b/auth-pam.c
|
||||||
|
index e143304e3..39b4e4563 100644
|
||||||
|
--- a/auth-pam.c
|
||||||
|
+++ b/auth-pam.c
|
||||||
|
@@ -735,7 +735,7 @@ sshpam_init(struct ssh *ssh, Authctxt *authctxt)
|
||||||
|
sshpam_laddr = get_local_ipaddr(
|
||||||
|
ssh_packet_get_connection_in(ssh));
|
||||||
|
}
|
||||||
|
- if (sshpam_rhost != NULL) {
|
||||||
|
+ if (sshpam_rhost != NULL && strcmp(sshpam_rhost, "UNKNOWN") != 0) {
|
||||||
|
debug("PAM: setting PAM_RHOST to \"%s\"", sshpam_rhost);
|
||||||
|
sshpam_err = pam_set_item(sshpam_handle, PAM_RHOST,
|
||||||
|
sshpam_rhost);
|
||||||
|
--
|
||||||
|
2.44.0
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
diff -up openssh-8.7p1/log.c.xxx openssh-8.7p1/log.c
|
|
||||||
--- openssh-8.7p1/log.c.xxx 2024-06-28 11:02:43.949912398 +0200
|
|
||||||
+++ openssh-8.7p1/log.c 2024-06-28 11:02:58.652297885 +0200
|
|
||||||
@@ -455,12 +455,14 @@ void
|
|
||||||
sshsigdie(const char *file, const char *func, int line, int showfunc,
|
|
||||||
LogLevel level, const char *suffix, const char *fmt, ...)
|
|
||||||
{
|
|
||||||
+#if 0
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
va_start(args, fmt);
|
|
||||||
sshlogv(file, func, line, showfunc, SYSLOG_LEVEL_FATAL,
|
|
||||||
suffix, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
+#endif
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
diff -up openssh-8.7p1/sshd.c.xxx openssh-8.7p1/sshd.c
|
|
||||||
--- openssh-8.7p1/sshd.c.xxx 2024-07-01 10:33:04.332907749 +0200
|
|
||||||
+++ openssh-8.7p1/sshd.c 2024-07-01 10:33:47.843998038 +0200
|
|
||||||
@@ -384,7 +384,7 @@ grace_alarm_handler(int sig)
|
|
||||||
|
|
||||||
/* Log error and exit. */
|
|
||||||
if (use_privsep && pmonitor != NULL && pmonitor->m_pid <= 0)
|
|
||||||
- cleanup_exit(255); /* don't log in privsep child */
|
|
||||||
+ _exit(255); /* don't log in privsep child */
|
|
||||||
else {
|
|
||||||
sigdie("Timeout before authentication for %s port %d",
|
|
||||||
ssh_remote_ipaddr(the_active_state),
|
|
@ -0,0 +1,16 @@
|
|||||||
|
-----BEGIN PGP SIGNATURE-----
|
||||||
|
|
||||||
|
iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmaCMn0ACgkQKj9BTnNg
|
||||||
|
YLrjcBAAgO7xhKUXp8YxdqSZigDbcHu7T37bm1pRTKg2ihPepz+q6pV+DY8AHSRu
|
||||||
|
eyuOCOHYzjLyArFpiMX3z9iT2NqO+KNBvKQoh8loaxNrECmgRGk2jBEKiibFSP5M
|
||||||
|
i6CYkF3sET9xnVDkt4P6KievWXY1/Tl93qve3K2a/bvvgT8s2AaBMM8u4BMGNm3D
|
||||||
|
sc3A6euN0aiXRts2V6I885VyrQDMK++E7+eTHet0ex82KH4I+ceIOwB48hny4wpb
|
||||||
|
Zaqy9pTFisTmFNOF6d3TB58yMWoLQIbLuVrbbbcr7hFYCWsgj0yN5iYQNOR9pU4E
|
||||||
|
ooF+aC0kK9M4iUXthzjjgIjnMzsCmPeKisbwblsPSfSgccj/pCMzW8C3CMVL6AvG
|
||||||
|
slSSLK42qm3f38kx3sg2S8LDW0v+hoyvBmKNFMiBwsF2tWCXIG+oP1PDYpJUpaOJ
|
||||||
|
RFHG7JEPtY94UJGdo5C4YhqDWr3HOqEwuVIt1gWMMPs9IvDkDRo6emmDd64FFAKH
|
||||||
|
ss3hHixu6OHqU5iw6JIVVtYiur6s9m6N/Xxt5Ho6wuqnzUZ+Dwj3L6lF9IOJbJxU
|
||||||
|
Ufb70I1Uko9kXcoje9ONUsqr88wfQY+JZxxVTlzDUDadytCzmO3wXsz+cosMQ5Rw
|
||||||
|
aOZwXYyvmcoZuUQG8GIqRO1wfOcD7o7pI6IyVJQjOeG/rA0eu/4=
|
||||||
|
=Gj2n
|
||||||
|
-----END PGP SIGNATURE-----
|
@ -1,2 +0,0 @@
|
|||||||
#Type Name ID
|
|
||||||
g ssh_keys 101
|
|
@ -1,36 +0,0 @@
|
|||||||
authfd.c
|
|
||||||
authfd.h
|
|
||||||
atomicio.c
|
|
||||||
atomicio.h
|
|
||||||
bufaux.c
|
|
||||||
bufbn.c
|
|
||||||
buffer.h
|
|
||||||
buffer.c
|
|
||||||
cleanup.c
|
|
||||||
cipher.h
|
|
||||||
compat.h
|
|
||||||
entropy.c
|
|
||||||
entropy.h
|
|
||||||
fatal.c
|
|
||||||
includes.h
|
|
||||||
kex.h
|
|
||||||
key.c
|
|
||||||
key.h
|
|
||||||
log.c
|
|
||||||
log.h
|
|
||||||
match.h
|
|
||||||
misc.c
|
|
||||||
misc.h
|
|
||||||
pathnames.h
|
|
||||||
platform.h
|
|
||||||
rsa.h
|
|
||||||
ssh-dss.c
|
|
||||||
ssh-rsa.c
|
|
||||||
ssh.h
|
|
||||||
ssh2.h
|
|
||||||
uidswap.c
|
|
||||||
uidswap.h
|
|
||||||
uuencode.c
|
|
||||||
uuencode.h
|
|
||||||
xmalloc.c
|
|
||||||
xmalloc.h
|
|
@ -1,992 +0,0 @@
|
|||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/get_command_line.c 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -27,6 +27,7 @@
|
|
||||||
* or implied, of Jamie Beverly.
|
|
||||||
*/
|
|
||||||
|
|
||||||
+#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <string.h>
|
|
||||||
@@ -66,8 +67,8 @@ proc_pid_cmdline(char *** inargv)
|
|
||||||
case EOF:
|
|
||||||
case '\0':
|
|
||||||
if (len > 0) {
|
|
||||||
- argv = pamsshagentauth_xrealloc(argv, count + 1, sizeof(*argv));
|
|
||||||
- argv[count] = pamsshagentauth_xcalloc(len + 1, sizeof(*argv[count]));
|
|
||||||
+ argv = xreallocarray(argv, count + 1, sizeof(*argv));
|
|
||||||
+ argv[count] = xcalloc(len + 1, sizeof(*argv[count]));
|
|
||||||
strncpy(argv[count++], argbuf, len);
|
|
||||||
memset(argbuf, '\0', MAX_LEN_PER_CMDLINE_ARG + 1);
|
|
||||||
len = 0;
|
|
||||||
@@ -106,9 +107,9 @@ pamsshagentauth_free_command_line(char *
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < n_args; i++)
|
|
||||||
- pamsshagentauth_xfree(argv[i]);
|
|
||||||
+ free(argv[i]);
|
|
||||||
|
|
||||||
- pamsshagentauth_xfree(argv);
|
|
||||||
+ free(argv);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/identity.h 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -30,8 +30,8 @@
|
|
||||||
#include "openbsd-compat/sys-queue.h"
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "log.h"
|
|
||||||
-#include "buffer.h"
|
|
||||||
-#include "key.h"
|
|
||||||
+#include "sshbuf.h"
|
|
||||||
+#include "sshkey.h"
|
|
||||||
#include "authfd.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ typedef struct idlist Idlist;
|
|
||||||
struct identity {
|
|
||||||
TAILQ_ENTRY(identity) next;
|
|
||||||
AuthenticationConnection *ac; /* set if agent supports key */
|
|
||||||
- Key *key; /* public/private key */
|
|
||||||
+ struct sshkey *key; /* public/private key */
|
|
||||||
char *filename; /* comment for agent-only keys */
|
|
||||||
int tried;
|
|
||||||
int isprivate; /* key points to the private key */
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c.psaa-compat 2020-09-23 10:52:16.421001434 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/iterate_ssh_agent_keys.c 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -36,8 +36,8 @@
|
|
||||||
#include "openbsd-compat/sys-queue.h"
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "log.h"
|
|
||||||
-#include "buffer.h"
|
|
||||||
-#include "key.h"
|
|
||||||
+#include "sshbuf.h"
|
|
||||||
+#include "sshkey.h"
|
|
||||||
#include "authfd.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
@@ -58,6 +58,8 @@
|
|
||||||
#include "get_command_line.h"
|
|
||||||
extern char **environ;
|
|
||||||
|
|
||||||
+#define PAM_SSH_AGENT_AUTH_REQUESTv1 101
|
|
||||||
+
|
|
||||||
/*
|
|
||||||
* Added by Jamie Beverly, ensure socket fd points to a socket owned by the user
|
|
||||||
* A cursory check is done, but to avoid race conditions, it is necessary
|
|
||||||
@@ -77,7 +79,7 @@ log_action(char ** action, size_t count)
|
|
||||||
if (count == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
- buf = pamsshagentauth_xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf));
|
|
||||||
+ buf = xcalloc((count * MAX_LEN_PER_CMDLINE_ARG) + (count * 3), sizeof(*buf));
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
strcat(buf, (i > 0) ? " '" : "'");
|
|
||||||
strncat(buf, action[i], MAX_LEN_PER_CMDLINE_ARG);
|
|
||||||
@@ -87,21 +89,25 @@ log_action(char ** action, size_t count)
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
-agent_action(Buffer *buf, char ** action, size_t count)
|
|
||||||
+agent_action(struct sshbuf **buf, char ** action, size_t count)
|
|
||||||
{
|
|
||||||
size_t i;
|
|
||||||
- pamsshagentauth_buffer_init(buf);
|
|
||||||
+ int r;
|
|
||||||
|
|
||||||
- pamsshagentauth_buffer_put_int(buf, count);
|
|
||||||
+ if ((*buf = sshbuf_new()) == NULL)
|
|
||||||
+ fatal("%s: sshbuf_new failed", __func__);
|
|
||||||
+ if ((r = sshbuf_put_u32(*buf, count)) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
|
|
||||||
for (i = 0; i < count; i++) {
|
|
||||||
- pamsshagentauth_buffer_put_cstring(buf, action[i]);
|
|
||||||
+ if ((r = sshbuf_put_cstring(*buf, action[i])) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-void
|
|
||||||
-pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user,
|
|
||||||
+static void
|
|
||||||
+pamsshagentauth_session_id2_gen(struct sshbuf ** session_id2, const char * user,
|
|
||||||
const char * ruser, const char * servicename)
|
|
||||||
{
|
|
||||||
u_char *cookie = NULL;
|
|
||||||
@@ -114,22 +120,23 @@ pamsshagentauth_session_id2_gen(Buffer *
|
|
||||||
char ** reported_argv = NULL;
|
|
||||||
size_t count = 0;
|
|
||||||
char * action_logbuf = NULL;
|
|
||||||
- Buffer action_agentbuf;
|
|
||||||
+ struct sshbuf *action_agentbuf = NULL;
|
|
||||||
uint8_t free_logbuf = 0;
|
|
||||||
char * retc;
|
|
||||||
int32_t reti;
|
|
||||||
+ int r;
|
|
||||||
|
|
||||||
- rnd = pamsshagentauth_arc4random();
|
|
||||||
+ rnd = arc4random();
|
|
||||||
cookie_len = ((uint8_t) rnd);
|
|
||||||
while (cookie_len < 16) {
|
|
||||||
cookie_len += 16; /* Add 16 bytes to the size to ensure that while the length is random, the length is always reasonable; ticket #18 */
|
|
||||||
}
|
|
||||||
|
|
||||||
- cookie = pamsshagentauth_xcalloc(1,cookie_len);
|
|
||||||
+ cookie = xcalloc(1, cookie_len);
|
|
||||||
|
|
||||||
for (i = 0; i < cookie_len; i++) {
|
|
||||||
if (i % 4 == 0) {
|
|
||||||
- rnd = pamsshagentauth_arc4random();
|
|
||||||
+ rnd = arc4random();
|
|
||||||
}
|
|
||||||
cookie[i] = (u_char) rnd;
|
|
||||||
rnd >>= 8;
|
|
||||||
@@ -144,7 +151,8 @@ pamsshagentauth_session_id2_gen(Buffer *
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
action_logbuf = "unknown on this platform";
|
|
||||||
- pamsshagentauth_buffer_init(&action_agentbuf); /* stays empty, means unavailable */
|
|
||||||
+ if ((action_agentbuf = sshbuf_new()) == NULL) /* stays empty, means unavailable */
|
|
||||||
+ fatal("%s: sshbuf_new failed", __func__);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -161,35 +169,39 @@ pamsshagentauth_session_id2_gen(Buffer *
|
|
||||||
retc = getcwd(pwd, sizeof(pwd) - 1);
|
|
||||||
time(&ts);
|
|
||||||
|
|
||||||
- pamsshagentauth_buffer_init(session_id2);
|
|
||||||
+ if ((*session_id2 = sshbuf_new()) == NULL)
|
|
||||||
+ fatal("%s: sshbuf_new failed", __func__);
|
|
||||||
|
|
||||||
- pamsshagentauth_buffer_put_int(session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1);
|
|
||||||
- /* pamsshagentauth_debug3("cookie: %s", pamsshagentauth_tohex(cookie, cookie_len)); */
|
|
||||||
- pamsshagentauth_buffer_put_string(session_id2, cookie, cookie_len);
|
|
||||||
- /* pamsshagentauth_debug3("user: %s", user); */
|
|
||||||
- pamsshagentauth_buffer_put_cstring(session_id2, user);
|
|
||||||
- /* pamsshagentauth_debug3("ruser: %s", ruser); */
|
|
||||||
- pamsshagentauth_buffer_put_cstring(session_id2, ruser);
|
|
||||||
- /* pamsshagentauth_debug3("servicename: %s", servicename); */
|
|
||||||
- pamsshagentauth_buffer_put_cstring(session_id2, servicename);
|
|
||||||
- /* pamsshagentauth_debug3("pwd: %s", pwd); */
|
|
||||||
- if(retc)
|
|
||||||
- pamsshagentauth_buffer_put_cstring(session_id2, pwd);
|
|
||||||
- else
|
|
||||||
- pamsshagentauth_buffer_put_cstring(session_id2, "");
|
|
||||||
- /* pamsshagentauth_debug3("action: %s", action_logbuf); */
|
|
||||||
- pamsshagentauth_buffer_put_string(session_id2, action_agentbuf.buf + action_agentbuf.offset, action_agentbuf.end - action_agentbuf.offset);
|
|
||||||
+ if ((r = sshbuf_put_u32(*session_id2, PAM_SSH_AGENT_AUTH_REQUESTv1)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_string(*session_id2, cookie, cookie_len)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_cstring(*session_id2, user)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_cstring(*session_id2, ruser)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_cstring(*session_id2, servicename)) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
+ if (retc) {
|
|
||||||
+ if ((r = sshbuf_put_cstring(*session_id2, pwd)) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
+ } else {
|
|
||||||
+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
+ }
|
|
||||||
+ if ((r = sshbuf_put_stringb(*session_id2, action_agentbuf)) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
if (free_logbuf) {
|
|
||||||
- pamsshagentauth_xfree(action_logbuf);
|
|
||||||
- pamsshagentauth_buffer_free(&action_agentbuf);
|
|
||||||
+ free(action_logbuf);
|
|
||||||
+ sshbuf_free(action_agentbuf);
|
|
||||||
+ }
|
|
||||||
+ /* debug3("hostname: %s", hostname); */
|
|
||||||
+ if (reti >= 0) {
|
|
||||||
+ if ((r = sshbuf_put_cstring(*session_id2, hostname)) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
+ } else {
|
|
||||||
+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
}
|
|
||||||
- /* pamsshagentauth_debug3("hostname: %s", hostname); */
|
|
||||||
- if(reti >= 0)
|
|
||||||
- pamsshagentauth_buffer_put_cstring(session_id2, hostname);
|
|
||||||
- else
|
|
||||||
- pamsshagentauth_buffer_put_cstring(session_id2, "");
|
|
||||||
- /* pamsshagentauth_debug3("ts: %ld", ts); */
|
|
||||||
- pamsshagentauth_buffer_put_int64(session_id2, (uint64_t) ts);
|
|
||||||
+ /* debug3("ts: %ld", ts); */
|
|
||||||
+ if ((r = sshbuf_put_u64(*session_id2, (uint64_t) ts)) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
|
|
||||||
free(cookie);
|
|
||||||
return;
|
|
||||||
@@ -278,7 +290,8 @@ ssh_get_authentication_connection_for_ui
|
|
||||||
|
|
||||||
auth = xmalloc(sizeof(*auth));
|
|
||||||
auth->fd = sock;
|
|
||||||
- buffer_init(&auth->identities);
|
|
||||||
+ if ((auth->identities = sshbuf_new()) == NULL)
|
|
||||||
+ fatal("%s: sshbuf_new failed", __func__);
|
|
||||||
auth->howmany = 0;
|
|
||||||
|
|
||||||
return auth;
|
|
||||||
@@ -287,9 +300,9 @@ ssh_get_authentication_connection_for_ui
|
|
||||||
int
|
|
||||||
pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
|
|
||||||
{
|
|
||||||
- Buffer session_id2 = { 0 };
|
|
||||||
+ struct sshbuf *session_id2 = NULL;
|
|
||||||
Identity *id;
|
|
||||||
- Key *key;
|
|
||||||
+ struct sshkey *key;
|
|
||||||
AuthenticationConnection *ac;
|
|
||||||
char *comment;
|
|
||||||
uint8_t retval = 0;
|
|
||||||
@@ -299,31 +312,30 @@ pamsshagentauth_find_authorized_keys(con
|
|
||||||
pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
|
|
||||||
|
|
||||||
if ((ac = ssh_get_authentication_connection_for_uid(uid))) {
|
|
||||||
- pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
|
||||||
+ verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
|
||||||
for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2))
|
|
||||||
{
|
|
||||||
if(key != NULL) {
|
|
||||||
- id = pamsshagentauth_xcalloc(1, sizeof(*id));
|
|
||||||
+ id = xcalloc(1, sizeof(*id));
|
|
||||||
id->key = key;
|
|
||||||
id->filename = comment;
|
|
||||||
id->ac = ac;
|
|
||||||
- if(userauth_pubkey_from_id(ruser, id, &session_id2)) {
|
|
||||||
+ if(userauth_pubkey_from_id(ruser, id, session_id2)) {
|
|
||||||
retval = 1;
|
|
||||||
}
|
|
||||||
- pamsshagentauth_xfree(id->filename);
|
|
||||||
- pamsshagentauth_key_free(id->key);
|
|
||||||
- pamsshagentauth_xfree(id);
|
|
||||||
+ free(id->filename);
|
|
||||||
+ key_free(id->key);
|
|
||||||
+ free(id);
|
|
||||||
if(retval == 1)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- pamsshagentauth_buffer_free(&session_id2);
|
|
||||||
+ sshbuf_free(session_id2);
|
|
||||||
ssh_close_authentication_connection(ac);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
- pamsshagentauth_verbose("No ssh-agent could be contacted");
|
|
||||||
+ verbose("No ssh-agent could be contacted");
|
|
||||||
}
|
|
||||||
- /* pamsshagentauth_xfree(session_id2); */
|
|
||||||
EVP_cleanup();
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c.psaa-compat 2020-09-23 10:52:16.423001461 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_ssh_agent_auth.c 2020-09-23 10:53:10.631727657 +0200
|
|
||||||
@@ -106,7 +106,7 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
|
||||||
* a patch 8-)
|
|
||||||
*/
|
|
||||||
#if ! HAVE___PROGNAME || HAVE_BUNDLE
|
|
||||||
- __progname = pamsshagentauth_xstrdup(servicename);
|
|
||||||
+ __progname = xstrdup(servicename);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for(i = argc, argv_ptr = (char **) argv; i > 0; ++argv_ptr, i--) {
|
|
||||||
@@ -132,11 +132,11 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
- pamsshagentauth_log_init(__progname, log_lvl, facility, getenv("PAM_SSH_AGENT_AUTH_DEBUG") ? 1 : 0);
|
|
||||||
+ log_init(__progname, log_lvl, facility, getenv("PAM_SSH_AGENT_AUTH_DEBUG") ? 1 : 0);
|
|
||||||
pam_get_item(pamh, PAM_USER, (void *) &user);
|
|
||||||
pam_get_item(pamh, PAM_RUSER, (void *) &ruser_ptr);
|
|
||||||
|
|
||||||
- pamsshagentauth_verbose("Beginning pam_ssh_agent_auth for user %s", user);
|
|
||||||
+ verbose("Beginning pam_ssh_agent_auth for user %s", user);
|
|
||||||
|
|
||||||
if(ruser_ptr) {
|
|
||||||
strncpy(ruser, ruser_ptr, sizeof(ruser) - 1);
|
|
||||||
@@ -151,12 +151,12 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
|
||||||
#ifdef ENABLE_SUDO_HACK
|
|
||||||
if( (strlen(sudo_service_name) > 0) && strncasecmp(servicename, sudo_service_name, sizeof(sudo_service_name) - 1) == 0 && getenv("SUDO_USER") ) {
|
|
||||||
strncpy(ruser, getenv("SUDO_USER"), sizeof(ruser) - 1 );
|
|
||||||
- pamsshagentauth_verbose( "Using environment variable SUDO_USER (%s)", ruser );
|
|
||||||
+ verbose( "Using environment variable SUDO_USER (%s)", ruser );
|
|
||||||
} else
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if( ! getpwuid(getuid()) ) {
|
|
||||||
- pamsshagentauth_verbose("Unable to getpwuid(getuid())");
|
|
||||||
+ verbose("Unable to getpwuid(getuid())");
|
|
||||||
goto cleanexit;
|
|
||||||
}
|
|
||||||
strncpy(ruser, getpwuid(getuid())->pw_name, sizeof(ruser) - 1);
|
|
||||||
@@ -165,11 +165,11 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
|
||||||
|
|
||||||
/* Might as well explicitely confirm the user exists here */
|
|
||||||
if(! getpwnam(ruser) ) {
|
|
||||||
- pamsshagentauth_verbose("getpwnam(%s) failed, bailing out", ruser);
|
|
||||||
+ verbose("getpwnam(%s) failed, bailing out", ruser);
|
|
||||||
goto cleanexit;
|
|
||||||
}
|
|
||||||
if( ! getpwnam(user) ) {
|
|
||||||
- pamsshagentauth_verbose("getpwnam(%s) failed, bailing out", user);
|
|
||||||
+ verbose("getpwnam(%s) failed, bailing out", user);
|
|
||||||
goto cleanexit;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -179,8 +179,8 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
|
||||||
*/
|
|
||||||
parse_authorized_key_file(user, authorized_keys_file_input);
|
|
||||||
} else {
|
|
||||||
- pamsshagentauth_verbose("Using default file=/etc/security/authorized_keys");
|
|
||||||
- authorized_keys_file = pamsshagentauth_xstrdup("/etc/security/authorized_keys");
|
|
||||||
+ verbose("Using default file=/etc/security/authorized_keys");
|
|
||||||
+ authorized_keys_file = xstrdup("/etc/security/authorized_keys");
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@@ -189,7 +189,7 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(user && strlen(ruser) > 0) {
|
|
||||||
- pamsshagentauth_verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
|
||||||
+ verbose("Attempting authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Attempt to read data from the sshd if we're being called as an auth agent.
|
|
||||||
@@ -197,10 +197,10 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
|
||||||
const char* ssh_user_auth = pam_getenv(pamh, "SSH_AUTH_INFO_0");
|
|
||||||
int sshd_service = strncasecmp(servicename, sshd_service_name, sizeof(sshd_service_name) - 1);
|
|
||||||
if (sshd_service == 0 && ssh_user_auth != NULL) {
|
|
||||||
- pamsshagentauth_verbose("Got SSH_AUTH_INFO_0: `%.20s...'", ssh_user_auth);
|
|
||||||
+ verbose("Got SSH_AUTH_INFO_0: `%.20s...'", ssh_user_auth);
|
|
||||||
if (userauth_pubkey_from_pam(ruser, ssh_user_auth) > 0) {
|
|
||||||
retval = PAM_SUCCESS;
|
|
||||||
- pamsshagentauth_logit("Authenticated (sshd): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
|
||||||
+ logit("Authenticated (sshd): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
|
||||||
goto cleanexit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -208,13 +208,13 @@ pam_sm_authenticate(pam_handle_t * pamh,
|
|
||||||
* this pw_uid is used to validate the SSH_AUTH_SOCK, and so must be the uid of the ruser invoking the program, not the target-user
|
|
||||||
*/
|
|
||||||
if(pamsshagentauth_find_authorized_keys(user, ruser, servicename)) { /* getpwnam(ruser)->pw_uid)) { */
|
|
||||||
- pamsshagentauth_logit("Authenticated (agent): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
|
||||||
+ logit("Authenticated (agent): `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
|
||||||
retval = PAM_SUCCESS;
|
|
||||||
} else {
|
|
||||||
- pamsshagentauth_logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
|
||||||
+ logit("Failed Authentication: `%s' as `%s' using %s", ruser, user, authorized_keys_file);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
- pamsshagentauth_logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" );
|
|
||||||
+ logit("No %s specified, cannot continue with this form of authentication", (user) ? "ruser" : "user" );
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanexit:
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.c 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -66,8 +66,8 @@
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "match.h"
|
|
||||||
#include "log.h"
|
|
||||||
-#include "buffer.h"
|
|
||||||
-#include "key.h"
|
|
||||||
+#include "sshbuf.h"
|
|
||||||
+#include "sshkey.h"
|
|
||||||
#include "misc.h"
|
|
||||||
|
|
||||||
#include "xmalloc.h"
|
|
||||||
@@ -77,7 +77,6 @@
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "secure_filename.h"
|
|
||||||
|
|
||||||
-#include "identity.h"
|
|
||||||
#include "pam_user_key_allowed2.h"
|
|
||||||
|
|
||||||
extern char *authorized_keys_file;
|
|
||||||
@@ -117,12 +116,12 @@ parse_authorized_key_file(const char *us
|
|
||||||
} else {
|
|
||||||
slash_ptr = strchr(auth_keys_file_buf, '/');
|
|
||||||
if(!slash_ptr)
|
|
||||||
- pamsshagentauth_fatal
|
|
||||||
+ fatal
|
|
||||||
("cannot expand tilde in path without a `/'");
|
|
||||||
|
|
||||||
owner_uname_len = slash_ptr - auth_keys_file_buf - 1;
|
|
||||||
if(owner_uname_len > (sizeof(owner_uname) - 1))
|
|
||||||
- pamsshagentauth_fatal("Username too long");
|
|
||||||
+ fatal("Username too long");
|
|
||||||
|
|
||||||
strncat(owner_uname, auth_keys_file_buf + 1, owner_uname_len);
|
|
||||||
if(!authorized_keys_file_allowed_owner_uid)
|
|
||||||
@@ -130,11 +129,11 @@ parse_authorized_key_file(const char *us
|
|
||||||
getpwnam(owner_uname)->pw_uid;
|
|
||||||
}
|
|
||||||
authorized_keys_file =
|
|
||||||
- pamsshagentauth_tilde_expand_filename(auth_keys_file_buf,
|
|
||||||
+ tilde_expand_filename(auth_keys_file_buf,
|
|
||||||
authorized_keys_file_allowed_owner_uid);
|
|
||||||
strncpy(auth_keys_file_buf, authorized_keys_file,
|
|
||||||
sizeof(auth_keys_file_buf) - 1);
|
|
||||||
- pamsshagentauth_xfree(authorized_keys_file) /* when we
|
|
||||||
+ free(authorized_keys_file) /* when we
|
|
||||||
percent_expand
|
|
||||||
later, we'd step
|
|
||||||
on this, so free
|
|
||||||
@@ -150,13 +149,13 @@ parse_authorized_key_file(const char *us
|
|
||||||
strncat(hostname, fqdn, strcspn(fqdn, "."));
|
|
||||||
#endif
|
|
||||||
authorized_keys_file =
|
|
||||||
- pamsshagentauth_percent_expand(auth_keys_file_buf, "h",
|
|
||||||
+ percent_expand(auth_keys_file_buf, "h",
|
|
||||||
getpwnam(user)->pw_dir, "H", hostname,
|
|
||||||
"f", fqdn, "u", user, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
-pam_user_key_allowed(const char *ruser, Key * key)
|
|
||||||
+pam_user_key_allowed(const char *ruser, struct sshkey * key)
|
|
||||||
{
|
|
||||||
return
|
|
||||||
pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid),
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_authorized_keys.h 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -32,7 +32,7 @@
|
|
||||||
#define _PAM_USER_KEY_ALLOWED_H
|
|
||||||
|
|
||||||
#include "identity.h"
|
|
||||||
-int pam_user_key_allowed(const char *, Key *);
|
|
||||||
+int pam_user_key_allowed(const char *, struct sshkey *);
|
|
||||||
void parse_authorized_key_file(const char *, const char *);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.c 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -45,44 +45,46 @@
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "ssh.h"
|
|
||||||
#include "ssh2.h"
|
|
||||||
-#include "buffer.h"
|
|
||||||
+#include "sshbuf.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "compat.h"
|
|
||||||
-#include "key.h"
|
|
||||||
+#include "digest.h"
|
|
||||||
+#include "sshkey.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "secure_filename.h"
|
|
||||||
#include "uidswap.h"
|
|
||||||
-
|
|
||||||
-#include "identity.h"
|
|
||||||
+#include <unistd.h>
|
|
||||||
|
|
||||||
/* return 1 if user allows given key */
|
|
||||||
/* Modified slightly from original found in auth2-pubkey.c */
|
|
||||||
static int
|
|
||||||
-pamsshagentauth_check_authkeys_file(FILE * f, char *file, Key * key)
|
|
||||||
+pamsshagentauth_check_authkeys_file(FILE * f, char *file, struct sshkey * key)
|
|
||||||
{
|
|
||||||
- char line[SSH_MAX_PUBKEY_BYTES];
|
|
||||||
+ char *line = NULL;
|
|
||||||
int found_key = 0;
|
|
||||||
u_long linenum = 0;
|
|
||||||
- Key *found;
|
|
||||||
+ struct sshkey *found;
|
|
||||||
char *fp;
|
|
||||||
+ size_t linesize = 0;
|
|
||||||
|
|
||||||
found_key = 0;
|
|
||||||
- found = pamsshagentauth_key_new(key->type);
|
|
||||||
+ found = sshkey_new(key->type);
|
|
||||||
|
|
||||||
- while(read_keyfile_line(f, file, line, sizeof(line), &linenum) != -1) {
|
|
||||||
+ while ((getline(&line, &linesize, f)) != -1) {
|
|
||||||
char *cp = NULL; /* *key_options = NULL; */
|
|
||||||
|
|
||||||
+ linenum++;
|
|
||||||
/* Skip leading whitespace, empty and comment lines. */
|
|
||||||
for(cp = line; *cp == ' ' || *cp == '\t'; cp++);
|
|
||||||
if(!*cp || *cp == '\n' || *cp == '#')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
- if(pamsshagentauth_key_read(found, &cp) != 1) {
|
|
||||||
+ if (sshkey_read(found, &cp) != 0) {
|
|
||||||
/* no key? check if there are options for this key */
|
|
||||||
int quoted = 0;
|
|
||||||
|
|
||||||
- pamsshagentauth_verbose("user_key_allowed: check options: '%s'", cp);
|
|
||||||
+ verbose("user_key_allowed: check options: '%s'", cp);
|
|
||||||
/* key_options = cp; */
|
|
||||||
for(; *cp && (quoted || (*cp != ' ' && *cp != '\t')); cp++) {
|
|
||||||
if(*cp == '\\' && cp[1] == '"')
|
|
||||||
@@ -92,26 +94,27 @@ pamsshagentauth_check_authkeys_file(FILE
|
|
||||||
}
|
|
||||||
/* Skip remaining whitespace. */
|
|
||||||
for(; *cp == ' ' || *cp == '\t'; cp++);
|
|
||||||
- if(pamsshagentauth_key_read(found, &cp) != 1) {
|
|
||||||
- pamsshagentauth_verbose("user_key_allowed: advance: '%s'", cp);
|
|
||||||
+ if(sshkey_read(found, &cp) != 0) {
|
|
||||||
+ verbose("user_key_allowed: advance: '%s'", cp);
|
|
||||||
/* still no key? advance to next line */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- if(pamsshagentauth_key_equal(found, key)) {
|
|
||||||
+ if(sshkey_equal(found, key)) {
|
|
||||||
found_key = 1;
|
|
||||||
- pamsshagentauth_logit("matching key found: file/command %s, line %lu", file,
|
|
||||||
+ logit("matching key found: file/command %s, line %lu", file,
|
|
||||||
linenum);
|
|
||||||
- fp = pamsshagentauth_key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);
|
|
||||||
- pamsshagentauth_logit("Found matching %s key: %s",
|
|
||||||
- pamsshagentauth_key_type(found), fp);
|
|
||||||
- pamsshagentauth_xfree(fp);
|
|
||||||
+ fp = sshkey_fingerprint(found, SSH_DIGEST_SHA256, SSH_FP_BASE64);
|
|
||||||
+ logit("Found matching %s key: %s",
|
|
||||||
+ sshkey_type(found), fp);
|
|
||||||
+ free(fp);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
- pamsshagentauth_key_free(found);
|
|
||||||
+ free(line);
|
|
||||||
+ sshkey_free(found);
|
|
||||||
if(!found_key)
|
|
||||||
- pamsshagentauth_verbose("key not found");
|
|
||||||
+ verbose("key not found");
|
|
||||||
return found_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -120,19 +123,19 @@ pamsshagentauth_check_authkeys_file(FILE
|
|
||||||
* returns 1 if the key is allowed or 0 otherwise.
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
-pamsshagentauth_user_key_allowed2(struct passwd *pw, Key * key, char *file)
|
|
||||||
+pamsshagentauth_user_key_allowed2(struct passwd *pw, struct sshkey * key, char *file)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
int found_key = 0;
|
|
||||||
struct stat st;
|
|
||||||
- char buf[SSH_MAX_PUBKEY_BYTES];
|
|
||||||
+ char buf[256];
|
|
||||||
|
|
||||||
/* Temporarily use the user's uid. */
|
|
||||||
- pamsshagentauth_verbose("trying public key file %s", file);
|
|
||||||
+ verbose("trying public key file %s", file);
|
|
||||||
|
|
||||||
/* Fail not so quietly if file does not exist */
|
|
||||||
if(stat(file, &st) < 0) {
|
|
||||||
- pamsshagentauth_verbose("File not found: %s", file);
|
|
||||||
+ verbose("File not found: %s", file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -144,7 +147,7 @@ pamsshagentauth_user_key_allowed2(struct
|
|
||||||
|
|
||||||
if(pamsshagentauth_secure_filename(f, file, pw, buf, sizeof(buf)) != 0) {
|
|
||||||
fclose(f);
|
|
||||||
- pamsshagentauth_logit("Authentication refused: %s", buf);
|
|
||||||
+ logit("Authentication refused: %s", buf);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -160,7 +163,7 @@ pamsshagentauth_user_key_allowed2(struct
|
|
||||||
int
|
|
||||||
pamsshagentauth_user_key_command_allowed2(char *authorized_keys_command,
|
|
||||||
char *authorized_keys_command_user,
|
|
||||||
- struct passwd *user_pw, Key * key)
|
|
||||||
+ struct passwd *user_pw, struct sshkey * key)
|
|
||||||
{
|
|
||||||
FILE *f;
|
|
||||||
int ok, found_key = 0;
|
|
||||||
@@ -187,44 +190,44 @@ pamsshagentauth_user_key_command_allowed
|
|
||||||
else {
|
|
||||||
pw = getpwnam(authorized_keys_command_user);
|
|
||||||
if(pw == NULL) {
|
|
||||||
- pamsshagentauth_logerror("authorized_keys_command_user \"%s\" not found: %s",
|
|
||||||
+ error("authorized_keys_command_user \"%s\" not found: %s",
|
|
||||||
authorized_keys_command_user, strerror(errno));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- pamsshagentauth_temporarily_use_uid(pw);
|
|
||||||
+ temporarily_use_uid(pw);
|
|
||||||
|
|
||||||
if(stat(authorized_keys_command, &st) < 0) {
|
|
||||||
- pamsshagentauth_logerror
|
|
||||||
+ error
|
|
||||||
("Could not stat AuthorizedKeysCommand \"%s\": %s",
|
|
||||||
authorized_keys_command, strerror(errno));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if(pamsshagentauth_auth_secure_path
|
|
||||||
(authorized_keys_command, &st, NULL, 0, errmsg, sizeof(errmsg)) != 0) {
|
|
||||||
- pamsshagentauth_logerror("Unsafe AuthorizedKeysCommand: %s", errmsg);
|
|
||||||
+ error("Unsafe AuthorizedKeysCommand: %s", errmsg);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* open the pipe and read the keys */
|
|
||||||
if(pipe(p) != 0) {
|
|
||||||
- pamsshagentauth_logerror("%s: pipe: %s", __func__, strerror(errno));
|
|
||||||
+ error("%s: pipe: %s", __func__, strerror(errno));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
- pamsshagentauth_debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"",
|
|
||||||
+ debug("Running AuthorizedKeysCommand: \"%s\" as \"%s\" with argument: \"%s\"",
|
|
||||||
authorized_keys_command, pw->pw_name, username);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Don't want to call this in the child, where it can fatal() and
|
|
||||||
* run cleanup_exit() code.
|
|
||||||
*/
|
|
||||||
- pamsshagentauth_restore_uid();
|
|
||||||
+ restore_uid();
|
|
||||||
|
|
||||||
switch ((pid = fork())) {
|
|
||||||
case -1: /* error */
|
|
||||||
- pamsshagentauth_logerror("%s: fork: %s", __func__, strerror(errno));
|
|
||||||
+ error("%s: fork: %s", __func__, strerror(errno));
|
|
||||||
close(p[0]);
|
|
||||||
close(p[1]);
|
|
||||||
return 0;
|
|
||||||
@@ -234,13 +237,13 @@ pamsshagentauth_user_key_command_allowed
|
|
||||||
|
|
||||||
/* do this before the setresuid so thta they can be logged */
|
|
||||||
if((devnull = open(_PATH_DEVNULL, O_RDWR)) == -1) {
|
|
||||||
- pamsshagentauth_logerror("%s: open %s: %s", __func__, _PATH_DEVNULL,
|
|
||||||
+ error("%s: open %s: %s", __func__, _PATH_DEVNULL,
|
|
||||||
strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
if(dup2(devnull, STDIN_FILENO) == -1 || dup2(p[1], STDOUT_FILENO) == -1
|
|
||||||
|| dup2(devnull, STDERR_FILENO) == -1) {
|
|
||||||
- pamsshagentauth_logerror("%s: dup2: %s", __func__, strerror(errno));
|
|
||||||
+ error("%s: dup2: %s", __func__, strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
#if defined(HAVE_SETRESGID) && !defined(BROKEN_SETRESGID)
|
|
||||||
@@ -248,7 +251,7 @@ pamsshagentauth_user_key_command_allowed
|
|
||||||
#else
|
|
||||||
if (setgid(pw->pw_gid) != 0 || setegid(pw->pw_gid) != 0) {
|
|
||||||
#endif
|
|
||||||
- pamsshagentauth_logerror("setresgid %u: %s", (u_int) pw->pw_gid,
|
|
||||||
+ error("setresgid %u: %s", (u_int) pw->pw_gid,
|
|
||||||
strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
@@ -258,7 +261,7 @@ pamsshagentauth_user_key_command_allowed
|
|
||||||
#else
|
|
||||||
if (setuid(pw->pw_uid) != 0 || seteuid(pw->pw_uid) != 0) {
|
|
||||||
#endif
|
|
||||||
- pamsshagentauth_logerror("setresuid %u: %s", (u_int) pw->pw_uid,
|
|
||||||
+ error("setresuid %u: %s", (u_int) pw->pw_uid,
|
|
||||||
strerror(errno));
|
|
||||||
_exit(1);
|
|
||||||
}
|
|
||||||
@@ -270,18 +273,18 @@ pamsshagentauth_user_key_command_allowed
|
|
||||||
|
|
||||||
/* pretty sure this will barf because we are now suid, but since we
|
|
||||||
should't reach this anyway, I'll leave it here */
|
|
||||||
- pamsshagentauth_logerror("AuthorizedKeysCommand %s exec failed: %s",
|
|
||||||
+ error("AuthorizedKeysCommand %s exec failed: %s",
|
|
||||||
authorized_keys_command, strerror(errno));
|
|
||||||
_exit(127);
|
|
||||||
default: /* parent */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
- pamsshagentauth_temporarily_use_uid(pw);
|
|
||||||
+ temporarily_use_uid(pw);
|
|
||||||
|
|
||||||
close(p[1]);
|
|
||||||
if((f = fdopen(p[0], "r")) == NULL) {
|
|
||||||
- pamsshagentauth_logerror("%s: fdopen: %s", __func__, strerror(errno));
|
|
||||||
+ error("%s: fdopen: %s", __func__, strerror(errno));
|
|
||||||
close(p[0]);
|
|
||||||
/* Don't leave zombie child */
|
|
||||||
while(waitpid(pid, NULL, 0) == -1 && errno == EINTR);
|
|
||||||
@@ -292,22 +295,22 @@ pamsshagentauth_user_key_command_allowed
|
|
||||||
|
|
||||||
while(waitpid(pid, &status, 0) == -1) {
|
|
||||||
if(errno != EINTR) {
|
|
||||||
- pamsshagentauth_logerror("%s: waitpid: %s", __func__,
|
|
||||||
+ error("%s: waitpid: %s", __func__,
|
|
||||||
strerror(errno));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(WIFSIGNALED(status)) {
|
|
||||||
- pamsshagentauth_logerror("AuthorizedKeysCommand %s exited on signal %d",
|
|
||||||
+ error("AuthorizedKeysCommand %s exited on signal %d",
|
|
||||||
authorized_keys_command, WTERMSIG(status));
|
|
||||||
goto out;
|
|
||||||
} else if(WEXITSTATUS(status) != 0) {
|
|
||||||
- pamsshagentauth_logerror("AuthorizedKeysCommand %s returned status %d",
|
|
||||||
+ error("AuthorizedKeysCommand %s returned status %d",
|
|
||||||
authorized_keys_command, WEXITSTATUS(status));
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
found_key = ok;
|
|
||||||
out:
|
|
||||||
- pamsshagentauth_restore_uid();
|
|
||||||
+ restore_uid();
|
|
||||||
return found_key;
|
|
||||||
}
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/pam_user_key_allowed2.h 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -32,7 +32,7 @@
|
|
||||||
#define _PAM_USER_KEY_ALLOWED_H
|
|
||||||
|
|
||||||
#include "identity.h"
|
|
||||||
-int pamsshagentauth_user_key_allowed2(struct passwd *, Key *, char *);
|
|
||||||
-int pamsshagentauth_user_key_command_allowed2(char *, char *, struct passwd *, Key *);
|
|
||||||
+int pamsshagentauth_user_key_allowed2(struct passwd *, struct sshkey *, char *);
|
|
||||||
+int pamsshagentauth_user_key_command_allowed2(char *, char *, struct passwd *, struct sshkey *);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/secure_filename.c 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -53,8 +53,8 @@
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "match.h"
|
|
||||||
#include "log.h"
|
|
||||||
-#include "buffer.h"
|
|
||||||
-#include "key.h"
|
|
||||||
+#include "sshbuf.h"
|
|
||||||
+#include "sshkey.h"
|
|
||||||
#include "misc.h"
|
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ pamsshagentauth_auth_secure_path(const c
|
|
||||||
int comparehome = 0;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
- pamsshagentauth_verbose("auth_secure_filename: checking for uid: %u", uid);
|
|
||||||
+ verbose("auth_secure_filename: checking for uid: %u", uid);
|
|
||||||
|
|
||||||
if (realpath(name, buf) == NULL) {
|
|
||||||
snprintf(err, errlen, "realpath %s failed: %s", name,
|
|
||||||
@@ -115,9 +115,9 @@ pamsshagentauth_auth_secure_path(const c
|
|
||||||
snprintf(err, errlen, "dirname() failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
- pamsshagentauth_strlcpy(buf, cp, sizeof(buf));
|
|
||||||
+ strlcpy(buf, cp, sizeof(buf));
|
|
||||||
|
|
||||||
- pamsshagentauth_verbose("secure_filename: checking '%s'", buf);
|
|
||||||
+ verbose("secure_filename: checking '%s'", buf);
|
|
||||||
if (stat(buf, &st) < 0 ||
|
|
||||||
(st.st_uid != 0 && st.st_uid != uid) ||
|
|
||||||
(st.st_mode & 022) != 0) {
|
|
||||||
@@ -128,7 +128,7 @@ pamsshagentauth_auth_secure_path(const c
|
|
||||||
|
|
||||||
/* If are passed the homedir then we can stop */
|
|
||||||
if (comparehome && strcmp(homedir, buf) == 0) {
|
|
||||||
- pamsshagentauth_verbose("secure_filename: terminating check at '%s'",
|
|
||||||
+ verbose("secure_filename: terminating check at '%s'",
|
|
||||||
buf);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -37,10 +37,11 @@
|
|
||||||
#include "xmalloc.h"
|
|
||||||
#include "ssh.h"
|
|
||||||
#include "ssh2.h"
|
|
||||||
-#include "buffer.h"
|
|
||||||
+#include "sshbuf.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "compat.h"
|
|
||||||
-#include "key.h"
|
|
||||||
+#include "sshkey.h"
|
|
||||||
+#include "ssherr.h"
|
|
||||||
#include "pathnames.h"
|
|
||||||
#include "misc.h"
|
|
||||||
#include "secure_filename.h"
|
|
||||||
@@ -48,54 +49,59 @@
|
|
||||||
#include "identity.h"
|
|
||||||
#include "pam_user_authorized_keys.h"
|
|
||||||
|
|
||||||
+#define SSH2_MSG_USERAUTH_TRUST_REQUEST 54
|
|
||||||
+
|
|
||||||
/* extern u_char *session_id2;
|
|
||||||
extern uint8_t session_id_len;
|
|
||||||
*/
|
|
||||||
|
|
||||||
int
|
|
||||||
-userauth_pubkey_from_id(const char *ruser, Identity * id, Buffer * session_id2)
|
|
||||||
+userauth_pubkey_from_id(const char *ruser, Identity * id, struct sshbuf * session_id2)
|
|
||||||
{
|
|
||||||
- Buffer b = { 0 };
|
|
||||||
+ struct sshbuf *b = NULL;
|
|
||||||
char *pkalg = NULL;
|
|
||||||
u_char *pkblob = NULL, *sig = NULL;
|
|
||||||
- u_int blen = 0, slen = 0;
|
|
||||||
- int authenticated = 0;
|
|
||||||
+ size_t blen = 0, slen = 0;
|
|
||||||
+ int r, authenticated = 0;
|
|
||||||
|
|
||||||
- pkalg = (char *) key_ssh_name(id->key);
|
|
||||||
+ pkalg = (char *) sshkey_ssh_name(id->key);
|
|
||||||
|
|
||||||
/* first test if this key is even allowed */
|
|
||||||
if(! pam_user_key_allowed(ruser, id->key))
|
|
||||||
- goto user_auth_clean_exit;
|
|
||||||
+ goto user_auth_clean_exit_without_buffer;
|
|
||||||
|
|
||||||
- if(pamsshagentauth_key_to_blob(id->key, &pkblob, &blen) == 0)
|
|
||||||
- goto user_auth_clean_exit;
|
|
||||||
+ if(sshkey_to_blob(id->key, &pkblob, &blen) != 0)
|
|
||||||
+ goto user_auth_clean_exit_without_buffer;
|
|
||||||
|
|
||||||
/* construct packet to sign and test */
|
|
||||||
- pamsshagentauth_buffer_init(&b);
|
|
||||||
+ if ((b = sshbuf_new()) == NULL)
|
|
||||||
+ fatal("%s: sshbuf_new failed", __func__);
|
|
||||||
|
|
||||||
- pamsshagentauth_buffer_put_string(&b, session_id2->buf + session_id2->offset, session_id2->end - session_id2->offset);
|
|
||||||
- pamsshagentauth_buffer_put_char(&b, SSH2_MSG_USERAUTH_TRUST_REQUEST);
|
|
||||||
- pamsshagentauth_buffer_put_cstring(&b, ruser);
|
|
||||||
- pamsshagentauth_buffer_put_cstring(&b, "pam_ssh_agent_auth");
|
|
||||||
- pamsshagentauth_buffer_put_cstring(&b, "publickey");
|
|
||||||
- pamsshagentauth_buffer_put_char(&b, 1);
|
|
||||||
- pamsshagentauth_buffer_put_cstring(&b, pkalg);
|
|
||||||
- pamsshagentauth_buffer_put_string(&b, pkblob, blen);
|
|
||||||
+ if ((r = sshbuf_put_string(b, sshbuf_ptr(session_id2), sshbuf_len(session_id2))) != 0 ||
|
|
||||||
+ (r = sshbuf_put_u8(b, SSH2_MSG_USERAUTH_TRUST_REQUEST)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_cstring(b, ruser)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_cstring(b, "pam_ssh_agent_auth")) != 0 ||
|
|
||||||
+ (r = sshbuf_put_cstring(b, "publickey")) != 0 ||
|
|
||||||
+ (r = sshbuf_put_u8(b, 1)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_cstring(b, pkalg)) != 0 ||
|
|
||||||
+ (r = sshbuf_put_string(b, pkblob, blen)) != 0)
|
|
||||||
+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
|
|
||||||
- if(ssh_agent_sign(id->ac, id->key, &sig, &slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) != 0)
|
|
||||||
+ if (ssh_agent_sign(id->ac, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b)) != 0)
|
|
||||||
goto user_auth_clean_exit;
|
|
||||||
|
|
||||||
/* test for correct signature */
|
|
||||||
- if(pamsshagentauth_key_verify(id->key, sig, slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) == 1)
|
|
||||||
+ if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0, NULL) == 0)
|
|
||||||
authenticated = 1;
|
|
||||||
|
|
||||||
user_auth_clean_exit:
|
|
||||||
/* if(&b != NULL) */
|
|
||||||
- pamsshagentauth_buffer_free(&b);
|
|
||||||
+ sshbuf_free(b);
|
|
||||||
+ user_auth_clean_exit_without_buffer:
|
|
||||||
if(sig != NULL)
|
|
||||||
- pamsshagentauth_xfree(sig);
|
|
||||||
+ free(sig);
|
|
||||||
if(pkblob != NULL)
|
|
||||||
- pamsshagentauth_xfree(pkblob);
|
|
||||||
+ free(pkblob);
|
|
||||||
CRYPTO_cleanup_all_ex_data();
|
|
||||||
return authenticated;
|
|
||||||
}
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.h 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -31,7 +31,7 @@
|
|
||||||
#ifndef _USERAUTH_PUBKEY_FROM_ID_H
|
|
||||||
#define _USERAUTH_PUBKEY_FROM_ID_H
|
|
||||||
|
|
||||||
-#include <identity.h>
|
|
||||||
-int userauth_pubkey_from_id(const char *, Identity *, Buffer *);
|
|
||||||
+#include "identity.h"
|
|
||||||
+int userauth_pubkey_from_id(const char *, Identity *, struct sshbuf *);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c.psaa-compat openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c.psaa-compat 2019-07-08 18:36:13.000000000 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/uuencode.c 2020-09-23 10:52:16.424001475 +0200
|
|
||||||
@@ -56,7 +56,7 @@ pamsshagentauth_uudecode(const char *src
|
|
||||||
/* and remove trailing whitespace because __b64_pton needs this */
|
|
||||||
*p = '\0';
|
|
||||||
len = pamsshagentauth___b64_pton(encoded, target, targsize);
|
|
||||||
- pamsshagentauth_xfree(encoded);
|
|
||||||
+ xfree(encoded);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ pamsshagentauth_dump_base64(FILE *fp, co
|
|
||||||
fprintf(fp, "dump_base64: len > 65536\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
- buf = pamsshagentauth_xmalloc(2*len);
|
|
||||||
+ buf = malloc(2*len);
|
|
||||||
n = pamsshagentauth_uuencode(data, len, buf, 2*len);
|
|
||||||
for (i = 0; i < n; i++) {
|
|
||||||
fprintf(fp, "%c", buf[i]);
|
|
||||||
@@ -79,5 +79,5 @@ pamsshagentauth_dump_base64(FILE *fp, co
|
|
||||||
}
|
|
||||||
if (i % 70 != 69)
|
|
||||||
fprintf(fp, "\n");
|
|
||||||
- pamsshagentauth_xfree(buf);
|
|
||||||
+ free(buf);
|
|
||||||
}
|
|
||||||
--- openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_pam.c.compat 2020-09-23 11:32:30.783695267 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_pam.c 2020-09-23 11:33:21.383389036 +0200
|
|
||||||
@@ -33,7 +33,8 @@
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "defines.h"
|
|
||||||
-#include "key.h"
|
|
||||||
+#include <includes.h>
|
|
||||||
+#include "sshkey.h"
|
|
||||||
#include "log.h"
|
|
||||||
|
|
||||||
#include "pam_user_authorized_keys.h"
|
|
||||||
@@ -42,28 +42,28 @@
|
|
||||||
int authenticated = 0;
|
|
||||||
const char method[] = "publickey ";
|
|
||||||
|
|
||||||
- char* ai = pamsshagentauth_xstrdup(ssh_auth_info);
|
|
||||||
+ char* ai = xstrdup(ssh_auth_info);
|
|
||||||
char* saveptr;
|
|
||||||
|
|
||||||
char* auth_line = strtok_r(ai, "\n", &saveptr);
|
|
||||||
while (auth_line != NULL) {
|
|
||||||
if (strncmp(auth_line, method, sizeof(method) - 1) == 0) {
|
|
||||||
char* key_str = auth_line + sizeof(method) - 1;
|
|
||||||
- Key* key = pamsshagentauth_key_new(KEY_UNSPEC);
|
|
||||||
+ struct sshkey* key = sshkey_new(KEY_UNSPEC);
|
|
||||||
if (key == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
- int r = pamsshagentauth_key_read(key, &key_str);
|
|
||||||
+ int r = sshkey_read(key, &key_str);
|
|
||||||
if (r == 1) {
|
|
||||||
if (pam_user_key_allowed(ruser, key)) {
|
|
||||||
authenticated = 1;
|
|
||||||
- pamsshagentauth_key_free(key);
|
|
||||||
+ sshkey_free(key);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
- pamsshagentauth_verbose("Failed to create key for %s: %d", auth_line, r);
|
|
||||||
+ verbose("Failed to create key for %s: %d", auth_line, r);
|
|
||||||
}
|
|
||||||
- pamsshagentauth_key_free(key);
|
|
||||||
+ sshkey_free(key);
|
|
||||||
}
|
|
||||||
auth_line = strtok_r(NULL, "\n", &saveptr);
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
diff --git a/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c b/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c
|
|
||||||
--- a/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c
|
|
||||||
+++ b/pam_ssh_agent_auth-0.10.2/pam_user_authorized_keys.c
|
|
||||||
@@ -158,11 +158,12 @@ parse_authorized_key_file(const char *user,
|
|
||||||
int
|
|
||||||
pam_user_key_allowed(const char *ruser, struct sshkey * key)
|
|
||||||
{
|
|
||||||
+ struct passwd *pw;
|
|
||||||
return
|
|
||||||
- pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid),
|
|
||||||
- key, authorized_keys_file)
|
|
||||||
- || pamsshagentauth_user_key_allowed2(getpwuid(0), key,
|
|
||||||
- authorized_keys_file)
|
|
||||||
+ ( (pw = getpwuid(authorized_keys_file_allowed_owner_uid)) &&
|
|
||||||
+ pamsshagentauth_user_key_allowed2(pw, key, authorized_keys_file))
|
|
||||||
+ || ((pw = getpwuid(0)) &&
|
|
||||||
+ pamsshagentauth_user_key_allowed2(pw, key, authorized_keys_file))
|
|
||||||
|| pamsshagentauth_user_key_command_allowed2(authorized_keys_command,
|
|
||||||
authorized_keys_command_user,
|
|
||||||
getpwnam(ruser), key);
|
|
@ -1,37 +0,0 @@
|
|||||||
diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-seteuid openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c
|
|
||||||
--- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-seteuid 2017-02-07 15:41:53.172334151 +0100
|
|
||||||
+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-02-07 15:41:53.174334149 +0100
|
|
||||||
@@ -238,17 +238,26 @@ ssh_get_authentication_socket_for_uid(ui
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
- seteuid(uid); /* To ensure a race condition is not used to circumvent the stat
|
|
||||||
- above, we will temporarily drop UID to the caller */
|
|
||||||
- if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) {
|
|
||||||
+ /* To ensure a race condition is not used to circumvent the stat
|
|
||||||
+ above, we will temporarily drop UID to the caller */
|
|
||||||
+ if (seteuid(uid) == -1) {
|
|
||||||
close(sock);
|
|
||||||
- if(errno == EACCES)
|
|
||||||
- fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid);
|
|
||||||
+ error("seteuid(%lu) failed with error: %s",
|
|
||||||
+ (unsigned long) uid, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
+ if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) {
|
|
||||||
+ close(sock);
|
|
||||||
+ sock = -1;
|
|
||||||
+ if(errno == EACCES)
|
|
||||||
+ fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid);
|
|
||||||
+ }
|
|
||||||
|
|
||||||
- seteuid(0); /* we now continue the regularly scheduled programming */
|
|
||||||
-
|
|
||||||
+ /* we now continue the regularly scheduled programming */
|
|
||||||
+ if (0 != seteuid(0)) {
|
|
||||||
+ fatal("setuid(0) failed with error: %s", strerror(errno));
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
return sock;
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
|||||||
diff -up openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.rsasha2 openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c
|
|
||||||
--- openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c.rsasha2 2022-07-15 15:08:12.865585410 +0200
|
|
||||||
+++ openssh-8.7p1/pam_ssh_agent_auth-pam_ssh_agent_auth-0.10.4/userauth_pubkey_from_id.c 2022-07-15 15:16:25.164282372 +0200
|
|
||||||
@@ -87,8 +87,13 @@ userauth_pubkey_from_id(const char *ruse
|
|
||||||
(r = sshbuf_put_string(b, pkblob, blen)) != 0)
|
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
|
|
||||||
- if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0)
|
|
||||||
- goto user_auth_clean_exit;
|
|
||||||
+ if (sshkey_type_plain(id->key->type) == KEY_RSA
|
|
||||||
+ && ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), "rsa-sha2-256", 0) == 0) {
|
|
||||||
+ /* Do nothing */
|
|
||||||
+ } else {
|
|
||||||
+ if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0)
|
|
||||||
+ goto user_auth_clean_exit;
|
|
||||||
+ }
|
|
||||||
|
|
||||||
/* test for correct signature */
|
|
||||||
if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0, NULL) == 0)
|
|
@ -1,21 +0,0 @@
|
|||||||
diff -up openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visibility openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c
|
|
||||||
--- openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c.psaa-visibility 2014-03-31 19:35:17.000000000 +0200
|
|
||||||
+++ openssh-7.1p2/pam_ssh_agent_auth-0.10.2/pam_ssh_agent_auth.c 2016-01-22 15:22:40.984469774 +0100
|
|
||||||
@@ -72,7 +72,7 @@ char *__progname;
|
|
||||||
extern char *__progname;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
-PAM_EXTERN int
|
|
||||||
+PAM_EXTERN int __attribute__ ((visibility ("default")))
|
|
||||||
pam_sm_authenticate(pam_handle_t * pamh, int flags, int argc, const char **argv)
|
|
||||||
{
|
|
||||||
char **argv_ptr;
|
|
||||||
@@ -214,7 +214,7 @@ cleanexit:
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-PAM_EXTERN int
|
|
||||||
+PAM_EXTERN int __attribute__ ((visibility ("default")))
|
|
||||||
pam_sm_setcred(pam_handle_t * pamh, int flags, int argc, const char **argv)
|
|
||||||
{
|
|
||||||
UNUSED(pamh);
|
|
@ -1,96 +0,0 @@
|
|||||||
diff -up openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/identity.h
|
|
||||||
--- openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-agent 2016-11-13 04:24:32.000000000 +0100
|
|
||||||
+++ openssh/pam_ssh_agent_auth-0.10.3/identity.h 2017-09-27 14:25:49.421739027 +0200
|
|
||||||
@@ -38,6 +38,12 @@
|
|
||||||
typedef struct identity Identity;
|
|
||||||
typedef struct idlist Idlist;
|
|
||||||
|
|
||||||
+typedef struct {
|
|
||||||
+ int fd;
|
|
||||||
+ struct sshbuf *identities;
|
|
||||||
+ int howmany;
|
|
||||||
+} AuthenticationConnection;
|
|
||||||
+
|
|
||||||
struct identity {
|
|
||||||
TAILQ_ENTRY(identity) next;
|
|
||||||
AuthenticationConnection *ac; /* set if agent supports key */
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-agent 2017-09-27 14:25:49.420739021 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-09-27 14:25:49.421739027 +0200
|
|
||||||
@@ -39,6 +39,7 @@
|
|
||||||
#include "sshbuf.h"
|
|
||||||
#include "sshkey.h"
|
|
||||||
#include "authfd.h"
|
|
||||||
+#include "ssherr.h"
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include "ssh2.h"
|
|
||||||
@@ -291,36 +292,43 @@ pamsshagentauth_find_authorized_keys(con
|
|
||||||
{
|
|
||||||
struct sshbuf *session_id2 = NULL;
|
|
||||||
Identity *id;
|
|
||||||
- struct sshkey *key;
|
|
||||||
AuthenticationConnection *ac;
|
|
||||||
- char *comment;
|
|
||||||
uint8_t retval = 0;
|
|
||||||
uid_t uid = getpwnam(ruser)->pw_uid;
|
|
||||||
+ struct ssh_identitylist *idlist;
|
|
||||||
+ int r;
|
|
||||||
+ unsigned int i;
|
|
||||||
|
|
||||||
OpenSSL_add_all_digests();
|
|
||||||
pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
|
|
||||||
|
|
||||||
if ((ac = ssh_get_authentication_connection_for_uid(uid))) {
|
|
||||||
verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
|
||||||
- for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2))
|
|
||||||
- {
|
|
||||||
- if(key != NULL) {
|
|
||||||
+ if ((r = ssh_fetch_identitylist(ac->fd, &idlist)) != 0) {
|
|
||||||
+ if (r != SSH_ERR_AGENT_NO_IDENTITIES)
|
|
||||||
+ fprintf(stderr, "error fetching identities for "
|
|
||||||
+ "protocol %d: %s\n", 2, ssh_err(r));
|
|
||||||
+ } else {
|
|
||||||
+ for (i = 0; i < idlist->nkeys; i++)
|
|
||||||
+ {
|
|
||||||
+ if (idlist->keys[i] != NULL) {
|
|
||||||
id = xcalloc(1, sizeof(*id));
|
|
||||||
- id->key = key;
|
|
||||||
- id->filename = comment;
|
|
||||||
+ id->key = idlist->keys[i];
|
|
||||||
+ id->filename = idlist->comments[i];
|
|
||||||
id->ac = ac;
|
|
||||||
if(userauth_pubkey_from_id(ruser, id, session_id2)) {
|
|
||||||
retval = 1;
|
|
||||||
}
|
|
||||||
- free(id->filename);
|
|
||||||
- key_free(id->key);
|
|
||||||
free(id);
|
|
||||||
if(retval == 1)
|
|
||||||
break;
|
|
||||||
- }
|
|
||||||
- }
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
- sshbuf_free(session_id2);
|
|
||||||
- ssh_close_authentication_connection(ac);
|
|
||||||
+ sshbuf_free(session_id2);
|
|
||||||
+ ssh_free_identitylist(idlist);
|
|
||||||
+ }
|
|
||||||
+ ssh_close_authentication_socket(ac->fd);
|
|
||||||
+ free(ac);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
verbose("No ssh-agent could be contacted");
|
|
||||||
diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-agent openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c
|
|
||||||
--- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-agent 2017-09-27 14:25:49.420739021 +0200
|
|
||||||
+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c 2017-09-27 14:25:49.422739032 +0200
|
|
||||||
@@ -84,7 +85,7 @@ userauth_pubkey_from_id(const char *ruse
|
|
||||||
(r = sshbuf_put_string(b, pkblob, blen)) != 0)
|
|
||||||
fatal("%s: buffer error: %s", __func__, ssh_err(r));
|
|
||||||
|
|
||||||
- if (ssh_agent_sign(id->ac, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b)) != 0)
|
|
||||||
+ if (ssh_agent_sign(id->ac->fd, id->key, &sig, &slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) != 0)
|
|
||||||
goto user_auth_clean_exit;
|
|
||||||
|
|
||||||
/* test for correct signature */
|
|
@ -1,198 +0,0 @@
|
|||||||
diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c
|
|
||||||
--- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-build 2016-11-13 04:24:32.000000000 +0100
|
|
||||||
+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2017-02-07 14:29:41.626116675 +0100
|
|
||||||
@@ -43,12 +43,31 @@
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
#include "ssh2.h"
|
|
||||||
#include "misc.h"
|
|
||||||
+#include "ssh.h"
|
|
||||||
+#include <sys/types.h>
|
|
||||||
+#include <sys/stat.h>
|
|
||||||
+#include <sys/socket.h>
|
|
||||||
+#include <sys/un.h>
|
|
||||||
+#include <unistd.h>
|
|
||||||
+#include <stdlib.h>
|
|
||||||
+#include <errno.h>
|
|
||||||
+#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "userauth_pubkey_from_id.h"
|
|
||||||
#include "identity.h"
|
|
||||||
#include "get_command_line.h"
|
|
||||||
extern char **environ;
|
|
||||||
|
|
||||||
+/*
|
|
||||||
+ * Added by Jamie Beverly, ensure socket fd points to a socket owned by the user
|
|
||||||
+ * A cursory check is done, but to avoid race conditions, it is necessary
|
|
||||||
+ * to drop effective UID when connecting to the socket.
|
|
||||||
+ *
|
|
||||||
+ * If the cause of error is EACCES, because we verified we would not have that
|
|
||||||
+ * problem initially, we can safely assume that somebody is attempting to find a
|
|
||||||
+ * race condition; so a more "direct" log message is generated.
|
|
||||||
+ */
|
|
||||||
+
|
|
||||||
static char *
|
|
||||||
log_action(char ** action, size_t count)
|
|
||||||
{
|
|
||||||
@@ -85,7 +104,7 @@ void
|
|
||||||
pamsshagentauth_session_id2_gen(Buffer * session_id2, const char * user,
|
|
||||||
const char * ruser, const char * servicename)
|
|
||||||
{
|
|
||||||
- char *cookie = NULL;
|
|
||||||
+ u_char *cookie = NULL;
|
|
||||||
uint8_t i = 0;
|
|
||||||
uint32_t rnd = 0;
|
|
||||||
uint8_t cookie_len;
|
|
||||||
@@ -112,7 +131,7 @@ pamsshagentauth_session_id2_gen(Buffer *
|
|
||||||
if (i % 4 == 0) {
|
|
||||||
rnd = pamsshagentauth_arc4random();
|
|
||||||
}
|
|
||||||
- cookie[i] = (char) rnd;
|
|
||||||
+ cookie[i] = (u_char) rnd;
|
|
||||||
rnd >>= 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -177,6 +196,86 @@ pamsshagentauth_session_id2_gen(Buffer *
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
+ssh_get_authentication_socket_for_uid(uid_t uid)
|
|
||||||
+{
|
|
||||||
+ const char *authsocket;
|
|
||||||
+ int sock;
|
|
||||||
+ struct sockaddr_un sunaddr;
|
|
||||||
+ struct stat sock_st;
|
|
||||||
+
|
|
||||||
+ authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
|
|
||||||
+ if (!authsocket)
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ /* Advisory only; seteuid ensures no race condition; but will only log if we see EACCES */
|
|
||||||
+ if( stat(authsocket,&sock_st) == 0) {
|
|
||||||
+ if(uid != 0 && sock_st.st_uid != uid) {
|
|
||||||
+ fatal("uid %lu attempted to open an agent socket owned by uid %lu", (unsigned long) uid, (unsigned long) sock_st.st_uid);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Ensures that the EACCES tested for below can _only_ happen if somebody
|
|
||||||
+ * is attempting to race the stat above to bypass authentication.
|
|
||||||
+ */
|
|
||||||
+ if( (sock_st.st_mode & S_IWUSR) != S_IWUSR || (sock_st.st_mode & S_IRUSR) != S_IRUSR) {
|
|
||||||
+ error("ssh-agent socket has incorrect permissions for owner");
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ sunaddr.sun_family = AF_UNIX;
|
|
||||||
+ strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
|
|
||||||
+
|
|
||||||
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
|
||||||
+ if (sock < 0)
|
|
||||||
+ return -1;
|
|
||||||
+
|
|
||||||
+ /* close on exec */
|
|
||||||
+ if (fcntl(sock, F_SETFD, 1) == -1) {
|
|
||||||
+ close(sock);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ errno = 0;
|
|
||||||
+ seteuid(uid); /* To ensure a race condition is not used to circumvent the stat
|
|
||||||
+ above, we will temporarily drop UID to the caller */
|
|
||||||
+ if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) {
|
|
||||||
+ close(sock);
|
|
||||||
+ if(errno == EACCES)
|
|
||||||
+ fatal("MAJOR SECURITY WARNING: uid %lu made a deliberate and malicious attempt to open an agent socket owned by another user", (unsigned long) uid);
|
|
||||||
+ return -1;
|
|
||||||
+ }
|
|
||||||
+
|
|
||||||
+ seteuid(0); /* we now continue the regularly scheduled programming */
|
|
||||||
+
|
|
||||||
+ return sock;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+AuthenticationConnection *
|
|
||||||
+ssh_get_authentication_connection_for_uid(uid_t uid)
|
|
||||||
+{
|
|
||||||
+ AuthenticationConnection *auth;
|
|
||||||
+ int sock;
|
|
||||||
+
|
|
||||||
+ sock = ssh_get_authentication_socket_for_uid(uid);
|
|
||||||
+
|
|
||||||
+ /*
|
|
||||||
+ * Fail if we couldn't obtain a connection. This happens if we
|
|
||||||
+ * exited due to a timeout.
|
|
||||||
+ */
|
|
||||||
+ if (sock < 0)
|
|
||||||
+ return NULL;
|
|
||||||
+
|
|
||||||
+ auth = xmalloc(sizeof(*auth));
|
|
||||||
+ auth->fd = sock;
|
|
||||||
+ buffer_init(&auth->identities);
|
|
||||||
+ auth->howmany = 0;
|
|
||||||
+
|
|
||||||
+ return auth;
|
|
||||||
+}
|
|
||||||
+
|
|
||||||
+int
|
|
||||||
pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename)
|
|
||||||
{
|
|
||||||
Buffer session_id2 = { 0 };
|
|
||||||
@@ -190,7 +289,7 @@ pamsshagentauth_find_authorized_keys(con
|
|
||||||
OpenSSL_add_all_digests();
|
|
||||||
pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename);
|
|
||||||
|
|
||||||
- if ((ac = ssh_get_authentication_connection(uid))) {
|
|
||||||
+ if ((ac = ssh_get_authentication_connection_for_uid(uid))) {
|
|
||||||
pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid);
|
|
||||||
for (key = ssh_get_first_identity(ac, &comment, 2); key != NULL; key = ssh_get_next_identity(ac, &comment, 2))
|
|
||||||
{
|
|
||||||
diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in
|
|
||||||
--- openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build 2016-11-13 04:24:32.000000000 +0100
|
|
||||||
+++ openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in 2017-02-07 14:40:14.407566921 +0100
|
|
||||||
@@ -52,7 +52,7 @@ PATHS=
|
|
||||||
CC=@CC@
|
|
||||||
LD=@LD@
|
|
||||||
CFLAGS=@CFLAGS@
|
|
||||||
-CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
|
|
||||||
+CPPFLAGS=-I.. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@
|
|
||||||
LIBS=@LIBS@
|
|
||||||
AR=@AR@
|
|
||||||
AWK=@AWK@
|
|
||||||
@@ -61,8 +61,8 @@ INSTALL=@INSTALL@
|
|
||||||
PERL=@PERL@
|
|
||||||
SED=@SED@
|
|
||||||
ENT=@ENT@
|
|
||||||
-LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@
|
|
||||||
-LDFLAGS_SHARED = @LDFLAGS_SHARED@
|
|
||||||
+LDFLAGS=-L.. -L../openbsd-compat/ @LDFLAGS@
|
|
||||||
+LDFLAGS_SHARED =-Wl,-z,defs @LDFLAGS_SHARED@
|
|
||||||
EXEEXT=@EXEEXT@
|
|
||||||
|
|
||||||
INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@
|
|
||||||
@@ -74,7 +74,7 @@ SSHOBJS=xmalloc.o atomicio.o authfd.o bu
|
|
||||||
|
|
||||||
ED25519OBJS=ed25519-donna/ed25519.o
|
|
||||||
|
|
||||||
-PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o userauth_pubkey_from_pam.o
|
|
||||||
+PAM_SSH_AGENT_AUTH_OBJS=pam_user_key_allowed2.o iterate_ssh_agent_keys.o userauth_pubkey_from_id.o pam_user_authorized_keys.o get_command_line.o userauth_pubkey_from_pam.o secure_filename.o
|
|
||||||
|
|
||||||
|
|
||||||
MANPAGES_IN = pam_ssh_agent_auth.pod
|
|
||||||
@@ -94,13 +94,13 @@ $(PAM_MODULES): Makefile.in config.h
|
|
||||||
.c.o:
|
|
||||||
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
|
|
||||||
|
|
||||||
-LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
|
|
||||||
+LIBCOMPAT=../openbsd-compat/libopenbsd-compat.a
|
|
||||||
$(LIBCOMPAT): always
|
|
||||||
(cd openbsd-compat && $(MAKE))
|
|
||||||
always:
|
|
||||||
|
|
||||||
-pam_ssh_agent_auth.so: $(LIBCOMPAT) $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o
|
|
||||||
- $(LD) $(LDFLAGS_SHARED) -o $@ $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lopenbsd-compat pam_ssh_agent_auth.o $(LIBS) -lpam
|
|
||||||
+pam_ssh_agent_auth.so: $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o ../uidswap.o ../ssh-sk-client.o
|
|
||||||
+ $(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) ../ssh-sk-client.o $(LDFLAGS) -lssh -lopenbsd-compat pam_ssh_agent_auth.o ../uidswap.o $(LIBS) -lpam
|
|
||||||
|
|
||||||
$(MANPAGES): $(MANPAGES_IN)
|
|
||||||
pod2man --section=8 --release=v0.10.3 --name=pam_ssh_agent_auth --official --center "PAM" pam_ssh_agent_auth.pod > pam_ssh_agent_auth.8
|
|
@ -0,0 +1,14 @@
|
|||||||
|
# just a Makefile parallel_test.sh uses to run stuff in parallel with make
|
||||||
|
%:
|
||||||
|
$(MAKE) -j1 -C .t/$* $*
|
||||||
|
|
||||||
|
t-exec-%:
|
||||||
|
$(MAKE) -j1 -C ".t/t-exec-$*" \
|
||||||
|
TEST_SSH_PORT=10$*0 \
|
||||||
|
SKIP_LTESTS="$(shell cat .ltests/not-in/$*)" \
|
||||||
|
BUILDDIR="$(shell pwd)/.t/t-exec-$*" \
|
||||||
|
TEST_SHELL=sh \
|
||||||
|
MAKE=make \
|
||||||
|
TEST_SSH_TRACE=yes \
|
||||||
|
TEST_SSH_FAIL_FATAL=yes \
|
||||||
|
t-exec \
|
@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
set -uexo pipefail
|
||||||
|
|
||||||
|
# The custom %check script to run the OpenSSH upstream testsuite in parallel.
|
||||||
|
#
|
||||||
|
# The upstream testsuite is serial,
|
||||||
|
# so the idea here is to split the testsuite into several $PARTS:
|
||||||
|
# * file-tests
|
||||||
|
# * interop-tests
|
||||||
|
# * unit
|
||||||
|
# * ltests-00
|
||||||
|
# * ltests-01
|
||||||
|
# * ...
|
||||||
|
# * ltests-23
|
||||||
|
# and run them in parallel, using make, each in its own build subtree.
|
||||||
|
|
||||||
|
PARALLEL_MAKEFILE=$1
|
||||||
|
|
||||||
|
SPLIT=24
|
||||||
|
PARTS='file-tests interop-tests unit '
|
||||||
|
for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i);
|
||||||
|
PARTS+="t-exec-$ii "
|
||||||
|
done
|
||||||
|
|
||||||
|
# work around a selinux restriction:
|
||||||
|
#chcon -t unconfined_exec_t ssh-sk-helper || :
|
||||||
|
|
||||||
|
# work around something else that only crops up in brew
|
||||||
|
export TEST_SSH_UNSAFE_PERMISSIONS=1
|
||||||
|
|
||||||
|
# create a .test directory to store all our files in:
|
||||||
|
mkdir -p .t .ltests/{in,not-in}
|
||||||
|
|
||||||
|
# patch testsuite: use different ports to avoid port collisions
|
||||||
|
grep -REi 'port=[2-9][0-9]*' regress
|
||||||
|
sed -i 's|PORT=4242|PORT=$(expr $TEST_SSH_PORT + 1)|' \
|
||||||
|
regress/test-exec.sh*
|
||||||
|
sed -i 's|^P=3301 # test port|P=$(expr $TEST_SSH_PORT + 1)|' \
|
||||||
|
regress/multiplex.sh*
|
||||||
|
sed -i 's|^fwdport=3301|fwdport=$(expr $TEST_SSH_PORT + 1)|' \
|
||||||
|
regress/cfgmatch.sh* regress/cfgmatchlisten.sh*
|
||||||
|
sed -i 's|^LFWD_PORT=.*|LFWD_PORT=$(expr $TEST_SSH_PORT + 1)|' \
|
||||||
|
regress/forward-control.sh*
|
||||||
|
sed -i 's|^RFWD_PORT=.*|RFWD_PORT=$(expr $TEST_SSH_PORT + 2)|' \
|
||||||
|
regress/forward-control.sh*
|
||||||
|
( ! grep -REi 'port=[2-9][0-9]*' regress) # try to find more of those
|
||||||
|
|
||||||
|
# patch testsuite: speed up
|
||||||
|
sed -i 's|sleep 1$|sleep .25|' regress/forward-control.sh
|
||||||
|
|
||||||
|
# extract LTESTS list to .tests/ltests/all:
|
||||||
|
grep -Ex 'tests:[[:space:]]*file-tests t-exec interop-tests extra-tests unit' Makefile
|
||||||
|
echo -ne '\necho-ltests:\n\techo ${LTESTS}' >> regress/Makefile
|
||||||
|
make -s -C regress echo-ltests | tr ' ' '\n' > .ltests/all
|
||||||
|
|
||||||
|
# separate ltests into $SPLIT roughly equal .tests/ltests/in/$ii parts:
|
||||||
|
grep -qFx connect .ltests/all
|
||||||
|
( ! grep -qFx nonex .ltests/all )
|
||||||
|
split -d -a2 --number=l/$SPLIT .ltests/all .ltests/in/
|
||||||
|
wc -l .ltests/in/*
|
||||||
|
grep -qFx connect .ltests/in/*
|
||||||
|
|
||||||
|
# generate the inverses of them --- .ltests/not-in/$ii:
|
||||||
|
( ! grep -qFx nonex .ltests/in/* )
|
||||||
|
for ((i = 0; i < SPLIT; i++)); do ii=$(printf %02d $i);
|
||||||
|
while read -r tname; do
|
||||||
|
if ! grep -qFx "$tname" ".ltests/in/$ii"; then
|
||||||
|
echo -n "$tname " >> ".ltests/not-in/$ii"
|
||||||
|
fi
|
||||||
|
done < .ltests/all
|
||||||
|
done
|
||||||
|
grep . .ltests/not-in/*
|
||||||
|
( ! grep -q ^connect .ltests/not-in/0 )
|
||||||
|
for ((i = 1; i < SPLIT; i++)); do ii=$(printf %02d $i);
|
||||||
|
grep -q ^connect .ltests/not-in/$ii
|
||||||
|
done
|
||||||
|
|
||||||
|
# prepare several test directories:
|
||||||
|
for PART in $PARTS; do
|
||||||
|
mkdir .t/${PART}
|
||||||
|
cp -ra * .t/${PART}/
|
||||||
|
sed -i "s|abs_top_srcdir=.*|abs_top_srcdir=$(pwd)/.t/${PART}|" \
|
||||||
|
.t/${PART}/Makefile
|
||||||
|
sed -i "s|abs_top_builddir=.*|abs_top_builddir=$(pwd)/.t/${PART}|" \
|
||||||
|
.t/${PART}/Makefile
|
||||||
|
sed -i "s|^BUILDDIR=.*|BUILDDIR=$(pwd)/.t/${PART}|" \
|
||||||
|
.t/${PART}/Makefile
|
||||||
|
done
|
||||||
|
|
||||||
|
# finally, run tests $PARTS in parallel in their own subtrees:
|
||||||
|
time make -f "$PARALLEL_MAKEFILE" -j$(nproc) $PARTS
|
@ -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
|
@ -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
|
@ -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"
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue