import CS openssh-9.9p1-4.el9
This commit is contained in:
parent
88fdf9a2a3
commit
22cebc4f1e
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,3 @@
|
||||
SOURCES/gpgkey-736060BA.gpg
|
||||
SOURCES/openssh-8.7p1.tar.gz
|
||||
SOURCES/openssh-9.9p1.tar.gz
|
||||
SOURCES/pam_ssh_agent_auth-0.10.4.tar.gz
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
dbb35b4e9ae3f72b930a82c6fd5e83e9dcd7b193 SOURCES/gpgkey-736060BA.gpg
|
||||
8719032c1e47732c8fdb14adfb24b5e9e71de802 SOURCES/openssh-8.7p1.tar.gz
|
||||
5ded7eb0add0b02b5d1a1c4bf5cb2c89d2117b53 SOURCES/openssh-9.9p1.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
|
||||
--- openssh-5.8p2/ssh-keyscan.c.sigpipe 2011-08-23 18:30:33.873025916 +0200
|
||||
+++ openssh-5.8p2/ssh-keyscan.c 2011-08-23 18:32:24.574025362 +0200
|
||||
@@ -715,6 +715,8 @@ main(int argc, char **argv)
|
||||
@@ -715,6 +715,9 @@ main(int argc, char **argv)
|
||||
if (maxfd > fdlim_get(0))
|
||||
fdlim_set(maxfd);
|
||||
fdcon = xcalloc(maxfd, sizeof(con));
|
||||
|
||||
+
|
||||
+ signal(SIGPIPE, SIG_IGN);
|
||||
+
|
||||
read_wait_nfdset = howmany(maxfd, NFDBITS);
|
||||
read_wait = xcalloc(read_wait_nfdset, sizeof(fd_mask));
|
||||
read_wait = xcalloc(maxfd, sizeof(struct pollfd));
|
||||
for (j = 0; j < maxfd; j++)
|
||||
read_wait[j].fd = -1;
|
||||
|
||||
|
||||
@ -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,6 +1,6 @@
|
||||
diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c
|
||||
--- openssh-8.6p1/log.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/log.c 2021-05-06 11:32:25.179006811 +0200
|
||||
+++ openssh-8.6p1/log.c 2021-04-19 14:43:08.544843434 +0200
|
||||
@@ -194,6 +194,11 @@ void
|
||||
log_init(const char *av0, LogLevel level, SyslogFacility facility,
|
||||
int on_stderr)
|
||||
@ -27,8 +27,8 @@ diff -up openssh-8.6p1/log.c.log-in-chroot openssh-8.6p1/log.c
|
||||
log_on_stderr = on_stderr;
|
||||
if (on_stderr)
|
||||
diff -up openssh-8.6p1/log.h.log-in-chroot openssh-8.6p1/log.h
|
||||
--- openssh-8.6p1/log.h.log-in-chroot 2021-05-06 11:32:25.179006811 +0200
|
||||
+++ openssh-8.6p1/log.h 2021-05-06 11:34:22.349925757 +0200
|
||||
--- openssh-8.6p1/log.h.log-in-chroot 2021-04-19 14:43:08.544843434 +0200
|
||||
+++ openssh-8.6p1/log.h 2021-04-19 14:56:46.931042176 +0200
|
||||
@@ -52,6 +52,7 @@ typedef enum {
|
||||
typedef void (log_handler_fn)(LogLevel, int, const char *, void *);
|
||||
|
||||
@ -38,8 +38,8 @@ diff -up openssh-8.6p1/log.h.log-in-chroot openssh-8.6p1/log.h
|
||||
int log_change_level(LogLevel);
|
||||
int log_is_on_stderr(void);
|
||||
diff -up openssh-8.6p1/monitor.c.log-in-chroot openssh-8.6p1/monitor.c
|
||||
--- openssh-8.6p1/monitor.c.log-in-chroot 2021-05-06 11:32:25.153006607 +0200
|
||||
+++ openssh-8.6p1/monitor.c 2021-05-06 11:33:37.671575348 +0200
|
||||
--- openssh-8.6p1/monitor.c.log-in-chroot 2021-04-19 14:43:08.526843298 +0200
|
||||
+++ openssh-8.6p1/monitor.c 2021-04-19 14:55:25.286424043 +0200
|
||||
@@ -297,6 +297,8 @@ monitor_child_preauth(struct ssh *ssh, s
|
||||
close(pmonitor->m_log_sendfd);
|
||||
pmonitor->m_log_sendfd = pmonitor->m_recvfd = -1;
|
||||
@ -99,8 +99,8 @@ diff -up openssh-8.6p1/monitor.c.log-in-chroot openssh-8.6p1/monitor.c
|
||||
|
||||
#ifdef GSSAPI
|
||||
diff -up openssh-8.6p1/monitor.h.log-in-chroot openssh-8.6p1/monitor.h
|
||||
--- openssh-8.6p1/monitor.h.log-in-chroot 2021-05-06 11:32:25.153006607 +0200
|
||||
+++ openssh-8.6p1/monitor.h 2021-05-06 11:32:25.180006819 +0200
|
||||
--- openssh-8.6p1/monitor.h.log-in-chroot 2021-04-19 14:43:08.527843305 +0200
|
||||
+++ openssh-8.6p1/monitor.h 2021-04-19 14:43:08.545843441 +0200
|
||||
@@ -80,10 +80,11 @@ struct monitor {
|
||||
int m_log_sendfd;
|
||||
struct kex **m_pkex;
|
||||
@ -115,8 +115,8 @@ diff -up openssh-8.6p1/monitor.h.log-in-chroot openssh-8.6p1/monitor.h
|
||||
struct Authctxt;
|
||||
void monitor_child_preauth(struct ssh *, struct monitor *);
|
||||
diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c
|
||||
--- openssh-8.6p1/session.c.log-in-chroot 2021-05-06 11:32:25.166006709 +0200
|
||||
+++ openssh-8.6p1/session.c 2021-05-06 11:32:25.181006827 +0200
|
||||
--- openssh-8.6p1/session.c.log-in-chroot 2021-04-19 14:43:08.534843358 +0200
|
||||
+++ openssh-8.6p1/session.c 2021-04-19 14:43:08.545843441 +0200
|
||||
@@ -160,6 +160,7 @@ login_cap_t *lc;
|
||||
|
||||
static int is_child = 0;
|
||||
@ -189,7 +189,7 @@ diff -up openssh-8.6p1/session.c.log-in-chroot openssh-8.6p1/session.c
|
||||
/* Get the last component of the shell name. */
|
||||
diff -up openssh-8.6p1/sftp.h.log-in-chroot openssh-8.6p1/sftp.h
|
||||
--- openssh-8.6p1/sftp.h.log-in-chroot 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/sftp.h 2021-05-06 11:32:25.181006827 +0200
|
||||
+++ openssh-8.6p1/sftp.h 2021-04-19 14:43:08.545843441 +0200
|
||||
@@ -97,5 +97,5 @@
|
||||
|
||||
struct passwd;
|
||||
@ -199,7 +199,7 @@ diff -up openssh-8.6p1/sftp.h.log-in-chroot openssh-8.6p1/sftp.h
|
||||
void sftp_server_cleanup_exit(int) __attribute__((noreturn));
|
||||
diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c
|
||||
--- openssh-8.6p1/sftp-server.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/sftp-server.c 2021-05-06 11:32:25.181006827 +0200
|
||||
+++ openssh-8.6p1/sftp-server.c 2021-04-19 14:43:08.545843441 +0200
|
||||
@@ -1644,7 +1644,7 @@ sftp_server_usage(void)
|
||||
}
|
||||
|
||||
@ -207,8 +207,8 @@ diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c
|
||||
-sftp_server_main(int argc, char **argv, struct passwd *user_pw)
|
||||
+sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handler)
|
||||
{
|
||||
fd_set *rset, *wset;
|
||||
int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0;
|
||||
int i, r, in, out, ch, skipargs = 0, log_stderr = 0;
|
||||
ssize_t len, olen;
|
||||
@@ -1657,7 +1657,7 @@ sftp_server_main(int argc, char **argv,
|
||||
extern char *__progname;
|
||||
|
||||
@ -229,7 +229,7 @@ diff -up openssh-8.6p1/sftp-server.c.log-in-chroot openssh-8.6p1/sftp-server.c
|
||||
* On platforms where we can, avoid making /proc/self/{mem,maps}
|
||||
diff -up openssh-8.6p1/sftp-server-main.c.log-in-chroot openssh-8.6p1/sftp-server-main.c
|
||||
--- openssh-8.6p1/sftp-server-main.c.log-in-chroot 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/sftp-server-main.c 2021-05-06 11:32:25.181006827 +0200
|
||||
+++ openssh-8.6p1/sftp-server-main.c 2021-04-19 14:43:08.545843441 +0200
|
||||
@@ -50,5 +50,5 @@ main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
@ -237,11 +237,11 @@ diff -up openssh-8.6p1/sftp-server-main.c.log-in-chroot openssh-8.6p1/sftp-serve
|
||||
- return (sftp_server_main(argc, argv, user_pw));
|
||||
+ return (sftp_server_main(argc, argv, user_pw, 0));
|
||||
}
|
||||
diff -up openssh-8.6p1/sshd.c.log-in-chroot openssh-8.6p1/sshd.c
|
||||
--- openssh-8.6p1/sshd.c.log-in-chroot 2021-05-06 11:32:25.177006795 +0200
|
||||
+++ openssh-8.6p1/sshd.c 2021-05-06 11:32:25.182006834 +0200
|
||||
diff -up openssh-8.6p1/sshd-session.c.log-in-chroot openssh-8.6p1/sshd-session.c
|
||||
--- openssh-8.6p1/sshd-session.c.log-in-chroot 2021-04-19 14:43:08.543843426 +0200
|
||||
+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:43:08.545843441 +0200
|
||||
@@ -559,7 +559,7 @@ privsep_postauth(struct ssh *ssh, Authct
|
||||
}
|
||||
#endif
|
||||
|
||||
/* New socket pair */
|
||||
- monitor_reinit(pmonitor);
|
||||
|
||||
@ -93,19 +93,17 @@ index 8f32464..18a2ca4 100644
|
||||
#endif
|
||||
|
||||
diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
|
||||
index 22ea8ef..1fc963d 100644
|
||||
--- a/openbsd-compat/port-linux.c
|
||||
+++ b/openbsd-compat/port-linux.c
|
||||
@@ -179,7 +179,7 @@ ssh_selinux_change_context(const char *newname)
|
||||
strlcpy(newctx + len, newname, newlen - len);
|
||||
if ((cx = index(cx + 1, ':')))
|
||||
strlcat(newctx, cx, newlen);
|
||||
- debug3("%s: setting context from '%s' to '%s'", __func__,
|
||||
+ debug_f("setting context from '%s' to '%s'",
|
||||
oldctx, newctx);
|
||||
--- a/openbsd-compat/port-linux.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||
+++ b/openbsd-compat/port-linux.c (date 1703108053912)
|
||||
@@ -207,7 +207,7 @@
|
||||
xasprintf(&newctx, "%.*s%s%s", (int)(cx - oldctx + 1), oldctx,
|
||||
newname, cx2 == NULL ? "" : cx2);
|
||||
|
||||
- debug3_f("setting context from '%s' to '%s'", oldctx, newctx);
|
||||
+ debug_f("setting context from '%s' to '%s'", oldctx, newctx);
|
||||
if (setcon(newctx) < 0)
|
||||
do_log2(log_level, "%s: setcon %s from %s failed with %s",
|
||||
__func__, newctx, oldctx, strerror(errno));
|
||||
do_log2_f(log_level, "setcon %s from %s failed with %s",
|
||||
newctx, oldctx, strerror(errno));
|
||||
diff --git a/openbsd-compat/port-linux.h b/openbsd-compat/port-linux.h
|
||||
index cb51f99..8b7cda2 100644
|
||||
--- a/openbsd-compat/port-linux.h
|
||||
@ -118,10 +116,10 @@ index cb51f99..8b7cda2 100644
|
||||
#endif
|
||||
|
||||
#ifdef LINUX_OOM_ADJUST
|
||||
diff --git a/sshd.c b/sshd.c
|
||||
diff --git a/sshd-session.c b/sshd-session.c
|
||||
index 2871fe9..39b9c08 100644
|
||||
--- a/sshd.c
|
||||
+++ b/sshd.c
|
||||
--- a/sshd-session.c
|
||||
+++ b/sshd-session.c
|
||||
@@ -629,7 +629,7 @@ privsep_preauth_child(void)
|
||||
demote_sensitive_data();
|
||||
|
||||
|
||||
@ -38,16 +38,16 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c
|
||||
if (options->password_authentication == -1)
|
||||
options->password_authentication = 1;
|
||||
if (options->kbd_interactive_authentication == -1)
|
||||
@@ -418,7 +421,7 @@ typedef enum {
|
||||
sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedAlgorithms,
|
||||
@@ -578,7 +578,7 @@ typedef enum {
|
||||
sHostKeyAlgorithms, sPerSourceMaxStartups, sPerSourceNetBlockSize,
|
||||
sPerSourcePenalties, sPerSourcePenaltyExemptList,
|
||||
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
|
||||
- sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
|
||||
+ sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
|
||||
sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey,
|
||||
sAcceptEnv, sSetEnv, sPermitTunnel,
|
||||
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
|
||||
@@ -497,14 +500,16 @@ static struct {
|
||||
@@ -600,14 +600,16 @@ static struct {
|
||||
{ "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
|
||||
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
|
||||
{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
|
||||
@ -129,3 +129,6 @@ diff -up openssh-7.4p1/sshd_config.GSSAPIEnablek5users openssh-7.4p1/sshd_config
|
||||
|
||||
# Set this to 'yes' to enable PAM authentication, account processing,
|
||||
# and session processing. If this is enabled, PAM authentication will
|
||||
diff -up openssh-9.8p1/servconf.c.xxx openssh-9.8p1/servconf.c
|
||||
--- openssh-9.8p1/servconf.c.xxx 2024-07-11 13:51:19.969960781 +0200
|
||||
+++ openssh-9.8p1/servconf.c 2024-07-11 13:51:30.938231250 +0200
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
diff -up openssh/sshd.c.ip-opts openssh/sshd.c
|
||||
--- openssh/sshd.c.ip-opts 2016-07-25 13:58:48.998507834 +0200
|
||||
+++ openssh/sshd.c 2016-07-25 14:01:28.346469878 +0200
|
||||
@@ -1507,12 +1507,29 @@ check_ip_options(struct ssh *ssh)
|
||||
--- openssh/sshd-session.c.ip-opts 2016-07-25 13:58:48.998507834 +0200
|
||||
+++ openssh/sshd-session.c 2016-07-25 14:01:28.346469878 +0200
|
||||
@@ -1507,12 +1507,32 @@ check_ip_options(struct ssh *ssh)
|
||||
|
||||
if (getsockopt(sock_in, IPPROTO_IP, IP_OPTIONS, opts,
|
||||
&option_size) >= 0 && option_size != 0) {
|
||||
@ -21,11 +21,14 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c
|
||||
+ case 130:
|
||||
+ case 133:
|
||||
+ case 134:
|
||||
+ i += opts[i + 1];
|
||||
+ break;
|
||||
+ if (i + 1 < option_size && opts[i + 1] >= 2) {
|
||||
+ i += opts[i + 1];
|
||||
+ break;
|
||||
+ }
|
||||
+ /* FALLTHROUGH */
|
||||
+ default:
|
||||
+ /* Fail, fatally, if we detect either loose or strict
|
||||
+ * source routing options. */
|
||||
+ * or incorrect source routing options. */
|
||||
+ text[0] = '\0';
|
||||
+ for (i = 0; i < option_size; i++)
|
||||
+ snprintf(text + i*3, sizeof(text) - i*3,
|
||||
@ -35,5 +38,5 @@ diff -up openssh/sshd.c.ip-opts openssh/sshd.c
|
||||
+ }
|
||||
+ } while (i < option_size);
|
||||
}
|
||||
return;
|
||||
#endif /* IP_OPTIONS */
|
||||
}
|
||||
|
||||
@ -39,9 +39,9 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in
|
||||
SFTP_SERVER=$(libexecdir)/sftp-server
|
||||
SSH_KEYSIGN=$(libexecdir)/ssh-keysign
|
||||
+SSH_KEYCAT=$(libexecdir)/ssh-keycat
|
||||
SSHD_SESSION=$(libexecdir)/sshd-session
|
||||
SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
|
||||
SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper
|
||||
PRIVSEP_PATH=@PRIVSEP_PATH@
|
||||
@@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@
|
||||
K5LIBS=@K5LIBS@
|
||||
GSSLIBS=@GSSLIBS@
|
||||
@ -54,20 +54,20 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in
|
||||
|
||||
.SUFFIXES: .lo
|
||||
|
||||
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT)
|
||||
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT)
|
||||
-TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT)
|
||||
+TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) sshd-session$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) ssh-sk-helper$(EXEEXT) ssh-keycat$(EXEEXT)
|
||||
|
||||
XMSS_OBJS=\
|
||||
ssh-xmss.o \
|
||||
@@ -190,6 +191,9 @@ ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT)
|
||||
ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS)
|
||||
$(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2)
|
||||
$(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS)
|
||||
|
||||
+ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o
|
||||
+ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS)
|
||||
+
|
||||
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
|
||||
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
|
||||
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS)
|
||||
|
||||
@@ -321,6 +325,7 @@ install-files:
|
||||
$(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT)
|
||||
@ -95,8 +95,8 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/
|
||||
--- openssh/openbsd-compat/port-linux-sshd.c.keycat 2015-06-24 10:57:50.150849626 +0200
|
||||
+++ openssh/openbsd-compat/port-linux-sshd.c 2015-06-24 10:57:50.159849603 +0200
|
||||
@@ -54,6 +54,20 @@ extern Authctxt *the_authctxt;
|
||||
extern Authctxt *the_authctxt;
|
||||
extern int inetd_flag;
|
||||
extern int rexeced_flag;
|
||||
|
||||
+/* Wrapper around is_selinux_enabled() to log its return value once only */
|
||||
+int
|
||||
@ -131,7 +131,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.keycat openssh/openbsd-compat/
|
||||
- rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
|
||||
+ rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : "");
|
||||
|
||||
if (inetd_flag && !rexeced_flag) {
|
||||
if (inetd_flag) {
|
||||
use_current = "1";
|
||||
} else {
|
||||
use_current = "";
|
||||
|
||||
@ -155,8 +155,8 @@ diff -up openssh-7.4p1/gss-serv-krb5.c.kuserok openssh-7.4p1/gss-serv-krb5.c
|
||||
* because if they are on a krb5-protected filesystem, user credentials
|
||||
* to access these files aren't available yet. */
|
||||
- if (krb5_kuserok(krb_context, princ, name) && k5login_exists) {
|
||||
+ if (ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)
|
||||
+ && k5login_exists) {
|
||||
+ if (k5login_exists &&
|
||||
+ ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)) {
|
||||
retval = 1;
|
||||
logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
|
||||
name, (char *)client->displayname.value);
|
||||
@ -196,11 +196,11 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c
|
||||
sPort, sHostKeyFile, sLoginGraceTime,
|
||||
sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
|
||||
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
|
||||
- sKerberosGetAFSToken, sKerberosUniqueCCache,
|
||||
+ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok,
|
||||
sChallengeResponseAuthentication,
|
||||
sPasswordAuthentication, sKbdInteractiveAuthentication,
|
||||
sListenAddress, sAddressFamily,
|
||||
- sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication,
|
||||
+ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication,
|
||||
sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
|
||||
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
|
||||
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
|
||||
@@ -478,12 +481,14 @@ static struct {
|
||||
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
|
||||
#endif
|
||||
@ -266,8 +266,8 @@ diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5
|
||||
+The default is
|
||||
+.Cm yes .
|
||||
.It Cm KexAlgorithms
|
||||
Specifies the available KEX (Key Exchange) algorithms.
|
||||
Multiple algorithms must be comma-separated.
|
||||
Specifies the permitted KEX (Key Exchange) algorithms that the server will
|
||||
offer to clients.
|
||||
@@ -1078,6 +1082,7 @@ Available keywords are
|
||||
.Cm IPQoS ,
|
||||
.Cm KbdInteractiveAuthentication ,
|
||||
|
||||
@ -49,7 +49,7 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c
|
||||
platform_setusercontext(pw);
|
||||
|
||||
- if (platform_privileged_uidswap()) {
|
||||
+ if (platform_privileged_uidswap() && (!is_child || !use_privsep)) {
|
||||
+ if (platform_privileged_uidswap() && !is_child) {
|
||||
#ifdef HAVE_LOGIN_CAP
|
||||
if (setusercontext(lc, pw, pw->pw_uid,
|
||||
(LOGIN_SETALL & ~(LOGIN_SETPATH|LOGIN_SETUSER))) < 0) {
|
||||
@ -96,8 +96,8 @@ diff -up openssh-7.4p1/session.c.privsep-selinux openssh-7.4p1/session.c
|
||||
}
|
||||
|
||||
diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c
|
||||
--- openssh-7.4p1/sshd.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100
|
||||
+++ openssh-7.4p1/sshd.c 2016-12-23 18:59:13.808124269 +0100
|
||||
--- openssh-7.4p1/sshd-session.c.privsep-selinux 2016-12-23 18:58:52.973122201 +0100
|
||||
+++ openssh-7.4p1/sshd-session.c 2016-12-23 18:59:13.808124269 +0100
|
||||
@@ -540,6 +540,10 @@ privsep_preauth_child(void)
|
||||
/* Demote the private keys to public keys. */
|
||||
demote_sensitive_data();
|
||||
@ -109,13 +109,12 @@ diff -up openssh-7.4p1/sshd.c.privsep-selinux openssh-7.4p1/sshd.c
|
||||
/* Demote the child */
|
||||
if (privsep_chroot) {
|
||||
/* Change our root directory */
|
||||
@@ -633,6 +637,9 @@ privsep_postauth(Authctxt *authctxt)
|
||||
{
|
||||
#ifdef DISABLE_FD_PASSING
|
||||
if (1) {
|
||||
+#elif defined(WITH_SELINUX)
|
||||
+ if (0) {
|
||||
+ /* even root user can be confined by SELinux */
|
||||
#else
|
||||
if (authctxt->pw->pw_uid == 0) {
|
||||
@@ -403,7 +403,7 @@ privsep_postauth(struct ssh *ssh, Authct
|
||||
* fd passing, as AFAIK PTY allocation on this platform doesn't require
|
||||
* special privileges to begin with.
|
||||
*/
|
||||
-#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN)
|
||||
+#if defined(DISABLE_FD_PASSING) && !defined(HAVE_CYGWIN) && !defined(WITH_SELINUX)
|
||||
skip_privdrop = 1;
|
||||
#endif
|
||||
|
||||
|
||||
@ -1,37 +1,3 @@
|
||||
diff -up openssh-8.5p1/addr.c.coverity openssh-8.5p1/addr.c
|
||||
--- openssh-8.5p1/addr.c.coverity 2021-03-02 11:31:47.000000000 +0100
|
||||
+++ openssh-8.5p1/addr.c 2021-03-24 12:03:33.782968159 +0100
|
||||
@@ -312,8 +312,10 @@ addr_pton(const char *p, struct xaddr *n
|
||||
if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
|
||||
return -1;
|
||||
|
||||
- if (ai == NULL || ai->ai_addr == NULL)
|
||||
+ if (ai == NULL || ai->ai_addr == NULL) {
|
||||
+ freeaddrinfo(ai);
|
||||
return -1;
|
||||
+ }
|
||||
|
||||
if (n != NULL && addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen,
|
||||
n) == -1) {
|
||||
@@ -336,12 +338,16 @@ addr_sa_pton(const char *h, const char *
|
||||
if (h == NULL || getaddrinfo(h, s, &hints, &ai) != 0)
|
||||
return -1;
|
||||
|
||||
- if (ai == NULL || ai->ai_addr == NULL)
|
||||
+ if (ai == NULL || ai->ai_addr == NULL) {
|
||||
+ freeaddrinfo(ai);
|
||||
return -1;
|
||||
+ }
|
||||
|
||||
if (sa != NULL) {
|
||||
- if (slen < ai->ai_addrlen)
|
||||
+ if (slen < ai->ai_addrlen) {
|
||||
+ freeaddrinfo(ai);
|
||||
return -1;
|
||||
+ }
|
||||
memcpy(sa, &ai->ai_addr, ai->ai_addrlen);
|
||||
}
|
||||
|
||||
diff -up openssh-8.5p1/auth-krb5.c.coverity openssh-8.5p1/auth-krb5.c
|
||||
--- openssh-8.5p1/auth-krb5.c.coverity 2021-03-24 12:03:33.724967756 +0100
|
||||
+++ openssh-8.5p1/auth-krb5.c 2021-03-24 12:03:33.782968159 +0100
|
||||
@ -51,40 +17,6 @@ diff -up openssh-8.5p1/auth-krb5.c.coverity openssh-8.5p1/auth-krb5.c
|
||||
return oerrno;
|
||||
}
|
||||
/* make sure the KRB5CCNAME is set for non-standard location */
|
||||
diff -up openssh-8.5p1/auth-options.c.coverity openssh-8.5p1/auth-options.c
|
||||
--- openssh-8.5p1/auth-options.c.coverity 2021-03-02 11:31:47.000000000 +0100
|
||||
+++ openssh-8.5p1/auth-options.c 2021-03-24 12:03:33.782968159 +0100
|
||||
@@ -706,6 +708,7 @@ serialise_array(struct sshbuf *m, char *
|
||||
return r;
|
||||
}
|
||||
/* success */
|
||||
+ sshbuf_free(b);
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff -up openssh-7.4p1/channels.c.coverity openssh-7.4p1/channels.c
|
||||
--- openssh-7.4p1/channels.c.coverity 2016-12-23 16:40:26.881788686 +0100
|
||||
+++ openssh-7.4p1/channels.c 2016-12-23 16:42:36.244818763 +0100
|
||||
@@ -1875,7 +1875,7 @@ channel_post_connecting(struct ssh *ssh,
|
||||
debug("channel %d: connection failed: %s",
|
||||
c->self, strerror(err));
|
||||
/* Try next address, if any */
|
||||
- if ((sock = connect_next(&c->connect_ctx)) > 0) {
|
||||
+ if ((sock = connect_next(&c->connect_ctx)) >= 0) {
|
||||
close(c->sock);
|
||||
c->sock = c->rfd = c->wfd = sock;
|
||||
channel_find_maxfd(ssh->chanctxt);
|
||||
diff -up openssh-8.5p1/dns.c.coverity openssh-8.5p1/dns.c
|
||||
--- openssh-8.5p1/dns.c.coverity 2021-03-02 11:31:47.000000000 +0100
|
||||
+++ openssh-8.5p1/dns.c 2021-03-24 12:03:33.783968166 +0100
|
||||
@@ -282,6 +282,7 @@ verify_host_key_dns(const char *hostname
|
||||
&hostkey_digest, &hostkey_digest_len, hostkey)) {
|
||||
error("Error calculating key fingerprint.");
|
||||
freerrset(fingerprints);
|
||||
+ free(dnskey_digest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c
|
||||
--- openssh-8.5p1/gss-genr.c.coverity 2021-03-26 11:52:46.613942552 +0100
|
||||
+++ openssh-8.5p1/gss-genr.c 2021-03-26 11:54:37.881726318 +0100
|
||||
@ -95,21 +27,13 @@ diff -up openssh-8.5p1/gss-genr.c.coverity openssh-8.5p1/gss-genr.c
|
||||
-
|
||||
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
|
||||
cp = strncpy(s, kex, strlen(kex));
|
||||
+#pragma pop
|
||||
+#pragma GCC diagnostic pop
|
||||
for ((p = strsep(&cp, ",")); p && *p != '\0';
|
||||
(p = strsep(&cp, ","))) {
|
||||
if (sshbuf_len(buf) != 0 &&
|
||||
diff -up openssh-8.5p1/krl.c.coverity openssh-8.5p1/krl.c
|
||||
--- openssh-8.5p1/krl.c.coverity 2021-03-02 11:31:47.000000000 +0100
|
||||
+++ openssh-8.5p1/krl.c 2021-03-24 12:03:33.783968166 +0100
|
||||
@@ -1209,6 +1209,7 @@ ssh_krl_from_blob(struct sshbuf *buf, st
|
||||
sshkey_free(key);
|
||||
sshbuf_free(copy);
|
||||
sshbuf_free(sect);
|
||||
+ /* coverity[leaked_storage : FALSE] */
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -1261,6 +1262,7 @@ is_key_revoked(struct ssh_krl *krl, cons
|
||||
return r;
|
||||
erb = RB_FIND(revoked_blob_tree, &krl->revoked_sha1s, &rb);
|
||||
@ -149,22 +73,6 @@ diff -up openssh-8.5p1/loginrec.c.coverity openssh-8.5p1/loginrec.c
|
||||
strncpy(ut->ut_host, li->hostname,
|
||||
MIN_SIZEOF(ut->ut_host, li->hostname));
|
||||
# endif
|
||||
@@ -1690,6 +1692,7 @@ record_failed_login(struct ssh *ssh, con
|
||||
|
||||
memset(&ut, 0, sizeof(ut));
|
||||
/* strncpy because we don't necessarily want nul termination */
|
||||
+ /* coverity[buffer_size_warning : FALSE] */
|
||||
strncpy(ut.ut_user, username, sizeof(ut.ut_user));
|
||||
strlcpy(ut.ut_line, "ssh:notty", sizeof(ut.ut_line));
|
||||
|
||||
@@ -1699,6 +1702,7 @@ record_failed_login(struct ssh *ssh, con
|
||||
ut.ut_pid = getpid();
|
||||
|
||||
/* strncpy because we don't necessarily want nul termination */
|
||||
+ /* coverity[buffer_size_warning : FALSE] */
|
||||
strncpy(ut.ut_host, hostname, sizeof(ut.ut_host));
|
||||
|
||||
if (ssh_packet_connection_is_on_socket(ssh) &&
|
||||
diff -up openssh-8.5p1/misc.c.coverity openssh-8.5p1/misc.c
|
||||
--- openssh-8.5p1/misc.c.coverity 2021-03-24 12:03:33.745967902 +0100
|
||||
+++ openssh-8.5p1/misc.c 2021-03-24 13:31:47.037079617 +0100
|
||||
@ -185,17 +93,6 @@ diff -up openssh-8.5p1/misc.c.coverity openssh-8.5p1/misc.c
|
||||
return ret;
|
||||
}
|
||||
|
||||
diff -up openssh-8.5p1/moduli.c.coverity openssh-8.5p1/moduli.c
|
||||
--- openssh-8.5p1/moduli.c.coverity 2021-03-02 11:31:47.000000000 +0100
|
||||
+++ openssh-8.5p1/moduli.c 2021-03-24 12:03:33.784968173 +0100
|
||||
@@ -476,6 +476,7 @@ write_checkpoint(char *cpfile, u_int32_t
|
||||
else
|
||||
logit("failed to write to checkpoint file '%s': %s", cpfile,
|
||||
strerror(errno));
|
||||
+ /* coverity[leaked_storage : FALSE] */
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c
|
||||
--- openssh-7.4p1/monitor.c.coverity 2016-12-23 16:40:26.888788688 +0100
|
||||
+++ openssh-7.4p1/monitor.c 2016-12-23 16:40:26.900788691 +0100
|
||||
@ -217,23 +114,6 @@ diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c
|
||||
return (0);
|
||||
|
||||
error:
|
||||
diff -up openssh-7.4p1/monitor_wrap.c.coverity openssh-7.4p1/monitor_wrap.c
|
||||
--- openssh-7.4p1/monitor_wrap.c.coverity 2016-12-23 16:40:26.892788689 +0100
|
||||
+++ openssh-7.4p1/monitor_wrap.c 2016-12-23 16:40:26.900788691 +0100
|
||||
@@ -525,10 +525,10 @@ mm_pty_allocate(int *ptyfd, int *ttyfd,
|
||||
if ((tmp1 = dup(pmonitor->m_recvfd)) == -1 ||
|
||||
(tmp2 = dup(pmonitor->m_recvfd)) == -1) {
|
||||
error_f("cannot allocate fds for pty");
|
||||
- if (tmp1 > 0)
|
||||
+ if (tmp1 >= 0)
|
||||
close(tmp1);
|
||||
- if (tmp2 > 0)
|
||||
- close(tmp2);
|
||||
+ /*DEAD CODE if (tmp2 >= 0)
|
||||
+ close(tmp2);*/
|
||||
return 0;
|
||||
}
|
||||
close(tmp1);
|
||||
diff -up openssh-7.4p1/openbsd-compat/bindresvport.c.coverity openssh-7.4p1/openbsd-compat/bindresvport.c
|
||||
--- openssh-7.4p1/openbsd-compat/bindresvport.c.coverity 2016-12-19 05:59:41.000000000 +0100
|
||||
+++ openssh-7.4p1/openbsd-compat/bindresvport.c 2016-12-23 16:40:26.901788691 +0100
|
||||
@ -287,23 +167,6 @@ diff -up openssh-8.5p1/readconf.c.coverity openssh-8.5p1/readconf.c
|
||||
goto out;
|
||||
}
|
||||
free(arg2);
|
||||
diff -up openssh-8.7p1/scp.c.coverity openssh-8.7p1/scp.c
|
||||
--- openssh-8.7p1/scp.c.coverity 2021-08-30 16:23:35.389741329 +0200
|
||||
+++ openssh-8.7p1/scp.c 2021-08-30 16:27:04.854555296 +0200
|
||||
@@ -186,11 +186,11 @@ killchild(int signo)
|
||||
{
|
||||
if (do_cmd_pid > 1) {
|
||||
kill(do_cmd_pid, signo ? signo : SIGTERM);
|
||||
- waitpid(do_cmd_pid, NULL, 0);
|
||||
+ (void) waitpid(do_cmd_pid, NULL, 0);
|
||||
}
|
||||
if (do_cmd_pid2 > 1) {
|
||||
kill(do_cmd_pid2, signo ? signo : SIGTERM);
|
||||
- waitpid(do_cmd_pid2, NULL, 0);
|
||||
+ (void) waitpid(do_cmd_pid2, NULL, 0);
|
||||
}
|
||||
|
||||
if (signo)
|
||||
diff -up openssh-7.4p1/servconf.c.coverity openssh-7.4p1/servconf.c
|
||||
--- openssh-7.4p1/servconf.c.coverity 2016-12-23 16:40:26.896788690 +0100
|
||||
+++ openssh-7.4p1/servconf.c 2016-12-23 16:40:26.901788691 +0100
|
||||
@ -331,87 +194,6 @@ diff -up openssh-8.7p1/serverloop.c.coverity openssh-8.7p1/serverloop.c
|
||||
if (tun != SSH_TUNID_ANY &&
|
||||
auth_opts->force_tun_device != (int)tun)
|
||||
goto done;
|
||||
diff -up openssh-8.5p1/session.c.coverity openssh-8.5p1/session.c
|
||||
--- openssh-8.5p1/session.c.coverity 2021-03-24 12:03:33.777968124 +0100
|
||||
+++ openssh-8.5p1/session.c 2021-03-24 12:03:33.786968187 +0100
|
||||
@@ -1223,12 +1223,14 @@ do_setup_env(struct ssh *ssh, Session *s
|
||||
/* Environment specified by admin */
|
||||
for (i = 0; i < options.num_setenv; i++) {
|
||||
cp = xstrdup(options.setenv[i]);
|
||||
+ /* coverity[overwrite_var : FALSE] */
|
||||
if ((value = strchr(cp, '=')) == NULL) {
|
||||
/* shouldn't happen; vars are checked in servconf.c */
|
||||
fatal("Invalid config SetEnv: %s", options.setenv[i]);
|
||||
}
|
||||
*value++ = '\0';
|
||||
child_set_env(&env, &envsize, cp, value);
|
||||
+ free(cp);
|
||||
}
|
||||
|
||||
/* SSH_CLIENT deprecated */
|
||||
--- a/sftp.c 2022-06-30 10:43:13.914058913 +0200
|
||||
+++ b/sftp.c 2022-06-30 10:48:17.243997888 +0200
|
||||
@@ -222,7 +222,7 @@ killchild(int signo)
|
||||
pid = sshpid;
|
||||
if (pid > 1) {
|
||||
kill(pid, SIGTERM);
|
||||
- waitpid(pid, NULL, 0);
|
||||
+ (void) waitpid(pid, NULL, 0);
|
||||
}
|
||||
|
||||
_exit(1);
|
||||
@@ -768,6 +768,8 @@ process_put(struct sftp_conn *conn, cons
|
||||
fflag || global_fflag, 0) == -1)
|
||||
err = -1;
|
||||
}
|
||||
+ free(abs_dst);
|
||||
+ abs_dst = NULL;
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -991,6 +993,7 @@ do_globbed_ls(struct sftp_conn *conn, co
|
||||
if (lflag & LS_LONG_VIEW) {
|
||||
if (g.gl_statv[i] == NULL) {
|
||||
error("no stat information for %s", fname);
|
||||
+ free(fname);
|
||||
continue;
|
||||
}
|
||||
lname = ls_file(fname, g.gl_statv[i], 1,
|
||||
diff --git a/sftp-client.c b/sftp-client.c
|
||||
index 9de9afa20f..ea98d9f8d0 100644
|
||||
--- a/sftp-client.c
|
||||
+++ b/sftp-client.c
|
||||
@@ -2195,6 +2195,7 @@ handle_dest_replies(struct sftp_conn *to, const char *to_path, int synchronous,
|
||||
(*nreqsp)--;
|
||||
}
|
||||
debug3_f("done: %u outstanding replies", *nreqsp);
|
||||
+ sshbuf_free(msg);
|
||||
}
|
||||
|
||||
int
|
||||
diff --git a/sftp-server.c b/sftp-server.c
|
||||
index 18d1949112..6380c4dd23 100644
|
||||
--- a/sftp-server.c
|
||||
+++ b/sftp-server.c
|
||||
@@ -1553,6 +1553,7 @@ process_extended_expand(u_int32_t id)
|
||||
npath = xstrdup(path + 2);
|
||||
free(path);
|
||||
xasprintf(&path, "%s/%s", cwd, npath);
|
||||
+ free(npath);
|
||||
} else {
|
||||
/* ~user expansions */
|
||||
if (tilde_expand(path, pw->pw_uid, &npath) != 0) {
|
||||
diff -up openssh-8.5p1/sk-usbhid.c.coverity openssh-8.5p1/sk-usbhid.c
|
||||
--- openssh-8.5p1/sk-usbhid.c.coverity 2021-03-02 11:31:47.000000000 +0100
|
||||
+++ openssh-8.5p1/sk-usbhid.c 2021-03-24 12:03:33.786968187 +0100
|
||||
@@ -1256,6 +1256,7 @@ sk_load_resident_keys(const char *pin, s
|
||||
freezero(rks[i], sizeof(*rks[i]));
|
||||
}
|
||||
free(rks);
|
||||
+ free(device);
|
||||
return ret;
|
||||
}
|
||||
|
||||
diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c
|
||||
--- openssh-7.4p1/ssh-agent.c.coverity 2016-12-19 05:59:41.000000000 +0100
|
||||
+++ openssh-7.4p1/ssh-agent.c 2016-12-23 16:40:26.903788691 +0100
|
||||
@ -423,31 +205,9 @@ diff -up openssh-7.4p1/ssh-agent.c.coverity openssh-7.4p1/ssh-agent.c
|
||||
return NULL;
|
||||
}
|
||||
/* validate also provider from URI */
|
||||
@@ -1220,8 +1220,8 @@ main(int ac, char **av)
|
||||
sanitise_stdfd();
|
||||
|
||||
/* drop */
|
||||
- setegid(getgid());
|
||||
- setgid(getgid());
|
||||
+ (void) setegid(getgid());
|
||||
+ (void) setgid(getgid());
|
||||
|
||||
platform_disable_tracing(0); /* strict=no */
|
||||
|
||||
diff -up openssh-8.5p1/ssh.c.coverity openssh-8.5p1/ssh.c
|
||||
--- openssh-8.5p1/ssh.c.coverity 2021-03-24 12:03:33.779968138 +0100
|
||||
+++ openssh-8.5p1/ssh.c 2021-03-24 12:03:33.786968187 +0100
|
||||
@@ -1746,6 +1746,7 @@ control_persist_detach(void)
|
||||
close(muxserver_sock);
|
||||
muxserver_sock = -1;
|
||||
options.control_master = SSHCTL_MASTER_NO;
|
||||
+ /* coverity[leaked_handle: FALSE]*/
|
||||
muxclient(options.control_path);
|
||||
/* muxclient() doesn't return on success. */
|
||||
fatal("Failed to connect to new control master");
|
||||
diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c
|
||||
--- openssh-7.4p1/sshd.c.coverity 2016-12-23 16:40:26.897788690 +0100
|
||||
+++ openssh-7.4p1/sshd.c 2016-12-23 16:40:26.904788692 +0100
|
||||
diff -up openssh-7.4p1/sshd-session.c.coverity openssh-7.4p1/sshd-session.c
|
||||
--- openssh-7.4p1/sshd-session.c.coverity 2016-12-23 16:40:26.897788690 +0100
|
||||
+++ openssh-7.4p1/sshd-session.c 2016-12-23 16:40:26.904788692 +0100
|
||||
@@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt)
|
||||
|
||||
privsep_preauth_child(ssh);
|
||||
@ -460,16 +220,6 @@ diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1386,6 +1388,9 @@ server_accept_loop(int *sock_in, int *so
|
||||
explicit_bzero(rnd, sizeof(rnd));
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (fdset != NULL)
|
||||
+ free(fdset);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2519,8 +2524,11 @@ do_ssh2_kex(struct ssh *ssh)
|
||||
|
||||
if (newstr)
|
||||
@ -496,32 +246,3 @@ diff -up openssh-8.5p1/ssh-keygen.c.coverity openssh-8.5p1/ssh-keygen.c
|
||||
} else {
|
||||
if (strncasecmp(cp, "key:", 4) == 0) {
|
||||
cp += 4;
|
||||
@@ -2879,6 +2882,7 @@ do_moduli_screen(const char *out_file, c
|
||||
} else if (strncmp(opts[i], "start-line=", 11) == 0) {
|
||||
start_lineno = strtoul(opts[i]+11, NULL, 10);
|
||||
} else if (strncmp(opts[i], "checkpoint=", 11) == 0) {
|
||||
+ free(checkpoint);
|
||||
checkpoint = xstrdup(opts[i]+11);
|
||||
} else if (strncmp(opts[i], "generator=", 10) == 0) {
|
||||
generator_wanted = (u_int32_t)strtonum(
|
||||
@@ -2920,6 +2924,9 @@ do_moduli_screen(const char *out_file, c
|
||||
#else /* WITH_OPENSSL */
|
||||
fatal("Moduli screening is not supported");
|
||||
#endif /* WITH_OPENSSL */
|
||||
+ free(checkpoint);
|
||||
+ if (in != stdin)
|
||||
+ fclose(in);
|
||||
}
|
||||
|
||||
static char *
|
||||
diff -up openssh-8.5p1/sshsig.c.coverity openssh-8.5p1/sshsig.c
|
||||
--- openssh-8.5p1/sshsig.c.coverity 2021-03-02 11:31:47.000000000 +0100
|
||||
+++ openssh-8.5p1/sshsig.c 2021-03-24 12:03:33.787968194 +0100
|
||||
@@ -515,6 +515,7 @@ hash_file(int fd, const char *hashalg, s
|
||||
oerrno = errno;
|
||||
error_f("read: %s", strerror(errno));
|
||||
ssh_digest_free(ctx);
|
||||
+ ctx = NULL;
|
||||
errno = oerrno;
|
||||
r = SSH_ERR_SYSTEM_ERROR;
|
||||
goto out;
|
||||
|
||||
@ -109,7 +109,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
|
||||
@@ -717,6 +728,8 @@ do_exec(Session *s, const char *command)
|
||||
}
|
||||
if (s->command != NULL && s->ptyfd == -1)
|
||||
s->command_handle = PRIVSEP(audit_run_command(ssh, s->command));
|
||||
s->command_handle = mm_audit_run_command(ssh, s->command);
|
||||
+ if (pipe(paudit) < 0)
|
||||
+ fatal("pipe: %s", strerror(errno));
|
||||
#endif
|
||||
@ -121,7 +121,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
|
||||
|
||||
+#ifdef SSH_AUDIT_EVENTS
|
||||
+ close(paudit[1]);
|
||||
+ if (use_privsep && ret == 0) {
|
||||
+ if (ret == 0) {
|
||||
+ /*
|
||||
+ * Read the audit messages from forked child and send them
|
||||
+ * back to monitor. We don't want to communicate directly,
|
||||
@ -136,7 +136,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1538,6 +1565,34 @@ child_close_fds(void)
|
||||
@@ -1538,6 +1565,33 @@ child_close_fds(void)
|
||||
log_redirect_stderr_to(NULL);
|
||||
}
|
||||
|
||||
@ -147,12 +147,11 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
|
||||
+ int pparent = paudit[1];
|
||||
+ close(paudit[0]);
|
||||
+ /* Hack the monitor pipe to avoid race condition with parent */
|
||||
+ if (use_privsep)
|
||||
+ mm_set_monitor_pipe(pparent);
|
||||
+ mm_set_monitor_pipe(pparent);
|
||||
+#endif
|
||||
+
|
||||
+ /* remove hostkey from the child's memory */
|
||||
+ destroy_sensitive_data(ssh, use_privsep);
|
||||
+ destroy_sensitive_data(ssh);
|
||||
+ /*
|
||||
+ * We can audit this, because we hacked the pipe to direct the
|
||||
+ * messages over postauth child. But this message requires answer
|
||||
@ -176,7 +175,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c
|
||||
sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id));
|
||||
|
||||
- /* remove hostkey from the child's memory */
|
||||
- destroy_sensitive_data(ssh, 1);
|
||||
- destroy_sensitive_data(ssh);
|
||||
- ssh_packet_clear_keys(ssh);
|
||||
- /* Don't audit this - both us and the parent would be talking to the
|
||||
- monitor over a single socket, with no synchronization. */
|
||||
|
||||
@ -1,21 +1,23 @@
|
||||
diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c
|
||||
--- openssh-7.2p2/channels.c.x11 2016-03-09 19:04:48.000000000 +0100
|
||||
+++ openssh-7.2p2/channels.c 2016-06-03 10:42:04.775164520 +0200
|
||||
@@ -3990,21 +3990,24 @@ x11_create_display_inet(int x11_display_
|
||||
diff --git a/channels.c b/channels.c
|
||||
--- a/channels.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||
+++ b/channels.c (date 1703026069921)
|
||||
@@ -5075,11 +5075,13 @@
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
-connect_local_xsocket_path(const char *pathname)
|
||||
+connect_local_xsocket_path(const char *pathname, int len)
|
||||
{
|
||||
int sock;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
|
||||
+ if (len <= 0)
|
||||
+ return -1;
|
||||
sock = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (sock == -1)
|
||||
if (sock == -1) {
|
||||
error("socket: %.100s", strerror(errno));
|
||||
@@ -5087,11 +5089,12 @@
|
||||
}
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
- strlcpy(addr.sun_path, pathname, sizeof addr.sun_path);
|
||||
@ -29,8 +31,8 @@ diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c
|
||||
- error("connect %.100s: %.100s", addr.sun_path, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -4012,8 +4015,18 @@ static int
|
||||
|
||||
@@ -5099,8 +5102,18 @@
|
||||
connect_local_xsocket(u_int dnr)
|
||||
{
|
||||
char buf[1024];
|
||||
|
||||
@ -2,7 +2,7 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c
|
||||
--- openssh-7.4p1/channels.c.x11max 2016-12-23 15:46:32.071506625 +0100
|
||||
+++ openssh-7.4p1/channels.c 2016-12-23 15:46:32.139506636 +0100
|
||||
@@ -152,8 +152,8 @@ static int all_opens_permitted = 0;
|
||||
#define FWD_PERMIT_ANY_HOST "*"
|
||||
#define NUM_SOCKS 10
|
||||
|
||||
/* -- X11 forwarding */
|
||||
-/* Maximum number of fake X11 displays to try. */
|
||||
@ -10,8 +10,8 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c
|
||||
+/* Minimum port number for X11 forwarding */
|
||||
+#define X11_PORT_MIN 6000
|
||||
|
||||
/* Per-channel callback for pre/post select() actions */
|
||||
typedef void chan_fn(struct ssh *, Channel *c,
|
||||
/* Per-channel callback for pre/post IO actions */
|
||||
typedef void chan_fn(struct ssh *, Channel *c);
|
||||
@@ -4228,7 +4228,7 @@ channel_send_window_changes(void)
|
||||
*/
|
||||
int
|
||||
@ -82,7 +82,7 @@ diff -up openssh-7.4p1/channels.h.x11max openssh-7.4p1/channels.h
|
||||
+++ openssh-7.4p1/channels.h 2016-12-23 15:46:32.139506636 +0100
|
||||
@@ -293,7 +293,7 @@ int permitopen_port(const char *);
|
||||
|
||||
void channel_set_x11_refuse_time(struct ssh *, u_int);
|
||||
void channel_set_x11_refuse_time(struct ssh *, time_t);
|
||||
int x11_connect_display(struct ssh *);
|
||||
-int x11_create_display_inet(struct ssh *, int, int, int, u_int *, int **);
|
||||
+int x11_create_display_inet(struct ssh *, int, int, int, int, u_int *, int **);
|
||||
@ -110,9 +110,9 @@ diff -up openssh-7.4p1/servconf.c.x11max openssh-7.4p1/servconf.c
|
||||
options->x11_use_localhost = 1;
|
||||
if (options->xauth_location == NULL)
|
||||
@@ -419,7 +422,7 @@ typedef enum {
|
||||
sPasswordAuthentication, sKbdInteractiveAuthentication,
|
||||
sListenAddress, sAddressFamily,
|
||||
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
|
||||
sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sPasswordAuthentication,
|
||||
sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
|
||||
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
|
||||
- sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
|
||||
+ sX11Forwarding, sX11DisplayOffset, sX11MaxDisplays, sX11UseLocalhost,
|
||||
sPermitTTY, sStrictModes, sEmptyPasswd, sTCPKeepAlive,
|
||||
@ -191,8 +191,8 @@ diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5
|
||||
--- openssh-7.4p1/sshd_config.5.x11max 2016-12-23 15:46:32.134506635 +0100
|
||||
+++ openssh-7.4p1/sshd_config.5 2016-12-23 15:46:32.141506636 +0100
|
||||
@@ -1133,6 +1133,7 @@ Available keywords are
|
||||
.Cm StreamLocalBindUnlink ,
|
||||
.Cm TrustedUserCAKeys ,
|
||||
.Cm UnusedConnectionTimeout ,
|
||||
.Cm X11DisplayOffset ,
|
||||
+.Cm X11MaxDisplays ,
|
||||
.Cm X11Forwarding
|
||||
|
||||
@ -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);
|
||||
@ -21,7 +21,7 @@ index ca75cc7..6e7de31 100644
|
||||
+ SC_ALLOW(__NR_flock),
|
||||
+#endif
|
||||
#ifdef __NR_futex
|
||||
SC_ALLOW(__NR_futex),
|
||||
SC_FUTEX(__NR_futex),
|
||||
#endif
|
||||
@@ -178,6 +181,9 @@ static const struct sock_filter preauth_insns[] = {
|
||||
#ifdef __NR_gettimeofday
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c
|
||||
--- openssh-8.6p1/audit-bsm.c.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/audit-bsm.c 2021-05-06 12:05:27.376464524 +0200
|
||||
+++ openssh-8.6p1/audit-bsm.c 2021-04-19 16:47:35.753062106 +0200
|
||||
@@ -373,13 +373,26 @@ audit_connection_from(const char *host,
|
||||
#endif
|
||||
}
|
||||
@ -73,7 +73,7 @@ diff -up openssh-8.6p1/audit-bsm.c.audit openssh-8.6p1/audit-bsm.c
|
||||
#endif /* BSM */
|
||||
diff -up openssh-8.6p1/audit.c.audit openssh-8.6p1/audit.c
|
||||
--- openssh-8.6p1/audit.c.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/audit.c 2021-05-06 12:05:27.376464524 +0200
|
||||
+++ openssh-8.6p1/audit.c 2021-04-19 16:47:35.753062106 +0200
|
||||
@@ -34,6 +34,12 @@
|
||||
#include "log.h"
|
||||
#include "hostfile.h"
|
||||
@ -129,19 +129,19 @@ diff -up openssh-8.6p1/audit.c.audit openssh-8.6p1/audit.c
|
||||
+void
|
||||
+audit_unsupported(struct ssh *ssh, int what)
|
||||
+{
|
||||
+ PRIVSEP(audit_unsupported_body(ssh, what));
|
||||
+ mm_audit_unsupported_body(ssh, what);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs)
|
||||
+{
|
||||
+ PRIVSEP(audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid()));
|
||||
+ mm_audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid());
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+audit_session_key_free(struct ssh *ssh, int ctos)
|
||||
+{
|
||||
+ PRIVSEP(audit_session_key_free_body(ssh, ctos, getpid(), getuid()));
|
||||
+ mm_audit_session_key_free_body(ssh, ctos, getpid(), getuid());
|
||||
+}
|
||||
+
|
||||
# ifndef CUSTOM_SSH_AUDIT_EVENTS
|
||||
@ -253,7 +253,7 @@ diff -up openssh-8.6p1/audit.c.audit openssh-8.6p1/audit.c
|
||||
#endif /* SSH_AUDIT_EVENTS */
|
||||
diff -up openssh-8.6p1/audit.h.audit openssh-8.6p1/audit.h
|
||||
--- openssh-8.6p1/audit.h.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/audit.h 2021-05-06 12:05:27.376464524 +0200
|
||||
+++ openssh-8.6p1/audit.h 2021-04-19 16:47:35.753062106 +0200
|
||||
@@ -26,6 +26,7 @@
|
||||
# define _SSH_AUDIT_H
|
||||
|
||||
@ -298,7 +298,7 @@ diff -up openssh-8.6p1/audit.h.audit openssh-8.6p1/audit.h
|
||||
#endif /* _SSH_AUDIT_H */
|
||||
diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c
|
||||
--- openssh-8.6p1/audit-linux.c.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/audit-linux.c 2021-05-06 12:05:27.377464532 +0200
|
||||
+++ openssh-8.6p1/audit-linux.c 2021-04-19 16:47:35.753062106 +0200
|
||||
@@ -33,27 +33,40 @@
|
||||
|
||||
#include "log.h"
|
||||
@ -446,7 +446,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c
|
||||
/* Below is the sshd audit API code */
|
||||
|
||||
void
|
||||
@@ -76,49 +176,210 @@ audit_connection_from(const char *host,
|
||||
@@ -76,49 +176,211 @@ audit_connection_from(const char *host,
|
||||
/* not implemented */
|
||||
}
|
||||
|
||||
@ -525,6 +525,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c
|
||||
case SSH_AUTH_FAIL_PASSWD:
|
||||
+ if (options.use_pam)
|
||||
+ break;
|
||||
+ /* Fallthrough */
|
||||
+ case SSH_LOGIN_EXCEED_MAXTRIES:
|
||||
case SSH_AUTH_FAIL_KBDINT:
|
||||
case SSH_AUTH_FAIL_PUBKEY:
|
||||
@ -564,7 +565,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c
|
||||
+{
|
||||
+#ifdef AUDIT_CRYPTO_SESSION
|
||||
+ char buf[AUDIT_LOG_SIZE];
|
||||
+ const static char *name[] = { "cipher", "mac", "comp" };
|
||||
+ static const char *name[] = { "cipher", "mac", "comp" };
|
||||
+ char *s;
|
||||
+ int audit_fd;
|
||||
+
|
||||
@ -582,7 +583,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
+const static char *direction[] = { "from-server", "from-client", "both" };
|
||||
+static const char *direction[] = { "from-server", "from-client", "both" };
|
||||
+
|
||||
+void
|
||||
+audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress,
|
||||
@ -661,7 +662,7 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c
|
||||
+ }
|
||||
+ audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER,
|
||||
+ buf, NULL,
|
||||
+ listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh),
|
||||
+ ssh_remote_ipaddr(ssh), /*FIXME listening_for_clients() ? NULL : ssh_remote_ipaddr(ssh) */
|
||||
+ NULL, 1);
|
||||
+ audit_close(audit_fd);
|
||||
+ /* do not abort if the error is EPERM and sshd is run as non root user */
|
||||
@ -670,8 +671,8 @@ diff -up openssh-8.6p1/audit-linux.c.audit openssh-8.6p1/audit-linux.c
|
||||
+}
|
||||
#endif /* USE_LINUX_AUDIT */
|
||||
diff -up openssh-8.6p1/auditstub.c.audit openssh-8.6p1/auditstub.c
|
||||
--- openssh-8.6p1/auditstub.c.audit 2021-05-06 12:05:27.377464532 +0200
|
||||
+++ openssh-8.6p1/auditstub.c 2021-05-06 12:05:27.377464532 +0200
|
||||
--- openssh-8.6p1/auditstub.c.audit 2021-04-19 16:47:35.754062114 +0200
|
||||
+++ openssh-8.6p1/auditstub.c 2021-04-19 16:47:35.754062114 +0200
|
||||
@@ -0,0 +1,52 @@
|
||||
+/* $Id: auditstub.c,v 1.1 jfch Exp $ */
|
||||
+
|
||||
@ -726,28 +727,28 @@ diff -up openssh-8.6p1/auditstub.c.audit openssh-8.6p1/auditstub.c
|
||||
+{
|
||||
+}
|
||||
diff -up openssh-8.6p1/auth2.c.audit openssh-8.6p1/auth2.c
|
||||
--- openssh-8.6p1/auth2.c.audit 2021-05-06 12:05:27.305463975 +0200
|
||||
+++ openssh-8.6p1/auth2.c 2021-05-06 12:05:27.377464532 +0200
|
||||
--- openssh-8.6p1/auth2.c.audit 2021-04-19 16:47:35.682061561 +0200
|
||||
+++ openssh-8.6p1/auth2.c 2021-04-19 16:47:35.754062114 +0200
|
||||
@@ -298,9 +298,6 @@ input_userauth_request(int type, u_int32
|
||||
} else {
|
||||
authctxt->valid = 0;
|
||||
/* Invalid user, fake password information */
|
||||
authctxt->pw = fakepw();
|
||||
-#ifdef SSH_AUDIT_EVENTS
|
||||
- PRIVSEP(audit_event(ssh, SSH_INVALID_USER));
|
||||
- mm_audit_event(ssh, SSH_INVALID_USER);
|
||||
-#endif
|
||||
}
|
||||
#ifdef USE_PAM
|
||||
if (options.use_pam)
|
||||
diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c
|
||||
--- openssh-8.6p1/auth2-hostbased.c.audit 2021-05-06 12:05:27.283463805 +0200
|
||||
+++ openssh-8.6p1/auth2-hostbased.c 2021-05-06 12:05:27.377464532 +0200
|
||||
--- openssh-8.6p1/auth2-hostbased.c.audit 2021-04-19 16:47:35.656061361 +0200
|
||||
+++ openssh-8.6p1/auth2-hostbased.c 2021-04-19 16:47:35.754062114 +0200
|
||||
@@ -158,7 +158,7 @@ userauth_hostbased(struct ssh *ssh)
|
||||
authenticated = 0;
|
||||
if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser,
|
||||
chost, key)) &&
|
||||
- PRIVSEP(sshkey_verify(key, sig, slen,
|
||||
+ PRIVSEP(hostbased_key_verify(ssh, key, sig, slen,
|
||||
sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0)
|
||||
if (mm_hostbased_key_allowed(ssh, authctxt->pw, cuser,
|
||||
chost, key) &&
|
||||
- mm_sshkey_verify(key, sig, slen,
|
||||
+ mm_hostbased_key_verify(ssh, key, sig, slen,
|
||||
sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL) == 0)
|
||||
authenticated = 1;
|
||||
|
||||
@@ -175,6 +175,20 @@ done:
|
||||
@ -772,17 +773,17 @@ diff -up openssh-8.6p1/auth2-hostbased.c.audit openssh-8.6p1/auth2-hostbased.c
|
||||
int
|
||||
hostbased_key_allowed(struct ssh *ssh, struct passwd *pw,
|
||||
diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c
|
||||
--- openssh-8.6p1/auth2-pubkey.c.audit 2021-05-06 12:05:27.344464277 +0200
|
||||
+++ openssh-8.6p1/auth2-pubkey.c 2021-05-06 12:05:27.378464540 +0200
|
||||
--- openssh-8.6p1/auth2-pubkey.c.audit 2021-04-19 16:47:35.726061899 +0200
|
||||
+++ openssh-8.6p1/auth2-pubkey.c 2021-04-19 16:47:35.754062114 +0200
|
||||
@@ -213,7 +213,7 @@ userauth_pubkey(struct ssh *ssh)
|
||||
/* test for correct signature */
|
||||
authenticated = 0;
|
||||
if (PRIVSEP(user_key_allowed(ssh, pw, key, 1, &authopts)) &&
|
||||
- PRIVSEP(sshkey_verify(key, sig, slen,
|
||||
+ PRIVSEP(user_key_verify(ssh, key, sig, slen,
|
||||
if (mm_user_key_allowed(ssh, pw, key, 1, &authopts) &&
|
||||
- mm_sshkey_verify(key, sig, slen,
|
||||
+ mm_user_key_verify(ssh, key, sig, slen,
|
||||
sshbuf_ptr(b), sshbuf_len(b),
|
||||
(ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL,
|
||||
ssh->compat, &sig_details)) == 0) {
|
||||
ssh->compat, &sig_details) == 0) {
|
||||
@@ -305,6 +305,20 @@ done:
|
||||
return authenticated;
|
||||
}
|
||||
@ -802,11 +803,11 @@ diff -up openssh-8.6p1/auth2-pubkey.c.audit openssh-8.6p1/auth2-pubkey.c
|
||||
+}
|
||||
+
|
||||
static int
|
||||
match_principals_option(const char *principal_list, struct sshkey_cert *cert)
|
||||
{
|
||||
match_principals_file(struct passwd *pw, char *file,
|
||||
struct sshkey_cert *cert, struct sshauthopt **authoptsp)
|
||||
diff -up openssh-8.6p1/auth.c.audit openssh-8.6p1/auth.c
|
||||
--- openssh-8.6p1/auth.c.audit 2021-05-06 12:05:27.304463967 +0200
|
||||
+++ openssh-8.6p1/auth.c 2021-05-06 12:05:27.378464540 +0200
|
||||
--- openssh-8.6p1/auth.c.audit 2021-04-19 16:47:35.681061553 +0200
|
||||
+++ openssh-8.6p1/auth.c 2021-04-19 16:47:35.754062114 +0200
|
||||
@@ -597,9 +597,6 @@ getpwnamallow(struct ssh *ssh, const cha
|
||||
record_failed_login(ssh, user,
|
||||
auth_get_canonical_hostname(ssh, options.use_dns), "ssh");
|
||||
@ -818,17 +819,8 @@ diff -up openssh-8.6p1/auth.c.audit openssh-8.6p1/auth.c
|
||||
}
|
||||
if (!allowed_user(ssh, pw))
|
||||
diff -up openssh-8.6p1/auth.h.audit openssh-8.6p1/auth.h
|
||||
--- openssh-8.6p1/auth.h.audit 2021-05-06 12:05:27.318464076 +0200
|
||||
+++ openssh-8.6p1/auth.h 2021-05-06 12:05:27.378464540 +0200
|
||||
@@ -193,6 +193,8 @@ struct passwd * getpwnamallow(struct ssh
|
||||
|
||||
char *expand_authorized_keys(const char *, struct passwd *pw);
|
||||
char *authorized_principals_file(struct passwd *);
|
||||
+int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t,
|
||||
+ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
|
||||
|
||||
FILE *auth_openkeyfile(const char *, struct passwd *, int);
|
||||
FILE *auth_openprincipals(const char *, struct passwd *, int);
|
||||
--- openssh-8.6p1/auth.h.audit 2021-04-19 16:47:35.697061676 +0200
|
||||
+++ openssh-8.6p1/auth.h 2021-04-19 16:47:35.754062114 +0200
|
||||
@@ -212,6 +214,8 @@ struct sshkey *get_hostkey_private_by_ty
|
||||
int get_hostkey_index(struct sshkey *, int, struct ssh *);
|
||||
int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *,
|
||||
@ -837,10 +829,19 @@ diff -up openssh-8.6p1/auth.h.audit openssh-8.6p1/auth.h
|
||||
+ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
|
||||
|
||||
/* Key / cert options linkage to auth layer */
|
||||
const struct sshauthopt *auth_options(struct ssh *);
|
||||
int auth_activate_options(struct ssh *, struct sshauthopt *);
|
||||
@@ -239,6 +241,8 @@ struct passwd * getpwnamallow(struct ssh
|
||||
char *, const char *, const char *, const char *, struct sshauthopt **);
|
||||
int auth_check_authkeys_file(struct passwd *, FILE *, char *,
|
||||
struct sshkey *, const char *, const char *, struct sshauthopt **);
|
||||
+int user_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t,
|
||||
+ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
|
||||
FILE *auth_openkeyfile(const char *, struct passwd *, int);
|
||||
FILE *auth_openprincipals(const char *, struct passwd *, int);
|
||||
|
||||
diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c
|
||||
--- openssh-8.6p1/cipher.c.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/cipher.c 2021-05-06 12:05:27.378464540 +0200
|
||||
+++ openssh-8.6p1/cipher.c 2021-04-19 16:47:35.755062122 +0200
|
||||
@@ -64,25 +64,6 @@ struct sshcipher_ctx {
|
||||
const struct sshcipher *cipher;
|
||||
};
|
||||
@ -878,7 +879,7 @@ diff -up openssh-8.6p1/cipher.c.audit openssh-8.6p1/cipher.c
|
||||
chachapoly_free(cc->cp_ctx);
|
||||
diff -up openssh-8.6p1/cipher.h.audit openssh-8.6p1/cipher.h
|
||||
--- openssh-8.6p1/cipher.h.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/cipher.h 2021-05-06 12:05:27.378464540 +0200
|
||||
+++ openssh-8.6p1/cipher.h 2021-04-19 16:47:35.755062122 +0200
|
||||
@@ -47,7 +47,25 @@
|
||||
#define CIPHER_ENCRYPT 1
|
||||
#define CIPHER_DECRYPT 0
|
||||
@ -907,16 +908,16 @@ diff -up openssh-8.6p1/cipher.h.audit openssh-8.6p1/cipher.h
|
||||
|
||||
const struct sshcipher *cipher_by_name(const char *);
|
||||
diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c
|
||||
--- openssh-8.6p1/kex.c.audit 2021-05-06 12:05:27.368464462 +0200
|
||||
+++ openssh-8.6p1/kex.c 2021-05-06 12:05:27.379464547 +0200
|
||||
--- openssh-8.6p1/kex.c.audit 2021-04-19 16:47:35.743062030 +0200
|
||||
+++ openssh-8.6p1/kex.c 2021-04-19 16:47:35.755062122 +0200
|
||||
@@ -65,6 +65,7 @@
|
||||
#include "ssherr.h"
|
||||
#include "sshbuf.h"
|
||||
#include "digest.h"
|
||||
#include "xmalloc.h"
|
||||
+#include "audit.h"
|
||||
|
||||
#ifdef GSSAPI
|
||||
#include "ssh-gss.h"
|
||||
/* prototype */
|
||||
static int kex_choose_conf(struct ssh *, uint32_t seq);
|
||||
@@ -816,12 +817,16 @@ kex_start_rekex(struct ssh *ssh)
|
||||
}
|
||||
|
||||
@ -1036,8 +1037,8 @@ diff -up openssh-8.6p1/kex.c.audit openssh-8.6p1/kex.c
|
||||
* Send a plaintext error message to the peer, suffixed by \r\n.
|
||||
* Only used during banner exchange, and there only for the server.
|
||||
diff -up openssh-8.6p1/kex.h.audit openssh-8.6p1/kex.h
|
||||
--- openssh-8.6p1/kex.h.audit 2021-05-06 12:05:27.306463983 +0200
|
||||
+++ openssh-8.6p1/kex.h 2021-05-06 12:05:27.379464547 +0200
|
||||
--- openssh-8.6p1/kex.h.audit 2021-04-19 16:47:35.683061568 +0200
|
||||
+++ openssh-8.6p1/kex.h 2021-04-19 16:47:35.756062129 +0200
|
||||
@@ -226,6 +226,8 @@ int kexgss_client(struct ssh *);
|
||||
int kexgss_server(struct ssh *);
|
||||
#endif
|
||||
@ -1049,7 +1050,7 @@ diff -up openssh-8.6p1/kex.h.audit openssh-8.6p1/kex.h
|
||||
struct sshbuf **);
|
||||
diff -up openssh-8.6p1/mac.c.audit openssh-8.6p1/mac.c
|
||||
--- openssh-8.6p1/mac.c.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/mac.c 2021-05-06 12:05:27.379464547 +0200
|
||||
+++ openssh-8.6p1/mac.c 2021-04-19 16:47:35.756062129 +0200
|
||||
@@ -239,6 +239,20 @@ mac_clear(struct sshmac *mac)
|
||||
mac->umac_ctx = NULL;
|
||||
}
|
||||
@ -1073,7 +1074,7 @@ diff -up openssh-8.6p1/mac.c.audit openssh-8.6p1/mac.c
|
||||
int
|
||||
diff -up openssh-8.6p1/mac.h.audit openssh-8.6p1/mac.h
|
||||
--- openssh-8.6p1/mac.h.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/mac.h 2021-05-06 12:05:27.379464547 +0200
|
||||
+++ openssh-8.6p1/mac.h 2021-04-19 16:47:35.756062129 +0200
|
||||
@@ -49,5 +49,6 @@ int mac_compute(struct sshmac *, u_int3
|
||||
int mac_check(struct sshmac *, u_int32_t, const u_char *, size_t,
|
||||
const u_char *, size_t);
|
||||
@ -1082,10 +1083,10 @@ diff -up openssh-8.6p1/mac.h.audit openssh-8.6p1/mac.h
|
||||
|
||||
#endif /* SSHMAC_H */
|
||||
diff -up openssh-8.6p1/Makefile.in.audit openssh-8.6p1/Makefile.in
|
||||
--- openssh-8.6p1/Makefile.in.audit 2021-05-06 12:05:27.352464339 +0200
|
||||
+++ openssh-8.6p1/Makefile.in 2021-05-06 12:05:27.380464555 +0200
|
||||
--- openssh-8.6p1/Makefile.in.audit 2021-04-19 16:47:35.731061937 +0200
|
||||
+++ openssh-8.6p1/Makefile.in 2021-04-19 16:47:35.756062129 +0200
|
||||
@@ -112,7 +112,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
|
||||
kexsntrup761x25519.o sntrup761.o kexgen.o \
|
||||
kexsntrup761x25519.o kexmlkem768x25519.o sntrup761.o kexgen.o \
|
||||
kexgssc.o \
|
||||
sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \
|
||||
- sshbuf-io.o
|
||||
@ -1094,8 +1095,8 @@ diff -up openssh-8.6p1/Makefile.in.audit openssh-8.6p1/Makefile.in
|
||||
SKOBJS= ssh-sk-client.o
|
||||
|
||||
diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c
|
||||
--- openssh-8.6p1/monitor.c.audit 2021-05-06 12:05:27.326464138 +0200
|
||||
+++ openssh-8.6p1/monitor.c 2021-05-06 12:05:27.380464555 +0200
|
||||
--- openssh-8.6p1/monitor.c.audit 2021-04-19 16:47:35.707061753 +0200
|
||||
+++ openssh-8.6p1/monitor.c 2021-04-19 16:47:35.756062129 +0200
|
||||
@@ -93,6 +93,7 @@
|
||||
#include "compat.h"
|
||||
#include "ssh2.h"
|
||||
@ -1108,7 +1109,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c
|
||||
extern struct sshbuf *loginmsg;
|
||||
extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */
|
||||
|
||||
+extern void destroy_sensitive_data(struct ssh *, int);
|
||||
+extern void destroy_sensitive_data(struct ssh *);
|
||||
+
|
||||
/* State exported from the child */
|
||||
static struct sshbuf *child_state;
|
||||
@ -1195,9 +1196,9 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c
|
||||
|
||||
- ret = sshkey_verify(key, signature, signaturelen, data, datalen,
|
||||
- sigalg, ssh->compat, &sig_details);
|
||||
debug3_f("%s %s signature %s%s%s", auth_method, sshkey_type(key),
|
||||
debug3_f("%s %s signature using %s %s%s%s", auth_method,
|
||||
sshkey_type(key), sigalg == NULL ? "default" : sigalg,
|
||||
(ret == 0) ? "verified" : "unverified",
|
||||
(ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : "");
|
||||
@@ -1576,13 +1600,19 @@ mm_record_login(struct ssh *ssh, Session
|
||||
}
|
||||
|
||||
@ -1241,7 +1242,7 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c
|
||||
sshpam_cleanup();
|
||||
#endif
|
||||
|
||||
+ destroy_sensitive_data(ssh, 0);
|
||||
+ destroy_sensitive_data(ssh);
|
||||
+
|
||||
while (waitpid(pmonitor->m_pid, &status, 0) == -1)
|
||||
if (errno != EINTR)
|
||||
@ -1427,8 +1428,8 @@ diff -up openssh-8.6p1/monitor.c.audit openssh-8.6p1/monitor.c
|
||||
+}
|
||||
+#endif /* SSH_AUDIT_EVENTS */
|
||||
diff -up openssh-8.6p1/monitor.h.audit openssh-8.6p1/monitor.h
|
||||
--- openssh-8.6p1/monitor.h.audit 2021-05-06 12:05:27.326464138 +0200
|
||||
+++ openssh-8.6p1/monitor.h 2021-05-06 12:05:27.380464555 +0200
|
||||
--- openssh-8.6p1/monitor.h.audit 2021-04-19 16:47:35.707061753 +0200
|
||||
+++ openssh-8.6p1/monitor.h 2021-04-19 16:47:35.757062137 +0200
|
||||
@@ -65,7 +65,13 @@ enum monitor_reqtype {
|
||||
MONITOR_REQ_PAM_QUERY = 106, MONITOR_ANS_PAM_QUERY = 107,
|
||||
MONITOR_REQ_PAM_RESPOND = 108, MONITOR_ANS_PAM_RESPOND = 109,
|
||||
@ -1445,8 +1446,8 @@ diff -up openssh-8.6p1/monitor.h.audit openssh-8.6p1/monitor.h
|
||||
MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151,
|
||||
MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153,
|
||||
diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c
|
||||
--- openssh-8.6p1/monitor_wrap.c.audit 2021-05-06 12:05:27.307463991 +0200
|
||||
+++ openssh-8.6p1/monitor_wrap.c 2021-05-06 12:05:27.381464563 +0200
|
||||
--- openssh-8.6p1/monitor_wrap.c.audit 2021-04-19 16:47:35.685061584 +0200
|
||||
+++ openssh-8.6p1/monitor_wrap.c 2021-04-19 16:47:35.757062137 +0200
|
||||
@@ -520,7 +520,7 @@ mm_key_allowed(enum mm_keytype type, con
|
||||
*/
|
||||
|
||||
@ -1536,9 +1537,9 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c
|
||||
}
|
||||
#endif /* SSH_AUDIT_EVENTS */
|
||||
@@ -1095,3 +1137,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc
|
||||
return &ci;
|
||||
}
|
||||
|
||||
#endif /* GSSAPI */
|
||||
+#ifdef SSH_AUDIT_EVENTS
|
||||
+void
|
||||
+mm_audit_unsupported_body(struct ssh *ssh, int what)
|
||||
@ -1620,8 +1621,8 @@ diff -up openssh-8.6p1/monitor_wrap.c.audit openssh-8.6p1/monitor_wrap.c
|
||||
+}
|
||||
+#endif /* SSH_AUDIT_EVENTS */
|
||||
diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h
|
||||
--- openssh-8.6p1/monitor_wrap.h.audit 2021-05-06 12:05:27.307463991 +0200
|
||||
+++ openssh-8.6p1/monitor_wrap.h 2021-05-06 12:05:27.381464563 +0200
|
||||
--- openssh-8.6p1/monitor_wrap.h.audit 2021-04-19 16:47:35.685061584 +0200
|
||||
+++ openssh-8.6p1/monitor_wrap.h 2021-04-19 16:47:35.757062137 +0200
|
||||
@@ -61,7 +61,9 @@ int mm_user_key_allowed(struct ssh *, st
|
||||
struct sshauthopt **);
|
||||
int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *,
|
||||
@ -1632,7 +1633,7 @@ diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h
|
||||
+int mm_user_key_verify(struct ssh*, const struct sshkey *, const u_char *, size_t,
|
||||
const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **);
|
||||
|
||||
#ifdef GSSAPI
|
||||
void mm_decode_activate_server_options(struct ssh *ssh, struct sshbuf *m);
|
||||
@@ -86,7 +88,12 @@ void mm_sshpam_free_ctx(void *);
|
||||
#ifdef SSH_AUDIT_EVENTS
|
||||
#include "audit.h"
|
||||
@ -1649,7 +1650,7 @@ diff -up openssh-8.6p1/monitor_wrap.h.audit openssh-8.6p1/monitor_wrap.h
|
||||
struct Session;
|
||||
diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c
|
||||
--- openssh-8.6p1/packet.c.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/packet.c 2021-05-06 12:07:38.535478683 +0200
|
||||
+++ openssh-8.6p1/packet.c 2021-04-19 16:48:46.885608837 +0200
|
||||
@@ -81,6 +81,7 @@
|
||||
#endif
|
||||
|
||||
@ -1802,7 +1803,7 @@ diff -up openssh-8.6p1/packet.c.audit openssh-8.6p1/packet.c
|
||||
ssh_packet_set_postauth(struct ssh *ssh)
|
||||
diff -up openssh-8.6p1/packet.h.audit openssh-8.6p1/packet.h
|
||||
--- openssh-8.6p1/packet.h.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/packet.h 2021-05-06 12:05:27.382464571 +0200
|
||||
+++ openssh-8.6p1/packet.h 2021-04-19 16:47:35.758062145 +0200
|
||||
@@ -218,4 +218,5 @@ const u_char *sshpkt_ptr(struct ssh *, s
|
||||
# undef EC_POINT
|
||||
#endif
|
||||
@ -1810,14 +1811,14 @@ diff -up openssh-8.6p1/packet.h.audit openssh-8.6p1/packet.h
|
||||
+void packet_destroy_all(struct ssh *, int, int);
|
||||
#endif /* PACKET_H */
|
||||
diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c
|
||||
--- openssh-8.6p1/session.c.audit 2021-05-06 12:05:27.340464246 +0200
|
||||
+++ openssh-8.6p1/session.c 2021-05-06 12:05:27.383464578 +0200
|
||||
--- openssh-8.6p1/session.c.audit 2021-04-19 16:47:35.722061868 +0200
|
||||
+++ openssh-8.6p1/session.c 2021-04-19 16:47:35.758062145 +0200
|
||||
@@ -136,7 +136,7 @@ extern char *__progname;
|
||||
extern int debug_flag;
|
||||
extern u_int utmp_len;
|
||||
extern int startup_pipe;
|
||||
-extern void destroy_sensitive_data(void);
|
||||
+extern void destroy_sensitive_data(struct ssh *, int);
|
||||
+extern void destroy_sensitive_data(struct ssh *);
|
||||
extern struct sshbuf *loginmsg;
|
||||
extern struct sshauthopt *auth_opts;
|
||||
extern char *tun_fwd_ifnames; /* serverloop.c */
|
||||
@ -1843,18 +1844,18 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c
|
||||
+ if (s->command != NULL || s->command_handle != -1)
|
||||
+ fatal("do_exec: command already set");
|
||||
if (command != NULL)
|
||||
- PRIVSEP(audit_run_command(command));
|
||||
- mm_audit_run_command(command);
|
||||
+ s->command = xstrdup(command);
|
||||
else if (s->ttyfd == -1) {
|
||||
char *shell = s->pw->pw_shell;
|
||||
|
||||
if (shell[0] == '\0') /* empty shell means /bin/sh */
|
||||
shell =_PATH_BSHELL;
|
||||
- PRIVSEP(audit_run_command(shell));
|
||||
- mm_audit_run_command(shell);
|
||||
+ s->command = xstrdup(shell);
|
||||
}
|
||||
+ if (s->command != NULL && s->ptyfd == -1)
|
||||
+ s->command_handle = PRIVSEP(audit_run_command(ssh, s->command));
|
||||
+ s->command_handle = mm_audit_run_command(ssh, s->command);
|
||||
#endif
|
||||
if (s->ttyfd != -1)
|
||||
ret = do_exec_pty(ssh, s, command);
|
||||
@ -1863,7 +1864,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c
|
||||
|
||||
/* remove hostkey from the child's memory */
|
||||
- destroy_sensitive_data();
|
||||
+ destroy_sensitive_data(ssh, 1);
|
||||
+ destroy_sensitive_data(ssh);
|
||||
ssh_packet_clear_keys(ssh);
|
||||
+ /* Don't audit this - both us and the parent would be talking to the
|
||||
+ monitor over a single socket, with no synchronization. */
|
||||
@ -1923,7 +1924,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c
|
||||
+{
|
||||
+ if (s->command != NULL) {
|
||||
+ if (s->command_handle != -1)
|
||||
+ PRIVSEP(audit_end_command(ssh, s->command_handle, s->command));
|
||||
+ mm_audit_end_command(ssh, s->command_handle, s->command);
|
||||
+ free(s->command);
|
||||
+ s->command = NULL;
|
||||
+ s->command_handle = -1;
|
||||
@ -1981,7 +1982,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c
|
||||
@@ -2734,7 +2804,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au
|
||||
* or if running in monitor.
|
||||
*/
|
||||
if (!use_privsep || mm_is_monitor())
|
||||
if (mm_is_monitor())
|
||||
- session_destroy_all(ssh, session_pty_cleanup2);
|
||||
+ session_destroy_all(ssh, do_cleanup_one_session);
|
||||
}
|
||||
@ -1989,7 +1990,7 @@ diff -up openssh-8.6p1/session.c.audit openssh-8.6p1/session.c
|
||||
/* Return a name for the remote host that fits inside utmp_size */
|
||||
diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h
|
||||
--- openssh-8.6p1/session.h.audit 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/session.h 2021-05-06 12:05:27.384464586 +0200
|
||||
+++ openssh-8.6p1/session.h 2021-04-19 16:47:35.758062145 +0200
|
||||
@@ -61,6 +61,12 @@ struct Session {
|
||||
char *name;
|
||||
char *val;
|
||||
@ -2006,7 +2007,7 @@ diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h
|
||||
@@ -71,10 +77,12 @@ void session_unused(int);
|
||||
int session_input_channel_req(struct ssh *, Channel *, const char *);
|
||||
void session_close_by_pid(struct ssh *ssh, pid_t, int);
|
||||
void session_close_by_channel(struct ssh *, int, void *);
|
||||
void session_close_by_channel(struct ssh *, int, int, void *);
|
||||
-void session_destroy_all(struct ssh *, void (*)(Session *));
|
||||
+void session_destroy_all(struct ssh *, void (*)(struct ssh*, Session *));
|
||||
void session_pty_cleanup2(Session *);
|
||||
@ -2018,29 +2019,10 @@ diff -up openssh-8.6p1/session.h.audit openssh-8.6p1/session.h
|
||||
void session_close(struct ssh *, Session *);
|
||||
void do_setusercontext(struct passwd *);
|
||||
diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c
|
||||
--- openssh-8.6p1/sshd.c.audit 2021-05-06 12:05:27.346464292 +0200
|
||||
+++ openssh-8.6p1/sshd.c 2021-05-06 12:05:27.385464594 +0200
|
||||
@@ -122,6 +122,7 @@
|
||||
#include "ssh-gss.h"
|
||||
#endif
|
||||
#include "monitor_wrap.h"
|
||||
+#include "audit.h"
|
||||
#include "ssh-sandbox.h"
|
||||
#include "auth-options.h"
|
||||
#include "version.h"
|
||||
@@ -260,8 +261,8 @@ struct sshbuf *loginmsg;
|
||||
struct passwd *privsep_pw = NULL;
|
||||
|
||||
/* Prototypes for various functions defined later in this file. */
|
||||
-void destroy_sensitive_data(void);
|
||||
-void demote_sensitive_data(void);
|
||||
+void destroy_sensitive_data(struct ssh *, int);
|
||||
+void demote_sensitive_data(struct ssh *);
|
||||
static void do_ssh2_kex(struct ssh *);
|
||||
|
||||
static char *listener_proctitle;
|
||||
--- openssh-8.6p1/sshd.c.audit 2021-04-19 16:47:35.727061907 +0200
|
||||
+++ openssh-8.6p1/sshd.c 2021-04-19 16:47:35.759062152 +0200
|
||||
@@ -279,6 +280,15 @@ close_listen_socks(void)
|
||||
num_listen_socks = -1;
|
||||
num_listen_socks = 0;
|
||||
}
|
||||
|
||||
+/*
|
||||
@ -2049,16 +2031,82 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c
|
||||
+ */
|
||||
+int listening_for_clients(void)
|
||||
+{
|
||||
+ return num_listen_socks >= 0;
|
||||
+ return num_listen_socks > 0;
|
||||
+}
|
||||
+
|
||||
/* Allocate and initialise the children array */
|
||||
static void
|
||||
close_startup_pipes(void)
|
||||
{
|
||||
@@ -377,18 +387,45 @@ grace_alarm_handler(int sig)
|
||||
}
|
||||
}
|
||||
child_alloc(void)
|
||||
@@ -1204,6 +1259,7 @@ server_accept_loop(int *sock_in, int *so
|
||||
if (received_sigterm) {
|
||||
logit("Received signal %d; terminating.",
|
||||
(int) received_sigterm);
|
||||
+ /* destroy_sensitive_data(ssh, 0); FIXME */
|
||||
close_listen_socks();
|
||||
if (options.pid_file != NULL)
|
||||
unlink(options.pid_file);
|
||||
diff -up openssh-8.6p1/sshd-session.c.audit openssh-8.6p1/sshd-session.c
|
||||
--- openssh-8.6p1/sshd-session.c.audit 2021-04-19 16:47:35.727061907 +0200
|
||||
+++ openssh-8.6p1/sshd-session.c 2021-04-19 16:47:35.759062152 +0200
|
||||
@@ -122,6 +122,7 @@
|
||||
#include "ssh-gss.h"
|
||||
#endif
|
||||
#include "monitor_wrap.h"
|
||||
+#include "audit.h"
|
||||
#include "ssh-sandbox.h"
|
||||
#include "auth-options.h"
|
||||
#include "version.h"
|
||||
@@ -260,8 +261,44 @@ struct sshbuf *loginmsg;
|
||||
struct sshbuf *loginmsg;
|
||||
|
||||
/* Prototypes for various functions defined later in this file. */
|
||||
-void destroy_sensitive_data(void);
|
||||
-void demote_sensitive_data(void);
|
||||
+void destroy_sensitive_data(struct ssh *);
|
||||
+void demote_sensitive_data(struct ssh *);
|
||||
+
|
||||
+static int
|
||||
+sshkey_is_private(const struct sshkey *k)
|
||||
+{
|
||||
+ switch (k->type) {
|
||||
+#ifdef WITH_OPENSSL
|
||||
+ case KEY_RSA_CERT:
|
||||
+ case KEY_RSA: {
|
||||
+ const BIGNUM *d;
|
||||
+ const RSA *rsa = EVP_PKEY_get0_RSA(k->pkey);
|
||||
+ RSA_get0_key(rsa, NULL, NULL, &d);
|
||||
+ return d != NULL;
|
||||
+ }
|
||||
+ case KEY_DSA_CERT:
|
||||
+ case KEY_DSA: {
|
||||
+ const BIGNUM *priv_key;
|
||||
+ DSA_get0_key(k->dsa, NULL, &priv_key);
|
||||
+ return priv_key != NULL;
|
||||
+ }
|
||||
+#ifdef OPENSSL_HAS_ECC
|
||||
+ case KEY_ECDSA_CERT:
|
||||
+ case KEY_ECDSA: {
|
||||
+ const EC_KEY * ecdsa = EVP_PKEY_get0_EC_KEY(k->pkey);
|
||||
+ return EC_KEY_get0_private_key(ecdsa) != NULL;
|
||||
+ }
|
||||
+#endif /* OPENSSL_HAS_ECC */
|
||||
+#endif /* WITH_OPENSSL */
|
||||
+ case KEY_ED25519_CERT:
|
||||
+ case KEY_ED25519:
|
||||
+ return (k->ed25519_pk != NULL);
|
||||
+ default:
|
||||
+ /* fatal("key_is_private: bad key type %d", k->type); */
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void do_ssh2_kex(struct ssh *);
|
||||
|
||||
/*
|
||||
@@ -377,18 +387,40 @@ grace_alarm_handler(int sig)
|
||||
_exit(EXIT_LOGIN_GRACE);
|
||||
}
|
||||
|
||||
-/* Destroy the host and server keys. They will no longer be needed. */
|
||||
+/*
|
||||
+ * Destroy the host and server keys. They will no longer be needed. Careful,
|
||||
@ -2066,7 +2114,7 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c
|
||||
+ */
|
||||
void
|
||||
-destroy_sensitive_data(void)
|
||||
+destroy_sensitive_data(struct ssh *ssh, int privsep)
|
||||
+destroy_sensitive_data(struct ssh *ssh)
|
||||
{
|
||||
u_int i;
|
||||
+#ifdef SSH_AUDIT_EVENTS
|
||||
@ -2088,12 +2136,7 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c
|
||||
sensitive_data.host_keys[i] = NULL;
|
||||
+ if (fp != NULL) {
|
||||
+#ifdef SSH_AUDIT_EVENTS
|
||||
+ if (privsep)
|
||||
+ PRIVSEP(audit_destroy_sensitive_data(ssh, fp,
|
||||
+ pid, uid));
|
||||
+ else
|
||||
+ audit_destroy_sensitive_data(ssh, fp,
|
||||
+ pid, uid);
|
||||
+ audit_destroy_sensitive_data(ssh, fp, pid, uid);
|
||||
+#endif
|
||||
+ free(fp);
|
||||
+ }
|
||||
@ -2163,9 +2206,9 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c
|
||||
#ifdef WITH_SELINUX
|
||||
sshd_selinux_change_privsep_preauth_context();
|
||||
@@ -492,7 +547,7 @@ privsep_preauth(struct ssh *ssh)
|
||||
pmonitor->m_pkex = &ssh->kex;
|
||||
|
||||
if (use_privsep == PRIVSEP_ON)
|
||||
box = ssh_sandbox_init(pmonitor);
|
||||
box = ssh_sandbox_init(pmonitor);
|
||||
- pid = fork();
|
||||
+ pmonitor->m_pid = pid = fork();
|
||||
if (pid == -1) {
|
||||
@ -2189,48 +2232,21 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c
|
||||
|
||||
reseed_prngs();
|
||||
|
||||
@@ -1143,7 +1198,7 @@ server_listen(void)
|
||||
* from this function are in a forked subprocess.
|
||||
*/
|
||||
static void
|
||||
-server_accept_loop(int *sock_in, int *sock_out, int *newsock, int *config_s)
|
||||
+server_accept_loop(struct ssh *ssh, int *sock_in, int *sock_out, int *newsock, int *config_s)
|
||||
{
|
||||
fd_set *fdset;
|
||||
int i, j, ret, maxfd;
|
||||
@@ -1204,6 +1259,7 @@ server_accept_loop(int *sock_in, int *so
|
||||
if (received_sigterm) {
|
||||
logit("Received signal %d; terminating.",
|
||||
(int) received_sigterm);
|
||||
+ destroy_sensitive_data(ssh, 0);
|
||||
close_listen_socks();
|
||||
if (options.pid_file != NULL)
|
||||
unlink(options.pid_file);
|
||||
@@ -2098,7 +2154,7 @@ main(int ac, char **av)
|
||||
#endif
|
||||
|
||||
/* Accept a connection and return in a forked child */
|
||||
- server_accept_loop(&sock_in, &sock_out,
|
||||
+ server_accept_loop(ssh, &sock_in, &sock_out,
|
||||
&newsock, config_s);
|
||||
}
|
||||
|
||||
@@ -2333,6 +2389,9 @@ main(int ac, char **av)
|
||||
do_authenticated(ssh, authctxt);
|
||||
|
||||
/* The connection has been terminated. */
|
||||
+ packet_destroy_all(ssh, 1, 1);
|
||||
+ destroy_sensitive_data(ssh, 1);
|
||||
+ destroy_sensitive_data(ssh);
|
||||
+
|
||||
ssh_packet_get_bytes(ssh, &ibytes, &obytes);
|
||||
verbose("Transferred: sent %llu, received %llu bytes",
|
||||
(unsigned long long)obytes, (unsigned long long)ibytes);
|
||||
@@ -2513,6 +2572,15 @@ do_ssh2_kex(struct ssh *ssh)
|
||||
@@ -2513,6 +2572,14 @@ do_ssh2_kex(struct ssh *ssh)
|
||||
void
|
||||
cleanup_exit(int i)
|
||||
{
|
||||
+ static int in_cleanup = 0;
|
||||
+ int is_privsep_child;
|
||||
+
|
||||
+ /* cleanup_exit can be called at the very least from the privsep
|
||||
+ wrappers used for auditing. Make sure we don't recurse
|
||||
@ -2238,77 +2254,17 @@ diff -up openssh-8.6p1/sshd.c.audit openssh-8.6p1/sshd.c
|
||||
+ if (in_cleanup)
|
||||
+ _exit(i);
|
||||
+ in_cleanup = 1;
|
||||
extern int auth_attempted; /* monitor.c */
|
||||
|
||||
if (the_active_state != NULL && the_authctxt != NULL) {
|
||||
do_cleanup(the_active_state, the_authctxt);
|
||||
if (use_privsep && privsep_is_preauth &&
|
||||
@@ -2525,9 +2593,16 @@ cleanup_exit(int i)
|
||||
}
|
||||
}
|
||||
@@ -2525,7 +2593,9 @@ cleanup_exit(int i)
|
||||
}
|
||||
+ is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0;
|
||||
+ if (sensitive_data.host_keys != NULL && the_active_state != NULL)
|
||||
+ destroy_sensitive_data(the_active_state, is_privsep_child);
|
||||
+ if (the_active_state != NULL)
|
||||
+ packet_destroy_all(the_active_state, 1, is_privsep_child);
|
||||
#ifdef SSH_AUDIT_EVENTS
|
||||
/* done after do_cleanup so it can cancel the PAM auth 'thread' */
|
||||
- if (the_active_state != NULL && (!use_privsep || mm_is_monitor()))
|
||||
- if (the_active_state != NULL && mm_is_monitor())
|
||||
+ if (the_active_state != NULL &&
|
||||
+ (the_authctxt == NULL || !the_authctxt->authenticated) &&
|
||||
+ (!use_privsep || mm_is_monitor()))
|
||||
+ mm_is_monitor())
|
||||
audit_event(the_active_state, SSH_CONNECTION_ABANDON);
|
||||
#endif
|
||||
_exit(i);
|
||||
diff -up openssh-8.6p1/sshkey.c.audit openssh-8.6p1/sshkey.c
|
||||
--- openssh-8.6p1/sshkey.c.audit 2021-05-06 12:05:27.364464431 +0200
|
||||
+++ openssh-8.6p1/sshkey.c 2021-05-06 12:05:27.386464602 +0200
|
||||
@@ -371,6 +371,38 @@ sshkey_type_is_valid_ca(int type)
|
||||
}
|
||||
|
||||
int
|
||||
+sshkey_is_private(const struct sshkey *k)
|
||||
+{
|
||||
+ switch (k->type) {
|
||||
+#ifdef WITH_OPENSSL
|
||||
+ case KEY_RSA_CERT:
|
||||
+ case KEY_RSA: {
|
||||
+ const BIGNUM *d;
|
||||
+ RSA_get0_key(k->rsa, NULL, NULL, &d);
|
||||
+ return d != NULL;
|
||||
+ }
|
||||
+ case KEY_DSA_CERT:
|
||||
+ case KEY_DSA: {
|
||||
+ const BIGNUM *priv_key;
|
||||
+ DSA_get0_key(k->dsa, NULL, &priv_key);
|
||||
+ return priv_key != NULL;
|
||||
+ }
|
||||
+#ifdef OPENSSL_HAS_ECC
|
||||
+ case KEY_ECDSA_CERT:
|
||||
+ case KEY_ECDSA:
|
||||
+ return EC_KEY_get0_private_key(k->ecdsa) != NULL;
|
||||
+#endif /* OPENSSL_HAS_ECC */
|
||||
+#endif /* WITH_OPENSSL */
|
||||
+ case KEY_ED25519_CERT:
|
||||
+ case KEY_ED25519:
|
||||
+ return (k->ed25519_pk != NULL);
|
||||
+ default:
|
||||
+ /* fatal("key_is_private: bad key type %d", k->type); */
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+int
|
||||
sshkey_is_cert(const struct sshkey *k)
|
||||
{
|
||||
if (k == NULL)
|
||||
diff -up openssh-8.6p1/sshkey.h.audit openssh-8.6p1/sshkey.h
|
||||
--- openssh-8.6p1/sshkey.h.audit 2021-05-06 12:05:27.365464439 +0200
|
||||
+++ openssh-8.6p1/sshkey.h 2021-05-06 12:05:27.386464602 +0200
|
||||
@@ -189,6 +189,7 @@ int sshkey_shield_private(struct sshke
|
||||
int sshkey_unshield_private(struct sshkey *);
|
||||
|
||||
int sshkey_type_from_name(const char *);
|
||||
+int sshkey_is_private(const struct sshkey *);
|
||||
int sshkey_is_cert(const struct sshkey *);
|
||||
int sshkey_is_sk(const struct sshkey *);
|
||||
int sshkey_type_is_cert(int);
|
||||
/* Override default fatal exit value when auth was attempted */
|
||||
|
||||
@ -1,23 +1,22 @@
|
||||
diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
|
||||
--- openssh/auth2-pubkey.c.refactor 2019-04-04 13:19:12.188821236 +0200
|
||||
+++ openssh/auth2-pubkey.c 2019-04-04 13:19:12.276822078 +0200
|
||||
@@ -72,6 +72,9 @@
|
||||
@@ -72,6 +72,8 @@
|
||||
|
||||
/* import */
|
||||
extern ServerOptions options;
|
||||
+extern int inetd_flag;
|
||||
+extern int rexeced_flag;
|
||||
+extern Authctxt *the_authctxt;
|
||||
extern struct authmethod_cfg methodcfg_pubkey;
|
||||
|
||||
static char *
|
||||
format_key(const struct sshkey *key)
|
||||
@@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh
|
||||
if ((pid = subprocess("AuthorizedPrincipalsCommand", command,
|
||||
ac, av, &f,
|
||||
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD,
|
||||
- runas_pw, temporarily_use_uid, restore_uid)) == 0)
|
||||
+ runas_pw, temporarily_use_uid, restore_uid,
|
||||
+ (inetd_flag && !rexeced_flag), the_authctxt)) == 0)
|
||||
+ inetd_flag, the_authctxt)) == 0)
|
||||
goto out;
|
||||
|
||||
uid_swapped = 1;
|
||||
@ -27,7 +26,7 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c
|
||||
SSH_SUBPROCESS_STDOUT_CAPTURE|SSH_SUBPROCESS_STDERR_DISCARD,
|
||||
- runas_pw, temporarily_use_uid, restore_uid)) == 0)
|
||||
+ runas_pw, temporarily_use_uid, restore_uid,
|
||||
+ (inetd_flag && !rexeced_flag), the_authctxt)) == 0)
|
||||
+ inetd_flag, the_authctxt)) == 0)
|
||||
goto out;
|
||||
|
||||
uid_swapped = 1;
|
||||
@ -82,14 +81,13 @@ diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/por
|
||||
diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c
|
||||
--- openssh/openbsd-compat/port-linux-sshd.c.refactor 2019-04-04 13:19:12.256821887 +0200
|
||||
+++ openssh/openbsd-compat/port-linux-sshd.c 2019-04-04 13:19:12.276822078 +0200
|
||||
@@ -49,11 +49,6 @@
|
||||
@@ -49,10 +49,6 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
-extern ServerOptions options;
|
||||
-extern Authctxt *the_authctxt;
|
||||
-extern int inetd_flag;
|
||||
-extern int rexeced_flag;
|
||||
-
|
||||
/* Wrapper around is_selinux_enabled() to log its return value once only */
|
||||
int
|
||||
@ -128,7 +126,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
|
||||
|
||||
if (r == 0) {
|
||||
/* If launched from xinetd, we must use current level */
|
||||
- if (inetd_flag && !rexeced_flag) {
|
||||
- if (inetd_flag) {
|
||||
+ if (inetd) {
|
||||
security_context_t sshdsc=NULL;
|
||||
|
||||
@ -152,7 +150,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
|
||||
|
||||
rv = set_it("SELINUX_ROLE_REQUESTED", role ? role : "");
|
||||
|
||||
- if (inetd_flag && !rexeced_flag) {
|
||||
- if (inetd_flag) {
|
||||
+ if (inetd) {
|
||||
use_current = "1";
|
||||
} else {
|
||||
@ -216,55 +214,45 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa
|
||||
diff -up openssh/platform.c.refactor openssh/platform.c
|
||||
--- openssh/platform.c.refactor 2019-04-04 13:19:12.204821389 +0200
|
||||
+++ openssh/platform.c 2019-04-04 13:19:12.277822088 +0200
|
||||
@@ -32,6 +32,9 @@
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "openbsd-compat/openbsd-compat.h"
|
||||
|
||||
extern int use_privsep;
|
||||
extern ServerOptions options;
|
||||
+extern int inetd_flag;
|
||||
+extern int rexeced_flag;
|
||||
+extern Authctxt *the_authctxt;
|
||||
|
||||
void
|
||||
platform_pre_listen(void)
|
||||
/* return 1 if we are running with privilege to swap UIDs, 0 otherwise */
|
||||
int
|
||||
@@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru
|
||||
}
|
||||
#endif /* HAVE_SETPCRED */
|
||||
#ifdef WITH_SELINUX
|
||||
- sshd_selinux_setup_exec_context(pw->pw_name);
|
||||
+ sshd_selinux_setup_exec_context(pw->pw_name,
|
||||
+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt,
|
||||
+ inetd_flag, do_pam_putenv, the_authctxt,
|
||||
+ options.use_pam);
|
||||
#endif
|
||||
}
|
||||
|
||||
diff -up openssh/sshd.c.refactor openssh/sshd.c
|
||||
--- openssh/sshd.c.refactor 2019-04-04 13:19:12.275822068 +0200
|
||||
+++ openssh/sshd.c 2019-04-04 13:19:51.270195262 +0200
|
||||
diff -up openssh/sshd-session.c.refactor openssh/sshd-session.c
|
||||
--- openssh/sshd-session.c.refactor 2019-04-04 13:19:12.275822068 +0200
|
||||
+++ openssh/sshd-session.c 2019-04-04 13:19:51.270195262 +0200
|
||||
@@ -158,7 +158,7 @@ int debug_flag = 0;
|
||||
static int test_flag = 0;
|
||||
int debug_flag = 0;
|
||||
|
||||
/* Flag indicating that the daemon is being started from inetd. */
|
||||
-static int inetd_flag = 0;
|
||||
+int inetd_flag = 0;
|
||||
|
||||
/* Flag indicating that sshd should not detach and become a daemon. */
|
||||
static int no_daemon_flag = 0;
|
||||
@@ -171,7 +171,7 @@ static char **saved_argv;
|
||||
static int saved_argc;
|
||||
|
||||
/* re-exec */
|
||||
-static int rexeced_flag = 0;
|
||||
+int rexeced_flag = 0;
|
||||
static int rexec_flag = 1;
|
||||
static int rexec_argc = 0;
|
||||
static char **rexec_argv;
|
||||
/* debug goes to stderr unless inetd_flag is set */
|
||||
static int log_stderr = 0;
|
||||
@@ -2192,7 +2192,9 @@ main(int ac, char **av)
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_SELINUX
|
||||
- sshd_selinux_setup_exec_context(authctxt->pw->pw_name);
|
||||
+ sshd_selinux_setup_exec_context(authctxt->pw->pw_name,
|
||||
+ (inetd_flag && !rexeced_flag), do_pam_putenv, the_authctxt,
|
||||
+ inetd_flag, do_pam_putenv, the_authctxt,
|
||||
+ options.use_pam);
|
||||
#endif
|
||||
#ifdef USE_PAM
|
||||
|
||||
@ -72,17 +72,17 @@ diff -up openssh-8.6p1/dh.h.fips openssh-8.6p1/dh.h
|
||||
|
||||
u_int dh_estimate(int);
|
||||
void dh_set_moduli_file(const char *);
|
||||
diff -up openssh-8.6p1/kex.c.fips openssh-8.6p1/kex.c
|
||||
--- openssh-8.6p1/kex.c.fips 2021-05-06 12:08:36.489926807 +0200
|
||||
+++ openssh-8.6p1/kex.c 2021-05-06 12:08:36.498926877 +0200
|
||||
diff -up openssh-8.6p1/kex-names.c.fips openssh-8.6p1/kex-names.c
|
||||
--- openssh-8.6p1/kex-names.c.fips 2021-05-06 12:08:36.489926807 +0200
|
||||
+++ openssh-8.6p1/kex-names.c 2021-05-06 12:08:36.498926877 +0200
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/crypto.h>
|
||||
+#include <openssl/fips.h>
|
||||
#include <openssl/dh.h>
|
||||
# ifdef HAVE_EVP_KDF_CTX_NEW
|
||||
# include <openssl/kdf.h>
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
|
||||
@@ -203,7 +203,10 @@ kex_names_valid(const char *names)
|
||||
for ((p = strsep(&cp, ",")); p && *p != '\0';
|
||||
(p = strsep(&cp, ","))) {
|
||||
@ -121,8 +121,8 @@ diff -up openssh-8.6p1/myproposal.h.fips openssh-8.6p1/myproposal.h
|
||||
--- openssh-8.6p1/myproposal.h.fips 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/myproposal.h 2021-05-06 12:08:36.498926877 +0200
|
||||
@@ -57,6 +57,18 @@
|
||||
"rsa-sha2-256," \
|
||||
"ssh-rsa"
|
||||
"rsa-sha2-512," \
|
||||
"rsa-sha2-256"
|
||||
|
||||
+#define KEX_FIPS_PK_ALG \
|
||||
+ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \
|
||||
@ -268,9 +268,24 @@ diff -up openssh-8.6p1/ssh.c.fips openssh-8.6p1/ssh.c
|
||||
/* Expand SecurityKeyProvider if it refers to an environment variable */
|
||||
if (options.sk_provider != NULL && *options.sk_provider == '$' &&
|
||||
strlen(options.sk_provider) > 1) {
|
||||
diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c
|
||||
--- openssh-8.6p1/sshconnect2.c.fips 2021-05-06 12:08:36.485926777 +0200
|
||||
+++ openssh-8.6p1/sshconnect2.c 2021-05-06 12:08:36.501926900 +0200
|
||||
diff -up openssh-9.9p1/ssh-gss.h.xxx openssh-9.9p1/ssh-gss.h
|
||||
--- openssh-9.9p1/ssh-gss.h.xxx 2025-08-04 15:02:15.895341244 +0200
|
||||
+++ openssh-9.9p1/ssh-gss.h 2025-08-04 15:02:54.826304548 +0200
|
||||
@@ -94,6 +94,11 @@ extern char **k5users_allowed_cmds;
|
||||
KEX_GSS_GRP14_SHA1_ID "," \
|
||||
KEX_GSS_GEX_SHA1_ID
|
||||
|
||||
+#define GSS_KEX_DEFAULT_KEX_FIPS \
|
||||
+ KEX_GSS_GRP14_SHA256_ID "," \
|
||||
+ KEX_GSS_GRP16_SHA512_ID "," \
|
||||
+ KEX_GSS_NISTP256_SHA256_ID
|
||||
+
|
||||
#include "digest.h" /* SSH_DIGEST_MAX_LENGTH */
|
||||
|
||||
typedef struct {
|
||||
diff -up openssh-9.9p1/sshconnect2.c.xxx openssh-9.9p1/sshconnect2.c
|
||||
--- openssh-9.9p1/sshconnect2.c.xxx 2025-08-04 14:58:08.908229826 +0200
|
||||
+++ openssh-9.9p1/sshconnect2.c 2025-08-04 15:07:59.942477440 +0200
|
||||
@@ -45,6 +45,8 @@
|
||||
#include <vis.h>
|
||||
#endif
|
||||
@ -280,80 +295,32 @@ diff -up openssh-8.6p1/sshconnect2.c.fips openssh-8.6p1/sshconnect2.c
|
||||
#include "openbsd-compat/sys-queue.h"
|
||||
|
||||
#include "xmalloc.h"
|
||||
@@ -269,36 +271,41 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||
@@ -274,6 +277,9 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||
|
||||
#if defined(GSSAPI) && defined(WITH_OPENSSL)
|
||||
if (options.gss_keyex) {
|
||||
- /* Add the GSSAPI mechanisms currently supported on this
|
||||
- * client to the key exchange algorithm proposal */
|
||||
- orig = myproposal[PROPOSAL_KEX_ALGS];
|
||||
-
|
||||
- if (options.gss_server_identity) {
|
||||
- gss_host = xstrdup(options.gss_server_identity);
|
||||
- } else if (options.gss_trust_dns) {
|
||||
- gss_host = remote_hostname(ssh);
|
||||
- /* Fall back to specified host if we are using proxy command
|
||||
- * and can not use DNS on that socket */
|
||||
- if (strcmp(gss_host, "UNKNOWN") == 0) {
|
||||
- free(gss_host);
|
||||
+ if (FIPS_mode()) {
|
||||
+ logit("Disabling GSSAPIKeyExchange. Not usable in FIPS mode");
|
||||
+ options.gss_keyex = 0;
|
||||
+ } else {
|
||||
+ /* Add the GSSAPI mechanisms currently supported on this
|
||||
+ * client to the key exchange algorithm proposal */
|
||||
+ orig = myproposal[PROPOSAL_KEX_ALGS];
|
||||
+ char * gss_kex_filtered = FIPS_mode() ?
|
||||
+ match_filter_allowlist(options.gss_kex_algorithms, GSS_KEX_DEFAULT_KEX_FIPS) : xstrdup(options.gss_kex_algorithms);
|
||||
+
|
||||
+ if (options.gss_server_identity) {
|
||||
+ gss_host = xstrdup(options.gss_server_identity);
|
||||
+ } else if (options.gss_trust_dns) {
|
||||
+ gss_host = remote_hostname(ssh);
|
||||
+ /* Fall back to specified host if we are using proxy command
|
||||
+ * and can not use DNS on that socket */
|
||||
+ if (strcmp(gss_host, "UNKNOWN") == 0) {
|
||||
+ free(gss_host);
|
||||
+ gss_host = xstrdup(host);
|
||||
+ }
|
||||
+ } else {
|
||||
gss_host = xstrdup(host);
|
||||
}
|
||||
- } else {
|
||||
- gss_host = xstrdup(host);
|
||||
- }
|
||||
|
||||
- gss = ssh_gssapi_client_mechanisms(gss_host,
|
||||
- options.gss_client_identity, options.gss_kex_algorithms);
|
||||
- if (gss) {
|
||||
- debug("Offering GSSAPI proposal: %s", gss);
|
||||
- xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
|
||||
- "%s,%s", gss, orig);
|
||||
-
|
||||
- /* If we've got GSSAPI algorithms, then we also support the
|
||||
- * 'null' hostkey, as a last resort */
|
||||
- orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
|
||||
- xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
|
||||
- "%s,null", orig);
|
||||
+ gss = ssh_gssapi_client_mechanisms(gss_host,
|
||||
+ options.gss_client_identity, options.gss_kex_algorithms);
|
||||
+ if (gss) {
|
||||
+ debug("Offering GSSAPI proposal: %s", gss);
|
||||
+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
|
||||
+ "%s,%s", gss, orig);
|
||||
+
|
||||
+ /* If we've got GSSAPI algorithms, then we also support the
|
||||
+ * 'null' hostkey, as a last resort */
|
||||
+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
|
||||
+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
|
||||
+ "%s,null", orig);
|
||||
+ }
|
||||
/* Add the GSSAPI mechanisms currently supported on this
|
||||
* client to the key exchange algorithm proposal */
|
||||
orig = myproposal[PROPOSAL_KEX_ALGS];
|
||||
@@ -293,7 +299,9 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gss = ssh_gssapi_client_mechanisms(gss_host,
|
||||
- options.gss_client_identity, options.gss_kex_algorithms);
|
||||
+ options.gss_client_identity, gss_kex_filtered);
|
||||
+ free(gss_kex_filtered);
|
||||
+
|
||||
if (gss) {
|
||||
debug("Offering GSSAPI proposal: %s", gss);
|
||||
xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
|
||||
diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c
|
||||
--- openssh-8.6p1/sshd.c.fips 2021-05-06 12:08:36.493926838 +0200
|
||||
+++ openssh-8.6p1/sshd.c 2021-05-06 12:13:56.501492639 +0200
|
||||
@@ -66,6 +66,7 @@
|
||||
#include <grp.h>
|
||||
#endif
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
+#include <syslog.h>
|
||||
@ -361,21 +328,13 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -77,6 +78,7 @@
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/bn.h>
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
+#include <openssl/fips.h>
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
#endif
|
||||
|
||||
@@ -1619,6 +1621,7 @@ main(int ac, char **av)
|
||||
#endif
|
||||
__progname = ssh_get_progname(av[0]);
|
||||
|
||||
+ OpenSSL_add_all_algorithms();
|
||||
/* Save argv. Duplicate so setproctitle emulation doesn't clobber it */
|
||||
saved_argc = ac;
|
||||
rexec_argc = ac;
|
||||
@@ -1931,6 +1931,13 @@ main(int ac, char **av)
|
||||
&key, NULL)) != 0 && r != SSH_ERR_SYSTEM_ERROR)
|
||||
do_log2_r(r, ll, "Unable to load host key \"%s\"",
|
||||
@ -401,7 +360,18 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c
|
||||
/*
|
||||
* Chdir to the root directory so that the current disk can be
|
||||
* unmounted if desired.
|
||||
@@ -2494,10 +2501,14 @@ do_ssh2_kex(struct ssh *ssh)
|
||||
diff -up openssh-8.6p1/sshd-session.c.fips openssh-8.6p1/sshd-session.c
|
||||
--- a/sshd-session.c.fips 2021-05-06 12:08:36.493926838 +0200
|
||||
+++ b/sshd-session.c 2021-05-06 12:13:56.501492639 +0200
|
||||
@@ -78,6 +79,7 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/rand.h>
|
||||
+#include <openssl/fips.h>
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
#endif
|
||||
|
||||
@@ -2506,10 +2513,14 @@ do_ssh2_kex(struct ssh *ssh)
|
||||
if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0)
|
||||
orig = NULL;
|
||||
|
||||
@ -423,7 +393,7 @@ diff -up openssh-8.6p1/sshd.c.fips openssh-8.6p1/sshd.c
|
||||
diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
|
||||
--- openssh-8.6p1/sshkey.c.fips 2021-05-06 12:08:36.493926838 +0200
|
||||
+++ openssh-8.6p1/sshkey.c 2021-05-06 12:08:36.502926908 +0200
|
||||
@@ -34,6 +34,7 @@
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
@ -440,11 +410,11 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
|
||||
|
||||
#ifdef WITH_XMSS
|
||||
@@ -285,6 +285,18 @@ sshkey_alg_list(int certs_only, int plai
|
||||
for (kt = keytypes; kt->type != -1; kt++) {
|
||||
if (kt->name == NULL || kt->type == KEY_NULL)
|
||||
impl = keyimpls[i];
|
||||
if (impl->name == NULL || impl->type == KEY_NULL)
|
||||
continue;
|
||||
+ if (FIPS_mode()) {
|
||||
+ switch (kt->type) {
|
||||
+ switch (impl->type) {
|
||||
+ case KEY_ED25519:
|
||||
+ case KEY_ED25519_SK:
|
||||
+ case KEY_ED25519_CERT:
|
||||
@ -455,9 +425,9 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
if (!include_sigonly && kt->sigonly)
|
||||
if (!include_sigonly && impl->sigonly)
|
||||
continue;
|
||||
if ((certs_only && !kt->cert) || (plain_only && kt->cert))
|
||||
if ((certs_only && !impl->cert) || (plain_only && impl->cert))
|
||||
@@ -1503,6 +1503,20 @@ sshkey_read(struct sshkey *ret, char **c
|
||||
return SSH_ERR_EC_CURVE_MISMATCH;
|
||||
}
|
||||
@ -477,40 +447,31 @@ diff -up openssh-8.6p1/sshkey.c.fips openssh-8.6p1/sshkey.c
|
||||
+ break;
|
||||
+ }
|
||||
/* Fill in ret from parsed key */
|
||||
ret->type = type;
|
||||
if (sshkey_is_cert(ret)) {
|
||||
@@ -1705,6 +1707,8 @@ rsa_generate_private_key(u_int bits, RSA
|
||||
goto out;
|
||||
|
||||
if (EVP_PKEY_keygen(ctx, &res) <= 0) {
|
||||
+ if (FIPS_mode())
|
||||
+ logit_f("the key length might be unsupported by FIPS mode approved key generation method");
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
sshkey_free_contents(ret);
|
||||
*ret = *k;
|
||||
@@ -2916,6 +2916,11 @@ sshkey_sign(struct sshkey *key,
|
||||
break;
|
||||
case KEY_ED25519_SK:
|
||||
case KEY_ED25519_SK_CERT:
|
||||
+ if (FIPS_mode()) {
|
||||
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+ /* Fallthrough */
|
||||
case KEY_ECDSA_SK_CERT:
|
||||
case KEY_ECDSA_SK:
|
||||
r = sshsk_sign(sk_provider, key, sigp, lenp, data,
|
||||
*lenp = 0;
|
||||
if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) {
|
||||
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
+ /* Fallthrough */
|
||||
if ((impl = sshkey_impl_from_key(key)) == NULL)
|
||||
return SSH_ERR_KEY_TYPE_UNKNOWN;
|
||||
if ((r = sshkey_unshield_private(key)) != 0)
|
||||
@@ -2973,6 +2978,10 @@ sshkey_verify(const struct sshkey *key,
|
||||
return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
|
||||
case KEY_ED25519_SK:
|
||||
case KEY_ED25519_SK_CERT:
|
||||
+ if (FIPS_mode()) {
|
||||
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
return ssh_ed25519_sk_verify(key, sig, siglen, data, dlen,
|
||||
compat, detailsp);
|
||||
#ifdef WITH_XMSS
|
||||
*detailsp = NULL;
|
||||
if (siglen == 0 || dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ if (FIPS_mode() && ((key->type == KEY_ED25519_SK) || (key->type == KEY_ED25519_SK_CERT))) {
|
||||
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
if ((impl = sshkey_impl_from_key(key)) == NULL)
|
||||
return SSH_ERR_KEY_TYPE_UNKNOWN;
|
||||
return impl->funcs->verify(key, sig, siglen, data, dlen,
|
||||
diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
|
||||
--- openssh-8.6p1/ssh-keygen.c.fips 2021-05-06 12:08:36.467926637 +0200
|
||||
+++ openssh-8.6p1/ssh-keygen.c 2021-05-06 12:08:36.503926916 +0200
|
||||
@ -522,6 +483,14 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
|
||||
#include <openssl/pem.h>
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
#endif
|
||||
@@ -69,6 +69,7 @@
|
||||
#include "cipher.h"
|
||||
|
||||
#define DEFAULT_KEY_TYPE_NAME "ed25519"
|
||||
+#define FIPS_DEFAULT_KEY_TYPE_NAME "rsa"
|
||||
|
||||
/*
|
||||
* Default number of bits in the RSA, DSA and ECDSA keys. These value can be
|
||||
@@ -205,6 +205,12 @@ type_bits_valid(int type, const char *na
|
||||
#endif
|
||||
}
|
||||
@ -535,11 +504,20 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
|
||||
switch (type) {
|
||||
case KEY_DSA:
|
||||
if (*bitsp != 1024)
|
||||
@@ -266,7 +267,7 @@ ask_filename(struct passwd *pw, const ch
|
||||
char *name = NULL;
|
||||
|
||||
if (key_type_name == NULL)
|
||||
- name = _PATH_SSH_CLIENT_ID_ED25519;
|
||||
+ name = FIPS_mode() ? _PATH_SSH_CLIENT_ID_RSA : _PATH_SSH_CLIENT_ID_ED25519;
|
||||
else {
|
||||
switch (sshkey_type_from_shortname(key_type_name)) {
|
||||
#ifdef WITH_DSA
|
||||
@@ -1098,9 +1104,17 @@ do_gen_all_hostkeys(struct passwd *pw)
|
||||
first = 1;
|
||||
printf("%s: generating new host keys: ", __progname);
|
||||
}
|
||||
+ type = sshkey_type_from_name(key_types[i].key_type);
|
||||
+ type = sshkey_type_from_shortname(key_types[i].key_type);
|
||||
+
|
||||
+ /* Skip the keys that are not supported in FIPS mode */
|
||||
+ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) {
|
||||
@ -550,13 +528,42 @@ diff -up openssh-8.6p1/ssh-keygen.c.fips openssh-8.6p1/ssh-keygen.c
|
||||
+
|
||||
printf("%s ", key_types[i].key_type_display);
|
||||
fflush(stdout);
|
||||
- type = sshkey_type_from_name(key_types[i].key_type);
|
||||
- type = sshkey_type_from_shortname(key_types[i].key_type);
|
||||
if ((fd = mkstemp(prv_tmp)) == -1) {
|
||||
error("Could not save your private key in %s: %s",
|
||||
prv_tmp, strerror(errno));
|
||||
diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c
|
||||
--- openssh-8.7p1/kexgen.c.fips3 2022-07-11 16:11:21.973519913 +0200
|
||||
+++ openssh-8.7p1/kexgen.c 2022-07-11 16:25:31.172187365 +0200
|
||||
@@ -3830,7 +3831,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
|
||||
if (key_type_name == NULL)
|
||||
- key_type_name = DEFAULT_KEY_TYPE_NAME;
|
||||
+ key_type_name = FIPS_mode() ? FIPS_DEFAULT_KEY_TYPE_NAME : DEFAULT_KEY_TYPE_NAME;
|
||||
|
||||
type = sshkey_type_from_shortname(key_type_name);
|
||||
type_bits_valid(type, key_type_name, &bits);
|
||||
diff -up openssh-9.3p1/ssh-rsa.c.evpgenrsa openssh-9.3p1/ssh-rsa.c
|
||||
--- openssh-9.3p1/ssh-rsa.c.evpgenrsa 2022-06-30 15:14:58.200518353 +0200
|
||||
+++ openssh-9.3p1/ssh-rsa.c 2022-06-30 15:24:31.499641196 +0200
|
||||
@@ -33,6 +33,7 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/err.h>
|
||||
+#include <openssl/fips.h>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
@@ -1705,6 +1707,8 @@ ssh_rsa_generate(u_int bits, RSA
|
||||
goto out;
|
||||
}
|
||||
if (EVP_PKEY_keygen(ctx, &res) <= 0 || res == NULL) {
|
||||
+ if (FIPS_mode())
|
||||
+ logit_f("the key length might be unsupported by FIPS mode approved key generation method");
|
||||
ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
diff -up openssh-9.9p1/kexgen.c.xxx openssh-9.9p1/kexgen.c
|
||||
--- openssh-9.9p1/kexgen.c.xxx 2024-10-09 10:35:56.285946080 +0200
|
||||
+++ openssh-9.9p1/kexgen.c 2024-10-09 10:41:52.792597194 +0200
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -565,7 +572,7 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c
|
||||
|
||||
#include "sshkey.h"
|
||||
#include "kex.h"
|
||||
@@ -115,10 +116,20 @@ kex_gen_client(struct ssh *ssh)
|
||||
@@ -115,13 +116,28 @@ kex_gen_client(struct ssh *ssh)
|
||||
break;
|
||||
#endif
|
||||
case KEX_C25519_SHA256:
|
||||
@ -584,11 +591,20 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c
|
||||
+ r = SSH_ERR_INVALID_ARGUMENT;
|
||||
+ } else {
|
||||
+ r = kex_kem_sntrup761x25519_keypair(kex);
|
||||
+ }
|
||||
break;
|
||||
case KEX_KEM_MLKEM768X25519_SHA256:
|
||||
- r = kex_kem_mlkem768x25519_keypair(kex);
|
||||
+ if (FIPS_mode()) {
|
||||
+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode");
|
||||
+ r = SSH_ERR_INVALID_ARGUMENT;
|
||||
+ } else {
|
||||
+ r = kex_kem_mlkem768x25519_keypair(kex);
|
||||
+ }
|
||||
break;
|
||||
default:
|
||||
r = SSH_ERR_INVALID_ARGUMENT;
|
||||
@@ -186,11 +197,21 @@ input_kex_gen_reply(int type, u_int32_t
|
||||
@@ -189,15 +205,30 @@ input_kex_gen_reply(int type, u_int32_t
|
||||
break;
|
||||
#endif
|
||||
case KEX_C25519_SHA256:
|
||||
@ -609,11 +625,22 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c
|
||||
+ } else {
|
||||
+ r = kex_kem_sntrup761x25519_dec(kex, server_blob,
|
||||
+ &shared_secret);
|
||||
+ }
|
||||
break;
|
||||
case KEX_KEM_MLKEM768X25519_SHA256:
|
||||
- r = kex_kem_mlkem768x25519_dec(kex, server_blob,
|
||||
- &shared_secret);
|
||||
+ if (FIPS_mode()) {
|
||||
+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode");
|
||||
+ r = SSH_ERR_INVALID_ARGUMENT;
|
||||
+ } else {
|
||||
+ r = kex_kem_mlkem768x25519_dec(kex, server_blob,
|
||||
+ &shared_secret);
|
||||
+ }
|
||||
break;
|
||||
default:
|
||||
r = SSH_ERR_INVALID_ARGUMENT;
|
||||
@@ -285,12 +306,22 @@ input_kex_gen_init(int type, u_int32_t s
|
||||
@@ -312,16 +343,31 @@ input_kex_gen_init(int type, u_int32_t s
|
||||
break;
|
||||
#endif
|
||||
case KEX_C25519_SHA256:
|
||||
@ -636,6 +663,17 @@ diff -up openssh-8.7p1/kexgen.c.fips3 openssh-8.7p1/kexgen.c
|
||||
+ } else {
|
||||
+ r = kex_kem_sntrup761x25519_enc(kex, client_pubkey,
|
||||
+ &server_pubkey, &shared_secret);
|
||||
+ }
|
||||
break;
|
||||
case KEX_KEM_MLKEM768X25519_SHA256:
|
||||
- r = kex_kem_mlkem768x25519_enc(kex, client_pubkey,
|
||||
- &server_pubkey, &shared_secret);
|
||||
+ if (FIPS_mode()) {
|
||||
+ logit_f("Key exchange type mlkem768x25519 is not allowed in FIPS mode");
|
||||
+ r = SSH_ERR_INVALID_ARGUMENT;
|
||||
+ } else {
|
||||
+ r = kex_kem_mlkem768x25519_enc(kex, client_pubkey,
|
||||
+ &server_pubkey, &shared_secret);
|
||||
+ }
|
||||
break;
|
||||
default:
|
||||
@ -663,13 +701,33 @@ diff -up openssh-8.7p1/ssh-ed25519.c.fips3 openssh-8.7p1/ssh-ed25519.c
|
||||
if ((sig = malloc(slen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
@@ -108,6 +113,10 @@ ssh_ed25519_verify(const struct sshkey *
|
||||
datalen >= INT_MAX - crypto_sign_ed25519_BYTES ||
|
||||
signature == NULL || signaturelen == 0)
|
||||
dlen >= INT_MAX - crypto_sign_ed25519_BYTES ||
|
||||
sig == NULL || siglen == 0)
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ if (FIPS_mode()) {
|
||||
+ logit_f("Ed25519 keys are not allowed in FIPS mode");
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ }
|
||||
|
||||
if ((b = sshbuf_from(signature, signaturelen)) == NULL)
|
||||
if ((b = sshbuf_from(sig, siglen)) == NULL)
|
||||
return SSH_ERR_ALLOC_FAIL;
|
||||
diff -up openssh-9.9p1/kex.c.xxx openssh-9.9p1/kex.c
|
||||
--- openssh-9.9p1/kex.c.xxx 2024-10-11 12:44:08.087426597 +0200
|
||||
+++ openssh-9.9p1/kex.c 2024-10-11 14:00:10.404714521 +0200
|
||||
@@ -40,6 +40,7 @@
|
||||
#ifdef WITH_OPENSSL
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/dh.h>
|
||||
+#include <openssl/fips.h>
|
||||
# ifdef HAVE_EVP_KDF_CTX_NEW
|
||||
# include <openssl/kdf.h>
|
||||
# include <openssl/param_build.h>
|
||||
@@ -109,7 +110,7 @@ kex_proposal_populate_entries(struct ssh
|
||||
|
||||
/* Append EXT_INFO signalling to KexAlgorithms */
|
||||
if (kexalgos == NULL)
|
||||
- kexalgos = defprop[PROPOSAL_KEX_ALGS];
|
||||
+ kexalgos = FIPS_mode() ? KEX_DEFAULT_KEX_FIPS : defprop[PROPOSAL_KEX_ALGS];
|
||||
if ((cp = kex_names_cat(kexalgos, ssh->kex->server ?
|
||||
"ext-info-s,kex-strict-s-v00@openssh.com" :
|
||||
"ext-info-c,kex-strict-c-v00@openssh.com")) == NULL)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
diff -up openssh-8.6p1/auth.h.ccache_name openssh-8.6p1/auth.h
|
||||
--- openssh-8.6p1/auth.h.ccache_name 2021-05-06 11:15:36.345143341 +0200
|
||||
+++ openssh-8.6p1/auth.h 2021-05-06 11:15:36.387143654 +0200
|
||||
--- openssh-8.6p1/auth.h.ccache_name 2021-04-19 14:05:10.820744325 +0200
|
||||
+++ openssh-8.6p1/auth.h 2021-04-19 14:05:10.853744569 +0200
|
||||
@@ -83,6 +83,7 @@ struct Authctxt {
|
||||
krb5_principal krb5_user;
|
||||
char *krb5_ticket_file;
|
||||
@ -20,7 +20,7 @@ diff -up openssh-8.6p1/auth.h.ccache_name openssh-8.6p1/auth.h
|
||||
#endif /* AUTH_H */
|
||||
diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c
|
||||
--- openssh-8.6p1/auth-krb5.c.ccache_name 2021-04-16 05:55:25.000000000 +0200
|
||||
+++ openssh-8.6p1/auth-krb5.c 2021-05-06 11:28:40.195242317 +0200
|
||||
+++ openssh-8.6p1/auth-krb5.c 2021-04-19 14:40:55.142832954 +0200
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
@ -338,8 +338,8 @@ diff -up openssh-8.6p1/auth-krb5.c.ccache_name openssh-8.6p1/auth-krb5.c
|
||||
#endif /* !HEIMDAL */
|
||||
#endif /* KRB5 */
|
||||
diff -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c
|
||||
--- openssh-8.6p1/gss-serv.c.ccache_name 2021-05-06 11:15:36.374143558 +0200
|
||||
+++ openssh-8.6p1/gss-serv.c 2021-05-06 11:15:36.387143654 +0200
|
||||
--- openssh-8.6p1/gss-serv.c.ccache_name 2021-04-19 14:05:10.844744503 +0200
|
||||
+++ openssh-8.6p1/gss-serv.c 2021-04-19 14:05:10.854744577 +0200
|
||||
@@ -413,13 +413,15 @@ ssh_gssapi_cleanup_creds(void)
|
||||
}
|
||||
|
||||
@ -368,10 +368,10 @@ diff -up openssh-8.6p1/gss-serv.c.ccache_name openssh-8.6p1/gss-serv.c
|
||||
+ if (gssapi_client.store.envval == NULL)
|
||||
return;
|
||||
|
||||
ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
|
||||
ok = mm_ssh_gssapi_update_creds(&gssapi_client.store);
|
||||
diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c
|
||||
--- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-05-06 11:15:36.384143632 +0200
|
||||
+++ openssh-8.6p1/gss-serv-krb5.c 2021-05-06 11:15:36.387143654 +0200
|
||||
--- openssh-8.6p1/gss-serv-krb5.c.ccache_name 2021-04-19 14:05:10.852744562 +0200
|
||||
+++ openssh-8.6p1/gss-serv-krb5.c 2021-04-19 14:05:10.854744577 +0200
|
||||
@@ -267,7 +267,7 @@ ssh_gssapi_krb5_cmdok(krb5_principal pri
|
||||
/* This writes out any forwarded credentials from the structure populated
|
||||
* during userauth. Called after we have setuid to the user */
|
||||
@ -484,8 +484,8 @@ diff -up openssh-8.6p1/gss-serv-krb5.c.ccache_name openssh-8.6p1/gss-serv-krb5.c
|
||||
|
||||
int
|
||||
diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c
|
||||
--- openssh-8.6p1/servconf.c.ccache_name 2021-05-06 11:15:36.377143580 +0200
|
||||
+++ openssh-8.6p1/servconf.c 2021-05-06 11:15:36.388143662 +0200
|
||||
--- openssh-8.6p1/servconf.c.ccache_name 2021-04-19 14:05:10.848744532 +0200
|
||||
+++ openssh-8.6p1/servconf.c 2021-04-19 14:05:10.854744577 +0200
|
||||
@@ -136,6 +136,7 @@ initialize_server_options(ServerOptions
|
||||
options->kerberos_or_local_passwd = -1;
|
||||
options->kerberos_ticket_cleanup = -1;
|
||||
@ -503,16 +503,15 @@ diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c
|
||||
if (options->gss_authentication == -1)
|
||||
options->gss_authentication = 0;
|
||||
if (options->gss_keyex == -1)
|
||||
@@ -506,7 +509,8 @@ typedef enum {
|
||||
@@ -506,7 +509,7 @@ typedef enum {
|
||||
sPort, sHostKeyFile, sLoginGraceTime,
|
||||
sPermitRootLogin, sLogFacility, sLogLevel, sLogVerbose,
|
||||
sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup,
|
||||
- sKerberosGetAFSToken, sChallengeResponseAuthentication,
|
||||
+ sKerberosGetAFSToken, sKerberosUniqueCCache,
|
||||
+ sChallengeResponseAuthentication,
|
||||
sPasswordAuthentication, sKbdInteractiveAuthentication,
|
||||
sListenAddress, sAddressFamily,
|
||||
- sKerberosGetAFSToken, sPasswordAuthentication,
|
||||
+ sKerberosGetAFSToken, sKerberosUniqueCCache, sPasswordAuthentication,
|
||||
sKbdInteractiveAuthentication, sListenAddress, sAddressFamily,
|
||||
sPrintMotd, sPrintLastLog, sIgnoreRhosts,
|
||||
sX11Forwarding, sX11DisplayOffset, sX11UseLocalhost,
|
||||
@@ -593,11 +597,13 @@ static struct {
|
||||
#else
|
||||
{ "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL },
|
||||
@ -547,8 +546,8 @@ diff -up openssh-8.6p1/servconf.c.ccache_name openssh-8.6p1/servconf.c
|
||||
#ifdef GSSAPI
|
||||
dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
|
||||
diff -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h
|
||||
--- openssh-8.6p1/servconf.h.ccache_name 2021-05-06 11:15:36.377143580 +0200
|
||||
+++ openssh-8.6p1/servconf.h 2021-05-06 11:15:36.397143729 +0200
|
||||
--- openssh-8.6p1/servconf.h.ccache_name 2021-04-19 14:05:10.848744532 +0200
|
||||
+++ openssh-8.6p1/servconf.h 2021-04-19 14:05:10.855744584 +0200
|
||||
@@ -140,6 +140,8 @@ typedef struct {
|
||||
* file on logout. */
|
||||
int kerberos_get_afs_token; /* If true, try to get AFS token if
|
||||
@ -559,8 +558,8 @@ diff -up openssh-8.6p1/servconf.h.ccache_name openssh-8.6p1/servconf.h
|
||||
int gss_keyex; /* If true, permit GSSAPI key exchange */
|
||||
int gss_cleanup_creds; /* If true, destroy cred cache on logout */
|
||||
diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c
|
||||
--- openssh-8.6p1/session.c.ccache_name 2021-05-06 11:15:36.384143632 +0200
|
||||
+++ openssh-8.6p1/session.c 2021-05-06 11:15:36.397143729 +0200
|
||||
--- openssh-8.6p1/session.c.ccache_name 2021-04-19 14:05:10.852744562 +0200
|
||||
+++ openssh-8.6p1/session.c 2021-04-19 14:05:10.855744584 +0200
|
||||
@@ -1038,7 +1038,8 @@ do_setup_env(struct ssh *ssh, Session *s
|
||||
/* Allow any GSSAPI methods that we've used to alter
|
||||
* the child's environment as they see fit
|
||||
@ -580,9 +579,9 @@ diff -up openssh-8.6p1/session.c.ccache_name openssh-8.6p1/session.c
|
||||
child_set_env(&env, &envsize, "KRB5CCNAME",
|
||||
s->authctxt->krb5_ccname);
|
||||
#endif
|
||||
diff -up openssh-8.6p1/sshd.c.ccache_name openssh-8.6p1/sshd.c
|
||||
--- openssh-8.6p1/sshd.c.ccache_name 2021-05-06 11:15:36.380143602 +0200
|
||||
+++ openssh-8.6p1/sshd.c 2021-05-06 11:15:36.398143736 +0200
|
||||
diff -up openssh-8.6p1/sshd-session.c.ccache_name openssh-8.6p1/sshd-session.c
|
||||
--- openssh-8.6p1/sshd-session.c.ccache_name 2021-04-19 14:05:10.849744540 +0200
|
||||
+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:05:10.855744584 +0200
|
||||
@@ -2284,7 +2284,7 @@ main(int ac, char **av)
|
||||
#ifdef GSSAPI
|
||||
if (options.gss_authentication) {
|
||||
@ -593,8 +592,8 @@ diff -up openssh-8.6p1/sshd.c.ccache_name openssh-8.6p1/sshd.c
|
||||
}
|
||||
#endif
|
||||
diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5
|
||||
--- openssh-8.6p1/sshd_config.5.ccache_name 2021-05-06 11:15:36.380143602 +0200
|
||||
+++ openssh-8.6p1/sshd_config.5 2021-05-06 11:15:36.398143736 +0200
|
||||
--- openssh-8.6p1/sshd_config.5.ccache_name 2021-04-19 14:05:10.849744540 +0200
|
||||
+++ openssh-8.6p1/sshd_config.5 2021-04-19 14:05:10.856744592 +0200
|
||||
@@ -939,6 +939,14 @@ Specifies whether to automatically destr
|
||||
file on logout.
|
||||
The default is
|
||||
@ -608,11 +607,11 @@ diff -up openssh-8.6p1/sshd_config.5.ccache_name openssh-8.6p1/sshd_config.5
|
||||
+can lead to overwriting previous tickets by subseqent connections to the same
|
||||
+user account.
|
||||
.It Cm KexAlgorithms
|
||||
Specifies the available KEX (Key Exchange) algorithms.
|
||||
Multiple algorithms must be comma-separated.
|
||||
Specifies the permitted KEX (Key Exchange) algorithms that the server will
|
||||
offer to clients.
|
||||
diff -up openssh-8.6p1/ssh-gss.h.ccache_name openssh-8.6p1/ssh-gss.h
|
||||
--- openssh-8.6p1/ssh-gss.h.ccache_name 2021-05-06 11:15:36.384143632 +0200
|
||||
+++ openssh-8.6p1/ssh-gss.h 2021-05-06 11:15:36.398143736 +0200
|
||||
--- openssh-8.6p1/ssh-gss.h.ccache_name 2021-04-19 14:05:10.852744562 +0200
|
||||
+++ openssh-8.6p1/ssh-gss.h 2021-04-19 14:05:10.855744584 +0200
|
||||
@@ -114,7 +114,7 @@ typedef struct ssh_gssapi_mech_struct {
|
||||
int (*dochild) (ssh_gssapi_client *);
|
||||
int (*userok) (ssh_gssapi_client *, char *);
|
||||
|
||||
@ -1,13 +1,13 @@
|
||||
diff -up openssh-8.6p1/sshd.c.log-usepam-no openssh-8.6p1/sshd.c
|
||||
--- openssh-8.6p1/sshd.c.log-usepam-no 2021-04-19 14:00:45.099735129 +0200
|
||||
+++ openssh-8.6p1/sshd.c 2021-04-19 14:03:21.140920974 +0200
|
||||
--- openssh-8.6p1/sshd-session.c.log-usepam-no 2021-04-19 14:00:45.099735129 +0200
|
||||
+++ openssh-8.6p1/sshd-session.c 2021-04-19 14:03:21.140920974 +0200
|
||||
@@ -1749,6 +1749,10 @@ main(int ac, char **av)
|
||||
parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name,
|
||||
cfg, &includes, NULL);
|
||||
"enabled authentication methods");
|
||||
}
|
||||
|
||||
+ /* 'UsePAM no' is not supported in RHEL */
|
||||
+ /* 'UsePAM no' is not supported in our builds */
|
||||
+ if (! options.use_pam)
|
||||
+ logit("WARNING: 'UsePAM no' is not supported in RHEL and may cause several problems.");
|
||||
+ logit("WARNING: 'UsePAM no' is not supported in this build and may cause several problems.");
|
||||
+
|
||||
#ifdef WITH_OPENSSL
|
||||
if (options.moduli_file != NULL)
|
||||
@ -19,7 +19,7 @@ diff -up openssh-8.6p1/sshd_config.log-usepam-no openssh-8.6p1/sshd_config
|
||||
# If you just want the PAM account and session checks to run without
|
||||
# PAM authentication, then enable this but set PasswordAuthentication
|
||||
# and KbdInteractiveAuthentication to 'no'.
|
||||
+# WARNING: 'UsePAM no' is not supported in RHEL and may cause several
|
||||
+# WARNING: 'UsePAM no' is not supported in this build and may cause several
|
||||
+# problems.
|
||||
#UsePAM no
|
||||
|
||||
|
||||
@ -23,23 +23,20 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c
|
||||
if ((style = strchr(user, ':')) != NULL)
|
||||
*style++ = 0;
|
||||
|
||||
@@ -296,8 +304,15 @@ input_userauth_request(int type, u_int32
|
||||
use_privsep ? " [net]" : "");
|
||||
@@ -314,7 +314,13 @@ input_userauth_request(int type, u_int32
|
||||
setproctitle("%s [net]", authctxt->valid ? user : "unknown");
|
||||
authctxt->service = xstrdup(service);
|
||||
authctxt->style = style ? xstrdup(style) : NULL;
|
||||
- if (use_privsep)
|
||||
+#ifdef WITH_SELINUX
|
||||
+ authctxt->role = role ? xstrdup(role) : NULL;
|
||||
+#endif
|
||||
+ if (use_privsep) {
|
||||
mm_inform_authserv(service, style);
|
||||
mm_inform_authserv(service, style);
|
||||
+#ifdef WITH_SELINUX
|
||||
+ mm_inform_authrole(role);
|
||||
+ mm_inform_authrole(role);
|
||||
+#endif
|
||||
+ }
|
||||
userauth_banner(ssh);
|
||||
if (auth2_setup_methods_lists(authctxt) != 0)
|
||||
ssh_packet_disconnect(ssh,
|
||||
if ((r = kex_server_update_ext_info(ssh)) != 0)
|
||||
fatal_fr(r, "kex_server_update_ext_info failed");
|
||||
diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c
|
||||
--- openssh/auth2-gss.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||
+++ openssh/auth2-gss.c 2018-08-22 11:15:42.459799171 +0200
|
||||
@ -50,7 +47,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c
|
||||
+ char *micuser;
|
||||
struct sshbuf *b;
|
||||
gss_buffer_desc mic, gssbuf;
|
||||
const char *displayname;
|
||||
u_char *p;
|
||||
@@ -298,7 +299,13 @@ input_gssapi_mic(int type, u_int32_t ple
|
||||
fatal_f("sshbuf_new failed");
|
||||
mic.value = p;
|
||||
@ -74,7 +71,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c
|
||||
+ free(micuser);
|
||||
free(mic.value);
|
||||
|
||||
if ((!use_privsep || mm_is_monitor()) &&
|
||||
authctxt->postponed = 0;
|
||||
diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c
|
||||
--- openssh/auth2-hostbased.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||
+++ openssh/auth2-hostbased.c 2018-08-22 11:14:56.816430924 +0200
|
||||
@ -93,7 +90,7 @@ diff -up openssh/auth2-hostbased.c.role-mls openssh/auth2-hostbased.c
|
||||
(r = sshbuf_put_cstring(b, authctxt->user)) != 0 ||
|
||||
+#endif
|
||||
(r = sshbuf_put_cstring(b, authctxt->service)) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, "hostbased")) != 0 ||
|
||||
(r = sshbuf_put_cstring(b, method)) != 0 ||
|
||||
(r = sshbuf_put_string(b, pkalg, alen)) != 0 ||
|
||||
diff -up openssh/auth2-pubkey.c.role-mls openssh/auth2-pubkey.c
|
||||
--- openssh/auth2-pubkey.c.role-mls 2018-08-22 11:14:56.816430924 +0200
|
||||
@ -147,7 +144,7 @@ diff -up openssh/auth-pam.h.role-mls openssh/auth-pam.h
|
||||
+++ openssh/auth-pam.h 2018-08-22 11:14:56.817430932 +0200
|
||||
@@ -33,7 +33,7 @@ u_int do_pam_account(void);
|
||||
void do_pam_session(struct ssh *);
|
||||
void do_pam_setcred(int );
|
||||
void do_pam_setcred(void);
|
||||
void do_pam_chauthtok(void);
|
||||
-int do_pam_putenv(char *, char *);
|
||||
+int do_pam_putenv(char *, const char *);
|
||||
@ -240,14 +237,14 @@ diff -up openssh-8.6p1/monitor.c.role-mls openssh-8.6p1/monitor.c
|
||||
mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m)
|
||||
{
|
||||
@@ -1251,7 +1280,7 @@ monitor_valid_userblob(struct ssh *ssh,
|
||||
{
|
||||
struct sshbuf *b;
|
||||
struct sshkey *hostkey = NULL;
|
||||
const u_char *p;
|
||||
- char *userstyle, *cp;
|
||||
+ char *userstyle, *s, *cp;
|
||||
size_t len;
|
||||
u_char type;
|
||||
int r, fail = 0;
|
||||
int hostbound = 0, r, fail = 0;
|
||||
@@ -1282,6 +1311,8 @@ monitor_valid_userblob(struct ssh *ssh,
|
||||
fail++;
|
||||
if ((r = sshbuf_get_cstring(b, &cp, NULL)) != 0)
|
||||
@ -418,7 +415,7 @@ diff -up openssh/openbsd-compat/port-linux.h.role-mls openssh/openbsd-compat/por
|
||||
diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compat/port-linux-sshd.c
|
||||
--- openssh/openbsd-compat/port-linux-sshd.c.role-mls 2018-08-22 11:14:56.819430949 +0200
|
||||
+++ openssh/openbsd-compat/port-linux-sshd.c 2018-08-22 11:14:56.819430949 +0200
|
||||
@@ -0,0 +1,421 @@
|
||||
@@ -0,0 +1,420 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2005 Daniel Walsh <dwalsh@redhat.com>
|
||||
+ * Copyright (c) 2014 Petr Lautrbach <plautrba@redhat.com>
|
||||
@ -472,7 +469,6 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa
|
||||
+extern ServerOptions options;
|
||||
+extern Authctxt *the_authctxt;
|
||||
+extern int inetd_flag;
|
||||
+extern int rexeced_flag;
|
||||
+
|
||||
+/* Send audit message */
|
||||
+static int
|
||||
@ -678,7 +674,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa
|
||||
+
|
||||
+ if (r == 0) {
|
||||
+ /* If launched from xinetd, we must use current level */
|
||||
+ if (inetd_flag && !rexeced_flag) {
|
||||
+ if (inetd_flag) {
|
||||
+ security_context_t sshdsc=NULL;
|
||||
+
|
||||
+ if (getcon_raw(&sshdsc) < 0)
|
||||
@ -752,7 +748,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.role-mls openssh/openbsd-compa
|
||||
+
|
||||
+ rv = do_pam_putenv("SELINUX_ROLE_REQUESTED", role ? role : "");
|
||||
+
|
||||
+ if (inetd_flag && !rexeced_flag) {
|
||||
+ if (inetd_flag) {
|
||||
+ use_current = "1";
|
||||
+ } else {
|
||||
+ use_current = "";
|
||||
@ -853,8 +849,8 @@ diff -up openssh/platform.c.role-mls openssh/platform.c
|
||||
}
|
||||
|
||||
diff -up openssh/sshd.c.role-mls openssh/sshd.c
|
||||
--- openssh/sshd.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||
+++ openssh/sshd.c 2018-08-22 11:14:56.820430957 +0200
|
||||
--- openssh/sshd-session.c.role-mls 2018-08-20 07:57:29.000000000 +0200
|
||||
+++ openssh/sshd-session.c 2018-08-22 11:14:56.820430957 +0200
|
||||
@@ -2186,6 +2186,9 @@ main(int ac, char **av)
|
||||
restore_uid();
|
||||
}
|
||||
@ -864,4 +860,4 @@ diff -up openssh/sshd.c.role-mls openssh/sshd.c
|
||||
+#endif
|
||||
#ifdef USE_PAM
|
||||
if (options.use_pam) {
|
||||
do_pam_setcred(1);
|
||||
do_pam_setcred();
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
--- a/ssh_config.5 2022-07-12 15:05:22.550013071 +0200
|
||||
+++ b/ssh_config.5 2022-07-12 15:17:20.016704545 +0200
|
||||
@@ -373,17 +373,13 @@
|
||||
.Qq *.c.example.com
|
||||
domains.
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/ssh_config.5 openssh-9.3p1-patched/ssh_config.5
|
||||
--- openssh-9.3p1/ssh_config.5 2023-06-07 10:26:48.284590156 +0200
|
||||
+++ openssh-9.3p1-patched/ssh_config.5 2023-06-07 10:26:00.623052194 +0200
|
||||
@@ -378,17 +378,13 @@
|
||||
causes no CNAMEs to be considered for canonicalization.
|
||||
This is the default behaviour.
|
||||
.It Cm CASignatureAlgorithms
|
||||
+The default is handled system-wide by
|
||||
+.Xr crypto-policies 7 .
|
||||
@ -24,7 +24,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
If the specified list begins with a
|
||||
.Sq +
|
||||
character, then the specified algorithms will be appended to the default set
|
||||
@@ -445,20 +441,25 @@
|
||||
@@ -450,20 +446,25 @@
|
||||
(the default),
|
||||
the check will not be executed.
|
||||
.It Cm Ciphers
|
||||
@ -54,7 +54,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
.Pp
|
||||
The supported ciphers are:
|
||||
.Bd -literal -offset indent
|
||||
@@ -474,13 +475,6 @@
|
||||
@@ -479,13 +480,6 @@
|
||||
chacha20-poly1305@openssh.com
|
||||
.Ed
|
||||
.Pp
|
||||
@ -68,7 +68,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
The list of available ciphers may also be obtained using
|
||||
.Qq ssh -Q cipher .
|
||||
.It Cm ClearAllForwardings
|
||||
@@ -874,6 +868,11 @@
|
||||
@@ -885,6 +879,11 @@
|
||||
The default is
|
||||
.Dq no .
|
||||
.It Cm GSSAPIKexAlgorithms
|
||||
@ -80,7 +80,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
The list of key exchange algorithms that are offered for GSSAPI
|
||||
key exchange. Possible values are
|
||||
.Bd -literal -offset 3n
|
||||
@@ -886,10 +885,8 @@
|
||||
@@ -897,10 +896,8 @@
|
||||
gss-curve25519-sha256-
|
||||
.Ed
|
||||
.Pp
|
||||
@ -92,7 +92,70 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
.It Cm HashKnownHosts
|
||||
Indicates that
|
||||
.Xr ssh 1
|
||||
@@ -1219,29 +1216,25 @@
|
||||
@@ -919,36 +916,25 @@
|
||||
but may be manually hashed using
|
||||
.Xr ssh-keygen 1 .
|
||||
.It Cm HostbasedAcceptedAlgorithms
|
||||
+The default is handled system-wide by
|
||||
+.Xr crypto-policies 7 .
|
||||
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
|
||||
+.Xr update-crypto-policies 8 .
|
||||
+.Pp
|
||||
Specifies the signature algorithms that will be used for hostbased
|
||||
authentication as a comma-separated list of patterns.
|
||||
Alternately if the specified list begins with a
|
||||
.Sq +
|
||||
character, then the specified signature algorithms will be appended
|
||||
-to the default set instead of replacing them.
|
||||
+to the built-in openssh default set instead of replacing them.
|
||||
If the specified list begins with a
|
||||
.Sq -
|
||||
character, then the specified signature algorithms (including wildcards)
|
||||
-will be removed from the default set instead of replacing them.
|
||||
+will be removed from the built-in openssh default set instead of replacing them.
|
||||
If the specified list begins with a
|
||||
.Sq ^
|
||||
character, then the specified signature algorithms will be placed
|
||||
-at the head of the default set.
|
||||
-The default for this option is:
|
||||
-.Bd -literal -offset 3n
|
||||
-ssh-ed25519-cert-v01@openssh.com,
|
||||
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
|
||||
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
|
||||
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
|
||||
-sk-ssh-ed25519-cert-v01@openssh.com,
|
||||
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
|
||||
-rsa-sha2-512-cert-v01@openssh.com,
|
||||
-rsa-sha2-256-cert-v01@openssh.com,
|
||||
-ssh-ed25519,
|
||||
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
|
||||
-sk-ssh-ed25519@openssh.com,
|
||||
-sk-ecdsa-sha2-nistp256@openssh.com,
|
||||
-rsa-sha2-512,rsa-sha2-256
|
||||
-.Ed
|
||||
+at the head of the built-in openssh default set.
|
||||
.Pp
|
||||
The
|
||||
.Fl Q
|
||||
@@ -1001,6 +987,17 @@
|
||||
.Pp
|
||||
The list of available signature algorithms may also be obtained using
|
||||
.Qq ssh -Q HostKeyAlgorithms .
|
||||
+.Pp
|
||||
+The proposed
|
||||
+.Cm HostKeyAlgorithms
|
||||
+during KEX are limited to the set of algorithms that is defined in
|
||||
+.Cm PubkeyAcceptedAlgorithms
|
||||
+and therefore they are indirectly affected by system-wide
|
||||
+.Xr crypto_policies 7 .
|
||||
+.Xr crypto_policies 7 can not handle the list of host key algorithms directly as doing so
|
||||
+would break the order given by the
|
||||
+.Pa known_hosts
|
||||
+file.
|
||||
.It Cm HostKeyAlias
|
||||
Specifies an alias that should be used instead of the
|
||||
real host name when looking up or saving the host key
|
||||
@@ -1330,6 +1330,11 @@ it may be zero or more of:
|
||||
and
|
||||
.Cm pam .
|
||||
.It Cm KexAlgorithms
|
||||
@ -101,25 +164,31 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
|
||||
+.Xr update-crypto-policies 8 .
|
||||
+.Pp
|
||||
Specifies the available KEX (Key Exchange) algorithms.
|
||||
Multiple algorithms must be comma-separated.
|
||||
Specifies the permitted KEX (Key Exchange) algorithms that will be used and
|
||||
their preference order.
|
||||
The selected algorithm will be the first algorithm in this list that
|
||||
@@ -1338,29 +1343,17 @@ Multiple algorithms must be comma-separa
|
||||
.Pp
|
||||
If the specified list begins with a
|
||||
.Sq +
|
||||
-character, then the specified methods will be appended to the default set
|
||||
-character, then the specified algorithms will be appended to the default set
|
||||
-instead of replacing them.
|
||||
+character, then the specified methods will be appended to the built-in
|
||||
+openssh default set instead of replacing them.
|
||||
If the specified list begins with a
|
||||
.Sq -
|
||||
character, then the specified methods (including wildcards) will be removed
|
||||
character, then the specified algorithms (including wildcards) will be removed
|
||||
-from the default set instead of replacing them.
|
||||
+from the built-in openssh default set instead of replacing them.
|
||||
If the specified list begins with a
|
||||
.Sq ^
|
||||
character, then the specified methods will be placed at the head of the
|
||||
character, then the specified algorithms will be placed at the head of the
|
||||
-default set.
|
||||
-.Pp
|
||||
-The default is:
|
||||
-.Bd -literal -offset indent
|
||||
-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,
|
||||
-mlkem768x25519-sha256,
|
||||
-curve25519-sha256,curve25519-sha256@libssh.org,
|
||||
-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
|
||||
-diffie-hellman-group-exchange-sha256,
|
||||
@ -127,11 +196,12 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
-diffie-hellman-group18-sha512,
|
||||
-diffie-hellman-group14-sha256
|
||||
-.Ed
|
||||
+built-in openssh default set.
|
||||
.Pp
|
||||
The list of available key exchange algorithms may also be obtained using
|
||||
+built-in openssh default set.
|
||||
The list of supported key exchange algorithms may also be obtained using
|
||||
.Qq ssh -Q kex .
|
||||
@@ -1351,37 +1344,33 @@
|
||||
.It Cm KnownHostsCommand
|
||||
@@ -1365,37 +1357,33 @@
|
||||
file.
|
||||
This option is intended for debugging and no overrides are enabled by default.
|
||||
.It Cm MACs
|
||||
@ -178,7 +248,7 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
The list of available MAC algorithms may also be obtained using
|
||||
.Qq ssh -Q mac .
|
||||
.It Cm NoHostAuthenticationForLocalhost
|
||||
@@ -1553,37 +1542,25 @@
|
||||
@@ -1567,39 +1555,31 @@
|
||||
The default is
|
||||
.Cm no .
|
||||
.It Cm PubkeyAcceptedAlgorithms
|
||||
@ -214,21 +284,37 @@ diff --color -ru a/ssh_config.5 b/ssh_config.5
|
||||
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
|
||||
-rsa-sha2-512-cert-v01@openssh.com,
|
||||
-rsa-sha2-256-cert-v01@openssh.com,
|
||||
-ssh-rsa-cert-v01@openssh.com,
|
||||
-ssh-ed25519,
|
||||
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
|
||||
-sk-ssh-ed25519@openssh.com,
|
||||
-sk-ecdsa-sha2-nistp256@openssh.com,
|
||||
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
|
||||
-rsa-sha2-512,rsa-sha2-256
|
||||
-.Ed
|
||||
+built-in openssh default set.
|
||||
.Pp
|
||||
The list of available signature algorithms may also be obtained using
|
||||
.Qq ssh -Q PubkeyAcceptedAlgorithms .
|
||||
diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
--- a/sshd_config.5 2022-07-12 15:05:22.535012771 +0200
|
||||
+++ b/sshd_config.5 2022-07-12 15:15:33.394809258 +0200
|
||||
@@ -373,17 +373,13 @@
|
||||
+.Pp
|
||||
+This option affects also
|
||||
+.Cm HostKeyAlgorithms
|
||||
.It Cm PubkeyAuthentication
|
||||
Specifies whether to try public key authentication.
|
||||
The argument to this keyword must be
|
||||
@@ -2265,7 +2245,9 @@
|
||||
This file must be world-readable.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
-.Xr ssh 1
|
||||
+.Xr ssh 1 ,
|
||||
+.Xr crypto-policies 7 ,
|
||||
+.Xr update-crypto-policies 8
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
OpenSSH is a derivative of the original and free
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.3p1/sshd_config.5 openssh-9.3p1-patched/sshd_config.5
|
||||
--- openssh-9.3p1/sshd_config.5 2023-06-07 10:26:48.277590077 +0200
|
||||
+++ openssh-9.3p1-patched/sshd_config.5 2023-06-07 10:26:00.592051845 +0200
|
||||
@@ -379,17 +379,13 @@
|
||||
then no banner is displayed.
|
||||
By default, no banner is displayed.
|
||||
.It Cm CASignatureAlgorithms
|
||||
@ -251,7 +337,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
If the specified list begins with a
|
||||
.Sq +
|
||||
character, then the specified algorithms will be appended to the default set
|
||||
@@ -450,20 +446,25 @@
|
||||
@@ -525,20 +521,25 @@
|
||||
indicating not to
|
||||
.Xr chroot 2 .
|
||||
.It Cm Ciphers
|
||||
@ -281,7 +367,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
.Pp
|
||||
The supported ciphers are:
|
||||
.Pp
|
||||
@@ -490,13 +491,6 @@
|
||||
@@ -565,13 +566,6 @@
|
||||
chacha20-poly1305@openssh.com
|
||||
.El
|
||||
.Pp
|
||||
@ -295,7 +381,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
The list of available ciphers may also be obtained using
|
||||
.Qq ssh -Q cipher .
|
||||
.It Cm ClientAliveCountMax
|
||||
@@ -685,21 +679,22 @@
|
||||
@@ -766,53 +760,43 @@
|
||||
.Cm GSSAPIKeyExchange
|
||||
needs to be enabled in the server and also used by the client.
|
||||
.It Cm GSSAPIKexAlgorithms
|
||||
@ -327,18 +413,27 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- .
|
||||
This option only applies to connections using GSSAPI.
|
||||
.It Cm HostbasedAcceptedAlgorithms
|
||||
Specifies the signature algorithms that will be accepted for hostbased
|
||||
@@ -799,26 +794,13 @@
|
||||
.Ev SSH_AUTH_SOCK
|
||||
environment variable.
|
||||
.It Cm HostKeyAlgorithms
|
||||
+The default is handled system-wide by
|
||||
+.Xr crypto-policies 7 .
|
||||
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
|
||||
+.Xr update-crypto-policies 8 .
|
||||
+.Pp
|
||||
Specifies the host key signature algorithms
|
||||
that the server offers.
|
||||
Specifies the signature algorithms that will be accepted for hostbased
|
||||
authentication as a list of comma-separated patterns.
|
||||
Alternately if the specified list begins with a
|
||||
.Sq +
|
||||
character, then the specified signature algorithms will be appended to
|
||||
-the default set instead of replacing them.
|
||||
+the built-in openssh default set instead of replacing them.
|
||||
If the specified list begins with a
|
||||
.Sq -
|
||||
character, then the specified signature algorithms (including wildcards)
|
||||
-will be removed from the default set instead of replacing them.
|
||||
+will be removed from the built-in openssh default set instead of replacing them.
|
||||
If the specified list begins with a
|
||||
.Sq ^
|
||||
character, then the specified signature algorithms will be placed at
|
||||
-the head of the default set.
|
||||
-The default for this option is:
|
||||
-.Bd -literal -offset 3n
|
||||
-ssh-ed25519-cert-v01@openssh.com,
|
||||
@ -349,18 +444,48 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
|
||||
-rsa-sha2-512-cert-v01@openssh.com,
|
||||
-rsa-sha2-256-cert-v01@openssh.com,
|
||||
-ssh-rsa-cert-v01@openssh.com,
|
||||
-ssh-ed25519,
|
||||
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
|
||||
-sk-ssh-ed25519@openssh.com,
|
||||
-sk-ecdsa-sha2-nistp256@openssh.com,
|
||||
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
|
||||
-rsa-sha2-512,rsa-sha2-256
|
||||
-.Ed
|
||||
+the head of the built-in openssh default set.
|
||||
.Pp
|
||||
The list of available signature algorithms may also be obtained using
|
||||
.Qq ssh -Q HostbasedAcceptedAlgorithms .
|
||||
@@ -879,25 +863,14 @@
|
||||
.Ev SSH_AUTH_SOCK
|
||||
environment variable.
|
||||
.It Cm HostKeyAlgorithms
|
||||
+The default is handled system-wide by
|
||||
+.Xr crypto-policies 7 .
|
||||
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
|
||||
+.Xr update-crypto-policies 8 .
|
||||
+.Pp
|
||||
Specifies the host key signature algorithms
|
||||
that the server offers.
|
||||
The default for this option is:
|
||||
-.Bd -literal -offset 3n
|
||||
-ssh-ed25519-cert-v01@openssh.com,
|
||||
-ecdsa-sha2-nistp256-cert-v01@openssh.com,
|
||||
-ecdsa-sha2-nistp384-cert-v01@openssh.com,
|
||||
-ecdsa-sha2-nistp521-cert-v01@openssh.com,
|
||||
-sk-ssh-ed25519-cert-v01@openssh.com,
|
||||
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
|
||||
-rsa-sha2-512-cert-v01@openssh.com,
|
||||
-rsa-sha2-256-cert-v01@openssh.com,
|
||||
-ssh-ed25519,
|
||||
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
|
||||
-sk-ssh-ed25519@openssh.com,
|
||||
-sk-ecdsa-sha2-nistp256@openssh.com,
|
||||
-rsa-sha2-512,rsa-sha2-256
|
||||
-.Ed
|
||||
-.Pp
|
||||
The list of available signature algorithms may also be obtained using
|
||||
.Qq ssh -Q HostKeyAlgorithms .
|
||||
.It Cm IgnoreRhosts
|
||||
@@ -965,20 +947,25 @@
|
||||
@@ -1025,6 +1025,11 @@ Specifies whether to look at .k5login fi
|
||||
The default is
|
||||
.Cm yes .
|
||||
.It Cm KexAlgorithms
|
||||
@ -369,33 +494,38 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
+Information about defaults, how to modify the defaults and how to customize existing policies with sub-policies are present in manual page
|
||||
+.Xr update-crypto-policies 8 .
|
||||
+.Pp
|
||||
Specifies the available KEX (Key Exchange) algorithms.
|
||||
Multiple algorithms must be comma-separated.
|
||||
Alternately if the specified list begins with a
|
||||
Specifies the permitted KEX (Key Exchange) algorithms that the server will
|
||||
offer to clients.
|
||||
The ordering of this list is not important, as the client specifies the
|
||||
@@ -1033,16 +1038,16 @@ Multiple algorithms must be comma-separa
|
||||
.Pp
|
||||
If the specified list begins with a
|
||||
.Sq +
|
||||
-character, then the specified methods will be appended to the default set
|
||||
-character, then the specified algorithms will be appended to the default set
|
||||
-instead of replacing them.
|
||||
+character, then the specified methods will be appended to the built-in
|
||||
+openssh default set instead of replacing them.
|
||||
If the specified list begins with a
|
||||
.Sq -
|
||||
character, then the specified methods (including wildcards) will be removed
|
||||
character, then the specified algorithms (including wildcards) will be removed
|
||||
-from the default set instead of replacing them.
|
||||
+from the built-in openssh default set instead of replacing them.
|
||||
If the specified list begins with a
|
||||
.Sq ^
|
||||
character, then the specified methods will be placed at the head of the
|
||||
character, then the specified algorithms will be placed at the head of the
|
||||
-default set.
|
||||
+built-in openssh default set.
|
||||
.Pp
|
||||
The supported algorithms are:
|
||||
.Pp
|
||||
.Bl -item -compact -offset indent
|
||||
@@ -1010,15 +997,6 @@
|
||||
@@ -1075,17 +1080,6 @@ ecdh-sha2-nistp521
|
||||
sntrup761x25519-sha512@openssh.com
|
||||
.El
|
||||
.Pp
|
||||
-The default is:
|
||||
-.Bd -literal -offset indent
|
||||
-sntrup761x25519-sha512,sntrup761x25519-sha512@openssh.com,
|
||||
-mlkem768x25519-sha256,
|
||||
-curve25519-sha256,curve25519-sha256@libssh.org,
|
||||
-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
|
||||
-diffie-hellman-group-exchange-sha256,
|
||||
@ -403,10 +533,10 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
-diffie-hellman-group14-sha256
|
||||
-.Ed
|
||||
-.Pp
|
||||
The list of available key exchange algorithms may also be obtained using
|
||||
The list of supported key exchange algorithms may also be obtained using
|
||||
.Qq ssh -Q KexAlgorithms .
|
||||
.It Cm ListenAddress
|
||||
@@ -1104,21 +1082,26 @@
|
||||
@@ -1184,21 +1152,26 @@
|
||||
file.
|
||||
This option is intended for debugging and no overrides are enabled by default.
|
||||
.It Cm MACs
|
||||
@ -437,7 +567,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
.Pp
|
||||
The algorithms that contain
|
||||
.Qq -etm
|
||||
@@ -1161,15 +1144,6 @@
|
||||
@@ -1241,15 +1214,6 @@
|
||||
umac-128-etm@openssh.com
|
||||
.El
|
||||
.Pp
|
||||
@ -453,7 +583,7 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
The list of available MAC algorithms may also be obtained using
|
||||
.Qq ssh -Q mac .
|
||||
.It Cm Match
|
||||
@@ -1548,37 +1522,25 @@
|
||||
@@ -1633,36 +1597,25 @@
|
||||
The default is
|
||||
.Cm yes .
|
||||
.It Cm PubkeyAcceptedAlgorithms
|
||||
@ -489,14 +619,24 @@ diff --color -ru a/sshd_config.5 b/sshd_config.5
|
||||
-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com,
|
||||
-rsa-sha2-512-cert-v01@openssh.com,
|
||||
-rsa-sha2-256-cert-v01@openssh.com,
|
||||
-ssh-rsa-cert-v01@openssh.com,
|
||||
-ssh-ed25519,
|
||||
-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,
|
||||
-sk-ssh-ed25519@openssh.com,
|
||||
-sk-ecdsa-sha2-nistp256@openssh.com,
|
||||
-rsa-sha2-512,rsa-sha2-256,ssh-rsa
|
||||
-rsa-sha2-512,rsa-sha2-256
|
||||
-.Ed
|
||||
+built-in openssh default set.
|
||||
.Pp
|
||||
The list of available signature algorithms may also be obtained using
|
||||
.Qq ssh -Q PubkeyAcceptedAlgorithms .
|
||||
@@ -2131,7 +2084,9 @@
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr sftp-server 8 ,
|
||||
-.Xr sshd 8
|
||||
+.Xr sshd 8 ,
|
||||
+.Xr crypto-policies 7 ,
|
||||
+.Xr update-crypto-policies 8
|
||||
.Sh AUTHORS
|
||||
.An -nosplit
|
||||
OpenSSH is a derivative of the original and free
|
||||
|
||||
@ -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
@ -27,16 +27,15 @@ diff -up openssh-8.0p1/auth-pam.c.preserve-pam-errors openssh-8.0p1/auth-pam.c
|
||||
else if (sshpam_maxtries_reached)
|
||||
ssh_msg_send(ctxt->pam_csock, PAM_MAXTRIES, buffer);
|
||||
else
|
||||
@@ -856,10 +862,12 @@ sshpam_query(void *ctx, char **name, cha
|
||||
plen++;
|
||||
@@ -856,9 +862,11 @@ sshpam_query(void *ctx, char **name, cha
|
||||
free(msg);
|
||||
break;
|
||||
+ case PAM_USER_UNKNOWN:
|
||||
+ case PAM_PERM_DENIED:
|
||||
case PAM_ACCT_EXPIRED:
|
||||
+ sshpam_account_status = 0;
|
||||
+ /* FALLTHROUGH */
|
||||
case PAM_MAXTRIES:
|
||||
+ case PAM_USER_UNKNOWN:
|
||||
+ case PAM_PERM_DENIED:
|
||||
- if (type == PAM_ACCT_EXPIRED)
|
||||
- sshpam_account_status = 0;
|
||||
if (type == PAM_MAXTRIES)
|
||||
|
||||
@ -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
|
||||
@ -1,32 +0,0 @@
|
||||
diff --git a/servconf.c b/servconf.c
|
||||
index e16f9e90fc71..a3779a9d86ee 100644
|
||||
--- a/servconf.c
|
||||
+++ b/servconf.c
|
||||
@@ -1942,13 +1942,22 @@ process_server_config_line_depth(ServerOptions *options, char *line,
|
||||
fatal("%s line %d: %s missing argument.",
|
||||
filename, linenum, keyword);
|
||||
if (!*activep) {
|
||||
- arg = argv_next(&ac, &av);
|
||||
+ argv_consume(&ac);
|
||||
+ break;
|
||||
+ }
|
||||
+ found = 0;
|
||||
+ for (i = 0; i < options->num_subsystems; i++) {
|
||||
+ if (strcmp(arg, options->subsystem_name[i]) == 0) {
|
||||
+ found = 1;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ if (found) {
|
||||
+ debug("%s line %d: Subsystem '%s' already defined.",
|
||||
+ filename, linenum, arg);
|
||||
+ argv_consume(&ac);
|
||||
break;
|
||||
}
|
||||
- for (i = 0; i < options->num_subsystems; i++)
|
||||
- if (strcmp(arg, options->subsystem_name[i]) == 0)
|
||||
- fatal("%s line %d: Subsystem '%s' "
|
||||
- "already defined.", filename, linenum, arg);
|
||||
options->subsystem_name[options->num_subsystems] = xstrdup(arg);
|
||||
arg = argv_next(&ac, &av);
|
||||
if (!arg || *arg == '\0')
|
||||
@ -1,292 +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/dh.c openssh-8.7p1-patched/dh.c
|
||||
--- openssh-8.7p1/dh.c 2023-05-25 09:01:23.295627077 +0200
|
||||
+++ openssh-8.7p1-patched/dh.c 2023-05-25 09:00:56.519332820 +0200
|
||||
@@ -37,6 +37,9 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/fips.h>
|
||||
+#include <openssl/evp.h>
|
||||
+#include <openssl/core_names.h>
|
||||
+#include <openssl/param_build.h>
|
||||
|
||||
#include "dh.h"
|
||||
#include "pathnames.h"
|
||||
@@ -290,10 +293,15 @@
|
||||
int
|
||||
dh_gen_key(DH *dh, int need)
|
||||
{
|
||||
- int pbits;
|
||||
- const BIGNUM *dh_p, *pub_key;
|
||||
+ const BIGNUM *dh_p, *dh_g;
|
||||
+ BIGNUM *pub_key = NULL, *priv_key = NULL;
|
||||
+ EVP_PKEY *pkey = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ OSSL_PARAM *params = NULL;
|
||||
+ int pbits, r = 0;
|
||||
|
||||
- DH_get0_pqg(dh, &dh_p, NULL, NULL);
|
||||
+ DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
|
||||
|
||||
if (need < 0 || dh_p == NULL ||
|
||||
(pbits = BN_num_bits(dh_p)) <= 0 ||
|
||||
@@ -301,19 +309,85 @@
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (need < 256)
|
||||
need = 256;
|
||||
+
|
||||
+ if ((param_bld = OSSL_PARAM_BLD_new()) == NULL ||
|
||||
+ (ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL) {
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ return SSH_ERR_ALLOC_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_FFC_P, dh_p) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_FFC_G, dh_g) != 1) {
|
||||
+ error_f("Could not set p,q,g parameters");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
/*
|
||||
* Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
|
||||
* so double requested need here.
|
||||
*/
|
||||
- if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1)))
|
||||
- return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
-
|
||||
- if (DH_generate_key(dh) == 0)
|
||||
- return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
- DH_get0_key(dh, &pub_key, NULL);
|
||||
- if (!dh_pub_is_valid(dh, pub_key))
|
||||
- return SSH_ERR_INVALID_FORMAT;
|
||||
- return 0;
|
||||
+ if (OSSL_PARAM_BLD_push_int(param_bld,
|
||||
+ OSSL_PKEY_PARAM_DH_PRIV_LEN,
|
||||
+ MINIMUM(need * 2, pbits - 1)) != 1 ||
|
||||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_fromdata_init(ctx) != 1) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_fromdata(ctx, &pkey,
|
||||
+ EVP_PKEY_KEY_PARAMETERS, params) != 1) {
|
||||
+ error_f("Failed key generation");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* reuse context for key generation */
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ ctx = NULL;
|
||||
+
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
|
||||
+ EVP_PKEY_keygen_init(ctx) != 1) {
|
||||
+ error_f("Could not create or init context");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_generate(ctx, &pkey) != 1) {
|
||||
+ error_f("Could not generate keys");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_public_check(ctx) != 1) {
|
||||
+ error_f("The public key is incorrect");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
|
||||
+ &pub_key) != 1 ||
|
||||
+ EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
|
||||
+ &priv_key) != 1 ||
|
||||
+ DH_set0_key(dh, pub_key, priv_key) != 1) {
|
||||
+ error_f("Could not set pub/priv keys to DH struct");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* transferred */
|
||||
+ pub_key = NULL;
|
||||
+ priv_key = NULL;
|
||||
+out:
|
||||
+ OSSL_PARAM_free(params);
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ BN_clear_free(pub_key);
|
||||
+ BN_clear_free(priv_key);
|
||||
+ return r;
|
||||
}
|
||||
|
||||
DH *
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/kex.c openssh-8.7p1-patched/kex.c
|
||||
--- openssh-8.7p1/kex.c 2023-05-25 09:01:23.299627122 +0200
|
||||
+++ openssh-8.7p1-patched/kex.c 2023-05-25 09:00:56.519332820 +0200
|
||||
@@ -1603,3 +1603,47 @@
|
||||
return r;
|
||||
}
|
||||
|
||||
+#ifdef WITH_OPENSSL
|
||||
+/*
|
||||
+ * Creates an EVP_PKEY from the given parameters and keys.
|
||||
+ * The private key can be omitted.
|
||||
+ */
|
||||
+int
|
||||
+kex_create_evp_dh(EVP_PKEY **pkey, const BIGNUM *p, const BIGNUM *q,
|
||||
+ const BIGNUM *g, const BIGNUM *pub, const BIGNUM *priv)
|
||||
+{
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ int r = 0;
|
||||
+
|
||||
+ /* create EVP_PKEY-DH key */
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL ||
|
||||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL) {
|
||||
+ error_f("EVP_PKEY_CTX or PARAM_BLD init failed");
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_PUB_KEY, pub) != 1) {
|
||||
+ error_f("Failed pushing params to OSSL_PARAM_BLD");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (priv != NULL &&
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) {
|
||||
+ error_f("Failed pushing private key to OSSL_PARAM_BLD");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL)
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+out:
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ return r;
|
||||
+}
|
||||
+#endif /* WITH_OPENSSL */
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/kexdh.c openssh-8.7p1-patched/kexdh.c
|
||||
--- openssh-8.7p1/kexdh.c 2023-05-25 09:01:23.237626425 +0200
|
||||
+++ openssh-8.7p1-patched/kexdh.c 2023-05-25 09:03:21.817957988 +0200
|
||||
@@ -35,6 +35,10 @@
|
||||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
#include <openssl/dh.h>
|
||||
+#include <openssl/err.h>
|
||||
+#include <openssl/evp.h>
|
||||
+#include <openssl/core_names.h>
|
||||
+#include <openssl/param_build.h>
|
||||
|
||||
#include "sshkey.h"
|
||||
#include "kex.h"
|
||||
@@ -83,9 +87,12 @@
|
||||
kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
|
||||
{
|
||||
BIGNUM *shared_secret = NULL;
|
||||
+ const BIGNUM *pub, *priv, *p, *q, *g;
|
||||
+ EVP_PKEY *pkey = NULL, *dh_pkey = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
u_char *kbuf = NULL;
|
||||
size_t klen = 0;
|
||||
- int kout, r;
|
||||
+ int kout, r = 0;
|
||||
|
||||
#ifdef DEBUG_KEXDH
|
||||
fprintf(stderr, "dh_pub= ");
|
||||
@@ -100,24 +107,59 @@
|
||||
r = SSH_ERR_MESSAGE_INCOMPLETE;
|
||||
goto out;
|
||||
}
|
||||
- klen = DH_size(kex->dh);
|
||||
+
|
||||
+ DH_get0_key(kex->dh, &pub, &priv);
|
||||
+ DH_get0_pqg(kex->dh, &p, &q, &g);
|
||||
+ /* import key */
|
||||
+ r = kex_create_evp_dh(&pkey, p, q, g, pub, priv);
|
||||
+ if (r != 0) {
|
||||
+ error_f("Could not create EVP_PKEY for dh");
|
||||
+ ERR_print_errors_fp(stderr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* import peer key
|
||||
+ * the parameters should be the same as with pkey
|
||||
+ */
|
||||
+ r = kex_create_evp_dh(&dh_pkey, p, q, g, dh_pub, NULL);
|
||||
+ if (r != 0) {
|
||||
+ error_f("Could not import peer key for dh");
|
||||
+ ERR_print_errors_fp(stderr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL) {
|
||||
+ error_f("Could not init EVP_PKEY_CTX for dh");
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_derive_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 ||
|
||||
+ EVP_PKEY_derive(ctx, NULL, &klen) != 1) {
|
||||
+ error_f("Could not get key size");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
if ((kbuf = malloc(klen)) == NULL ||
|
||||
(shared_secret = BN_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
- if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
|
||||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
|
||||
+ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1 ||
|
||||
+ BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
|
||||
+ error_f("Could not derive key");
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_KEXDH
|
||||
- dump_digest("shared secret", kbuf, kout);
|
||||
+ dump_digest("shared secret", kbuf, klen);
|
||||
#endif
|
||||
r = sshbuf_put_bignum2(out, shared_secret);
|
||||
out:
|
||||
freezero(kbuf, klen);
|
||||
BN_clear_free(shared_secret);
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_free(dh_pkey);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-8.7p1/kex.h openssh-8.7p1-patched/kex.h
|
||||
--- openssh-8.7p1/kex.h 2023-05-25 09:01:23.299627122 +0200
|
||||
+++ openssh-8.7p1-patched/kex.h 2023-05-25 09:00:56.519332820 +0200
|
||||
@@ -33,6 +33,9 @@
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/dh.h>
|
||||
# include <openssl/ecdsa.h>
|
||||
+# include <openssl/evp.h>
|
||||
+# include <openssl/core_names.h>
|
||||
+# include <openssl/param_build.h>
|
||||
# ifdef OPENSSL_HAS_ECC
|
||||
# include <openssl/ec.h>
|
||||
# else /* OPENSSL_HAS_ECC */
|
||||
@@ -278,6 +281,8 @@
|
||||
const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int)
|
||||
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
|
||||
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
|
||||
+int kex_create_evp_dh(EVP_PKEY **, const BIGNUM *, const BIGNUM *,
|
||||
+ const BIGNUM *, const BIGNUM *, const BIGNUM *);
|
||||
|
||||
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
|
||||
void dump_digest(const char *, const u_char *, int);
|
||||
@ -1,207 +0,0 @@
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../openssh-8.7p1/kexecdh.c ./kexecdh.c
|
||||
--- ../openssh-8.7p1/kexecdh.c 2021-08-20 06:03:49.000000000 +0200
|
||||
+++ ./kexecdh.c 2023-04-13 14:30:14.882449593 +0200
|
||||
@@ -35,17 +35,57 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include <openssl/ecdh.h>
|
||||
+#include <openssl/evp.h>
|
||||
+#include <openssl/core_names.h>
|
||||
+#include <openssl/param_build.h>
|
||||
+#include <openssl/err.h>
|
||||
|
||||
#include "sshkey.h"
|
||||
#include "kex.h"
|
||||
#include "sshbuf.h"
|
||||
#include "digest.h"
|
||||
#include "ssherr.h"
|
||||
+#include "log.h"
|
||||
|
||||
static int
|
||||
kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key,
|
||||
const EC_GROUP *, struct sshbuf **);
|
||||
|
||||
+static EC_KEY *
|
||||
+generate_ec_keys(int ec_nid)
|
||||
+{
|
||||
+ EC_KEY *client_key = NULL;
|
||||
+ EVP_PKEY *pkey = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ OSSL_PARAM *params = NULL;
|
||||
+ const char *group_name;
|
||||
+
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL ||
|
||||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL)
|
||||
+ goto out;
|
||||
+ if ((group_name = OSSL_EC_curve_nid2name(ec_nid)) == NULL ||
|
||||
+ OSSL_PARAM_BLD_push_utf8_string(param_bld,
|
||||
+ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 ||
|
||||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
|
||||
+ error_f("Could not create OSSL_PARAM");
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_keygen_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_CTX_set_params(ctx, params) != 1 ||
|
||||
+ EVP_PKEY_generate(ctx, &pkey) != 1 ||
|
||||
+ (client_key = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
|
||||
+ error_f("Could not generate ec keys");
|
||||
+ goto out;
|
||||
+ }
|
||||
+out:
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ OSSL_PARAM_free(params);
|
||||
+ return client_key;
|
||||
+}
|
||||
+
|
||||
int
|
||||
kex_ecdh_keypair(struct kex *kex)
|
||||
{
|
||||
@@ -55,11 +95,7 @@
|
||||
struct sshbuf *buf = NULL;
|
||||
int r;
|
||||
|
||||
- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
|
||||
- r = SSH_ERR_ALLOC_FAIL;
|
||||
- goto out;
|
||||
- }
|
||||
- if (EC_KEY_generate_key(client_key) != 1) {
|
||||
+ if ((client_key = generate_ec_keys(kex->ec_nid)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
@@ -101,11 +137,7 @@
|
||||
*server_blobp = NULL;
|
||||
*shared_secretp = NULL;
|
||||
|
||||
- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
|
||||
- r = SSH_ERR_ALLOC_FAIL;
|
||||
- goto out;
|
||||
- }
|
||||
- if (EC_KEY_generate_key(server_key) != 1) {
|
||||
+ if ((server_key = generate_ec_keys(kex->ec_nid)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
@@ -140,11 +172,21 @@
|
||||
{
|
||||
struct sshbuf *buf = NULL;
|
||||
BIGNUM *shared_secret = NULL;
|
||||
- EC_POINT *dh_pub = NULL;
|
||||
- u_char *kbuf = NULL;
|
||||
- size_t klen = 0;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ EVP_PKEY *pkey = NULL, *dh_pkey = NULL;
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ OSSL_PARAM *params = NULL;
|
||||
+ u_char *kbuf = NULL, *pub = NULL;
|
||||
+ size_t klen = 0, publen;
|
||||
+ const char *group_name;
|
||||
int r;
|
||||
|
||||
+ /* import EC_KEY to EVP_PKEY */
|
||||
+ if ((r = ssh_create_evp_ec(key, kex->ec_nid, &pkey)) != 0) {
|
||||
+ error_f("Could not create EVP_PKEY");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
*shared_secretp = NULL;
|
||||
|
||||
if ((buf = sshbuf_new()) == NULL) {
|
||||
@@ -153,45 +195,82 @@
|
||||
}
|
||||
if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0)
|
||||
goto out;
|
||||
- if ((dh_pub = EC_POINT_new(group)) == NULL) {
|
||||
+
|
||||
+ /* the public key is in the buffer in octet string UNCOMPRESSED
|
||||
+ * format. See sshbuf_put_ec */
|
||||
+ if ((r = sshbuf_get_string(buf, &pub, &publen)) != 0)
|
||||
+ goto out;
|
||||
+ sshbuf_reset(buf);
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
|
||||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
- if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) {
|
||||
+ if ((group_name = OSSL_EC_curve_nid2name(kex->ec_nid)) == NULL) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (OSSL_PARAM_BLD_push_octet_string(param_bld,
|
||||
+ OSSL_PKEY_PARAM_PUB_KEY, pub, publen) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_utf8_string(param_bld,
|
||||
+ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 ||
|
||||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
|
||||
+ error_f("Failed to set params for dh_pkey");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_fromdata_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_fromdata(ctx, &dh_pkey,
|
||||
+ EVP_PKEY_PUBLIC_KEY, params) != 1 ||
|
||||
+ EVP_PKEY_public_check(ctx) != 1) {
|
||||
+ error_f("Peer public key import failed");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
- sshbuf_reset(buf);
|
||||
|
||||
#ifdef DEBUG_KEXECDH
|
||||
fputs("public key:\n", stderr);
|
||||
- sshkey_dump_ec_point(group, dh_pub);
|
||||
+ EVP_PKEY_print_public_fp(stderr, dh_pkey, 0, NULL);
|
||||
#endif
|
||||
- if (sshkey_ec_validate_public(group, dh_pub) != 0) {
|
||||
- r = SSH_ERR_MESSAGE_INCOMPLETE;
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ ctx = NULL;
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
|
||||
+ EVP_PKEY_derive_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 ||
|
||||
+ EVP_PKEY_derive(ctx, NULL, &klen) != 1) {
|
||||
+ error_f("Failed to get derive information");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
- klen = (EC_GROUP_get_degree(group) + 7) / 8;
|
||||
- if ((kbuf = malloc(klen)) == NULL ||
|
||||
- (shared_secret = BN_new()) == NULL) {
|
||||
+ if ((kbuf = malloc(klen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
- if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen ||
|
||||
- BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
|
||||
+ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_KEXECDH
|
||||
dump_digest("shared secret", kbuf, klen);
|
||||
#endif
|
||||
+ if ((shared_secret = BN_new()) == NULL ||
|
||||
+ (BN_bin2bn(kbuf, klen, shared_secret) == NULL)) {
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0)
|
||||
goto out;
|
||||
*shared_secretp = buf;
|
||||
buf = NULL;
|
||||
out:
|
||||
- EC_POINT_clear_free(dh_pub);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_free(dh_pkey);
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ OSSL_PARAM_free(params);
|
||||
BN_clear_free(shared_secret);
|
||||
freezero(kbuf, klen);
|
||||
+ freezero(pub, publen);
|
||||
sshbuf_free(buf);
|
||||
return r;
|
||||
}
|
||||
@ -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);
|
||||
|
||||
@ -4,9 +4,8 @@
|
||||
|
||||
#include "includes.h"
|
||||
|
||||
-#ifndef HAVE_CLOSEFROM
|
||||
+#if (!defined HAVE_CLOSEFROM) || (defined __s390__)
|
||||
-#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM)
|
||||
+#if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) || (defined __s390__)
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
@ -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
|
||||
index 7f26c680..42be690b 100644
|
||||
--- a/readconf.c
|
||||
+++ b/readconf.c
|
||||
@@ -174,7 +174,7 @@ typedef enum {
|
||||
oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
|
||||
oFingerprintHash, oUpdateHostkeys, oHostbasedAcceptedAlgorithms,
|
||||
oPubkeyAcceptedAlgorithms, oCASignatureAlgorithms, oProxyJump,
|
||||
- oSecurityKeyProvider, oKnownHostsCommand,
|
||||
+ oSecurityKeyProvider, oKnownHostsCommand, oRequiredRSASize,
|
||||
oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
|
||||
} OpCodes;
|
||||
|
||||
@@ -320,6 +320,8 @@ static struct {
|
||||
{ "proxyjump", oProxyJump },
|
||||
--- a/readconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||
+++ b/readconf.c (date 1703169891147)
|
||||
@@ -326,6 +326,7 @@
|
||||
{ "securitykeyprovider", oSecurityKeyProvider },
|
||||
{ "knownhostscommand", oKnownHostsCommand },
|
||||
+ { "requiredrsasize", oRequiredRSASize },
|
||||
{ "requiredrsasize", oRequiredRSASize },
|
||||
+ { "rsaminsize", oRequiredRSASize }, /* alias */
|
||||
|
||||
{ NULL, oBadOption }
|
||||
};
|
||||
@@ -2176,6 +2177,10 @@ parse_pubkey_algos:
|
||||
*charptr = xstrdup(arg);
|
||||
break;
|
||||
|
||||
+ case oRequiredRSASize:
|
||||
+ intptr = &options->required_rsa_size;
|
||||
+ goto parse_int;
|
||||
+
|
||||
case oDeprecated:
|
||||
debug("%s line %d: Deprecated option \"%s\"",
|
||||
filename, linenum, keyword);
|
||||
@@ -2423,6 +2428,7 @@ initialize_options(Options * options)
|
||||
options->hostbased_accepted_algos = NULL;
|
||||
options->pubkey_accepted_algos = NULL;
|
||||
options->known_hosts_command = NULL;
|
||||
+ options->required_rsa_size = -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2619,6 +2625,8 @@ fill_default_options(Options * options)
|
||||
if (options->sk_provider == NULL)
|
||||
options->sk_provider = xstrdup("$SSH_SK_PROVIDER");
|
||||
#endif
|
||||
+ if (options->required_rsa_size == -1)
|
||||
+ options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
|
||||
|
||||
/* Expand KEX name lists */
|
||||
all_cipher = cipher_alg_list(',', 0);
|
||||
@@ -3308,6 +3316,7 @@ dump_client_config(Options *o, const char *host)
|
||||
dump_cfg_int(oNumberOfPasswordPrompts, o->number_of_password_prompts);
|
||||
dump_cfg_int(oServerAliveCountMax, o->server_alive_count_max);
|
||||
dump_cfg_int(oServerAliveInterval, o->server_alive_interval);
|
||||
+ dump_cfg_int(oRequiredRSASize, o->required_rsa_size);
|
||||
|
||||
/* String options */
|
||||
dump_cfg_string(oBindAddress, o->bind_address);
|
||||
diff --git a/readconf.h b/readconf.h
|
||||
index f647bd42..ffb5ec4f 100644
|
||||
--- a/readconf.h
|
||||
+++ b/readconf.h
|
||||
@@ -176,6 +176,8 @@ typedef struct {
|
||||
|
||||
char *known_hosts_command;
|
||||
|
||||
+ int required_rsa_size; /* minimum size of RSA keys */
|
||||
+
|
||||
char *ignored_unknown; /* Pattern list of unknown tokens to ignore */
|
||||
} Options;
|
||||
|
||||
{ "enableescapecommandline", oEnableEscapeCommandline },
|
||||
{ "obscurekeystroketiming", oObscureKeystrokeTiming },
|
||||
{ "channeltimeout", oChannelTimeout },
|
||||
diff --git a/servconf.c b/servconf.c
|
||||
index 29df0463..423772b1 100644
|
||||
--- a/servconf.c
|
||||
+++ b/servconf.c
|
||||
@@ -195,6 +195,7 @@ initialize_server_options(ServerOptions *options)
|
||||
options->fingerprint_hash = -1;
|
||||
options->disable_forwarding = -1;
|
||||
options->expose_userauth_info = -1;
|
||||
+ options->required_rsa_size = -1;
|
||||
}
|
||||
|
||||
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
|
||||
@@ -441,6 +442,8 @@ fill_default_server_options(ServerOptions *options)
|
||||
options->expose_userauth_info = 0;
|
||||
if (options->sk_provider == NULL)
|
||||
options->sk_provider = xstrdup("internal");
|
||||
+ if (options->required_rsa_size == -1)
|
||||
+ options->required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
|
||||
|
||||
assemble_algorithms(options);
|
||||
|
||||
@@ -517,6 +520,7 @@ typedef enum {
|
||||
sStreamLocalBindMask, sStreamLocalBindUnlink,
|
||||
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
|
||||
sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
|
||||
+ sRequiredRSASize,
|
||||
sDeprecated, sIgnore, sUnsupported
|
||||
} ServerOpCodes;
|
||||
|
||||
@@ -676,6 +680,8 @@ static struct {
|
||||
{ "rdomain", sRDomain, SSHCFG_ALL },
|
||||
--- a/servconf.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||
+++ b/servconf.c (date 1703169891148)
|
||||
@@ -691,6 +691,7 @@
|
||||
{ "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
|
||||
{ "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL },
|
||||
+ { "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
|
||||
{ "requiredrsasize", sRequiredRSASize, SSHCFG_ALL },
|
||||
+ { "rsaminsize", sRequiredRSASize, SSHCFG_ALL }, /* alias */
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
|
||||
@@ -2438,6 +2443,10 @@ process_server_config_line_depth(ServerOptions *options, char *line,
|
||||
*charptr = xstrdup(arg);
|
||||
break;
|
||||
|
||||
+ case sRequiredRSASize:
|
||||
+ intptr = &options->required_rsa_size;
|
||||
+ goto parse_int;
|
||||
+
|
||||
case sDeprecated:
|
||||
case sIgnore:
|
||||
case sUnsupported:
|
||||
@@ -2610,6 +2619,7 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
|
||||
M_CP_INTOPT(rekey_limit);
|
||||
M_CP_INTOPT(rekey_interval);
|
||||
M_CP_INTOPT(log_level);
|
||||
+ M_CP_INTOPT(required_rsa_size);
|
||||
|
||||
/*
|
||||
* The bind_mask is a mode_t that may be unsigned, so we can't use
|
||||
@@ -2874,6 +2884,7 @@ dump_config(ServerOptions *o)
|
||||
dump_cfg_int(sMaxSessions, o->max_sessions);
|
||||
dump_cfg_int(sClientAliveInterval, o->client_alive_interval);
|
||||
dump_cfg_int(sClientAliveCountMax, o->client_alive_count_max);
|
||||
+ dump_cfg_int(sRequiredRSASize, o->required_rsa_size);
|
||||
dump_cfg_oct(sStreamLocalBindMask, o->fwd_opts.streamlocal_bind_mask);
|
||||
|
||||
/* formatted integer arguments */
|
||||
diff --git a/servconf.h b/servconf.h
|
||||
index 8a04463e..9346155c 100644
|
||||
--- a/servconf.h
|
||||
+++ b/servconf.h
|
||||
@@ -229,6 +229,7 @@ typedef struct {
|
||||
int expose_userauth_info;
|
||||
u_int64_t timing_secret;
|
||||
char *sk_provider;
|
||||
+ int required_rsa_size; /* minimum size of RSA keys */
|
||||
} ServerOptions;
|
||||
|
||||
/* Information about the incoming connection as used by Match */
|
||||
diff --git a/ssh.c b/ssh.c
|
||||
index 559bf2af..25be53d5 100644
|
||||
--- a/ssh.c
|
||||
+++ b/ssh.c
|
||||
@@ -516,14 +516,22 @@ resolve_canonicalize(char **hostp, int port)
|
||||
}
|
||||
|
||||
/*
|
||||
- * Check the result of hostkey loading, ignoring some errors and
|
||||
- * fatal()ing for others.
|
||||
+ * Check the result of hostkey loading, ignoring some errors and either
|
||||
+ * discarding the key or fatal()ing for others.
|
||||
*/
|
||||
static void
|
||||
-check_load(int r, const char *path, const char *message)
|
||||
+check_load(int r, struct sshkey **k, const char *path, const char *message)
|
||||
{
|
||||
switch (r) {
|
||||
case 0:
|
||||
+ /* Check RSA keys size and discard if undersized */
|
||||
+ if (k != NULL && *k != NULL &&
|
||||
+ (r = sshkey_check_rsa_length(*k,
|
||||
+ options.required_rsa_size)) != 0) {
|
||||
+ error_r(r, "load %s \"%s\"", message, path);
|
||||
+ free(*k);
|
||||
+ *k = NULL;
|
||||
+ }
|
||||
break;
|
||||
case SSH_ERR_INTERNAL_ERROR:
|
||||
case SSH_ERR_ALLOC_FAIL:
|
||||
@@ -1578,7 +1586,7 @@ main(int ac, char **av)
|
||||
if ((o) >= sensitive_data.nkeys) \
|
||||
fatal_f("pubkey out of array bounds"); \
|
||||
check_load(sshkey_load_public(p, &(sensitive_data.keys[o]), NULL), \
|
||||
- p, "pubkey"); \
|
||||
+ &(sensitive_data.keys[o]), p, "pubkey"); \
|
||||
} while (0)
|
||||
#define L_CERT(p,o) do { \
|
||||
if ((o) >= sensitive_data.nkeys) \
|
||||
@@ -1586,7 +1594,8 @@ main(int ac, char **av)
|
||||
#define L_CERT(p,o) do { \
|
||||
if ((o) >= sensitive_data.nkeys) \
|
||||
fatal_f("cert out of array bounds"); \
|
||||
- check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), p, "cert"); \
|
||||
+ check_load(sshkey_load_cert(p, &(sensitive_data.keys[o])), \
|
||||
+ &(sensitive_data.keys[o]), p, "cert"); \
|
||||
} while (0)
|
||||
|
||||
if (options.hostbased_authentication == 1) {
|
||||
@@ -2244,7 +2253,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
|
||||
filename = default_client_percent_dollar_expand(cp, cinfo);
|
||||
free(cp);
|
||||
check_load(sshkey_load_public(filename, &public, NULL),
|
||||
- filename, "pubkey");
|
||||
+ &public, filename, "pubkey");
|
||||
debug("identity file %s type %d", filename,
|
||||
public ? public->type : -1);
|
||||
free(options.identity_files[i]);
|
||||
@@ -2284,7 +2293,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
|
||||
continue;
|
||||
xasprintf(&cp, "%s-cert", filename);
|
||||
check_load(sshkey_load_public(cp, &public, NULL),
|
||||
- filename, "pubkey");
|
||||
+ &public, filename, "pubkey");
|
||||
debug("identity file %s type %d", cp,
|
||||
public ? public->type : -1);
|
||||
if (public == NULL) {
|
||||
@@ -2315,7 +2324,7 @@ load_public_identity_files(const struct ssh_conn_info *cinfo)
|
||||
free(cp);
|
||||
|
||||
check_load(sshkey_load_public(filename, &public, NULL),
|
||||
- filename, "certificate");
|
||||
+ &public, filename, "certificate");
|
||||
debug("certificate file %s type %d", filename,
|
||||
public ? public->type : -1);
|
||||
free(options.certificate_files[i]);
|
||||
diff --git a/sshconnect2.c b/sshconnect2.c
|
||||
index f9bd19ea..58fe98db 100644
|
||||
--- a/sshconnect2.c
|
||||
+++ b/sshconnect2.c
|
||||
@@ -96,6 +96,11 @@ static const struct ssh_conn_info *xxx_conn_info;
|
||||
static int
|
||||
verify_host_key_callback(struct sshkey *hostkey, struct ssh *ssh)
|
||||
{
|
||||
+ int r;
|
||||
+
|
||||
+ if ((r = sshkey_check_rsa_length(hostkey,
|
||||
+ options.required_rsa_size)) != 0)
|
||||
+ fatal_r(r, "Bad server host key");
|
||||
if (verify_host_key(xxx_host, xxx_hostaddr, hostkey,
|
||||
xxx_conn_info) == -1)
|
||||
fatal("Host key verification failed.");
|
||||
@@ -1606,6 +1611,13 @@ load_identity_file(Identity *id)
|
||||
private = NULL;
|
||||
quit = 1;
|
||||
}
|
||||
+ if (!quit && (r = sshkey_check_rsa_length(private,
|
||||
+ options.required_rsa_size)) != 0) {
|
||||
+ debug_fr(r, "Skipping key %s", id->filename);
|
||||
+ sshkey_free(private);
|
||||
+ private = NULL;
|
||||
+ quit = 1;
|
||||
+ }
|
||||
if (!quit && private != NULL && id->agent_fd == -1 &&
|
||||
!(id->key && id->isprivate))
|
||||
maybe_add_key_to_agent(id->filename, private, comment,
|
||||
@@ -1752,6 +1764,12 @@ pubkey_prepare(struct ssh *ssh, Authctxt *authctxt)
|
||||
close(agent_fd);
|
||||
} else {
|
||||
for (j = 0; j < idlist->nkeys; j++) {
|
||||
+ if ((r = sshkey_check_rsa_length(idlist->keys[j],
|
||||
+ options.required_rsa_size)) != 0) {
|
||||
+ debug_fr(r, "ignoring %s agent key",
|
||||
+ sshkey_ssh_name(idlist->keys[j]));
|
||||
+ continue;
|
||||
+ }
|
||||
found = 0;
|
||||
TAILQ_FOREACH(id, &files, next) {
|
||||
/*
|
||||
diff --git a/sshd.c b/sshd.c
|
||||
index 17eee9d8..395ef493 100644
|
||||
--- a/sshd.c
|
||||
+++ b/sshd.c
|
||||
@@ -1870,6 +1870,13 @@ main(int ac, char **av)
|
||||
fatal_r(r, "Could not demote key: \"%s\"",
|
||||
options.host_key_files[i]);
|
||||
}
|
||||
+ if (pubkey != NULL && (r = sshkey_check_rsa_length(pubkey,
|
||||
+ options.required_rsa_size)) != 0) {
|
||||
+ error_fr(r, "Host key %s", options.host_key_files[i]);
|
||||
+ sshkey_free(pubkey);
|
||||
+ sshkey_free(key);
|
||||
+ continue;
|
||||
+ }
|
||||
sensitive_data.host_keys[i] = key;
|
||||
sensitive_data.host_pubkeys[i] = pubkey;
|
||||
|
||||
diff --git a/sshkey.c b/sshkey.c
|
||||
index ed2b5dff..77093235 100644
|
||||
--- a/sshkey.c
|
||||
+++ b/sshkey.c
|
||||
@@ -2365,18 +2365,24 @@ cert_parse(struct sshbuf *b, struct sshkey *key, struct sshbuf *certbuf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-#ifdef WITH_OPENSSL
|
||||
-static int
|
||||
-check_rsa_length(const RSA *rsa)
|
||||
+int
|
||||
+sshkey_check_rsa_length(const struct sshkey *k, int min_size)
|
||||
{
|
||||
+#ifdef WITH_OPENSSL
|
||||
const BIGNUM *rsa_n;
|
||||
+ int nbits;
|
||||
|
||||
- RSA_get0_key(rsa, &rsa_n, NULL, NULL);
|
||||
- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
|
||||
+ if (k == NULL || k->rsa == NULL ||
|
||||
+ (k->type != KEY_RSA && k->type != KEY_RSA_CERT))
|
||||
+ return 0;
|
||||
+ RSA_get0_key(k->rsa, &rsa_n, NULL, NULL);
|
||||
+ nbits = BN_num_bits(rsa_n);
|
||||
+ if (nbits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
|
||||
+ (min_size > 0 && nbits < min_size))
|
||||
return SSH_ERR_KEY_LENGTH;
|
||||
+#endif /* WITH_OPENSSL */
|
||||
return 0;
|
||||
}
|
||||
-#endif
|
||||
|
||||
static int
|
||||
sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
|
||||
@@ -2439,7 +2445,7 @@ sshkey_from_blob_internal(struct sshbuf *b, struct sshkey **keyp,
|
||||
goto out;
|
||||
}
|
||||
rsa_n = rsa_e = NULL; /* transferred */
|
||||
- if ((ret = check_rsa_length(key->rsa)) != 0)
|
||||
+ if ((ret = sshkey_check_rsa_length(key, 0)) != 0)
|
||||
goto out;
|
||||
#ifdef DEBUG_PK
|
||||
RSA_print_fp(stderr, key->rsa, 8);
|
||||
@@ -3642,7 +3648,7 @@ sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
|
||||
goto out;
|
||||
}
|
||||
rsa_p = rsa_q = NULL; /* transferred */
|
||||
- if ((r = check_rsa_length(k->rsa)) != 0)
|
||||
+ if ((r = sshkey_check_rsa_length(k, 0)) != 0)
|
||||
goto out;
|
||||
if ((r = ssh_rsa_complete_crt_parameters(k, rsa_iqmp)) != 0)
|
||||
goto out;
|
||||
@@ -4644,7 +4650,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
- if ((r = check_rsa_length(prv->rsa)) != 0)
|
||||
+ if ((r = sshkey_check_rsa_length(prv, 0)) != 0)
|
||||
goto out;
|
||||
} else if (EVP_PKEY_base_id(pk) == EVP_PKEY_DSA &&
|
||||
(type == KEY_UNSPEC || type == KEY_DSA)) {
|
||||
diff --git a/sshkey.h b/sshkey.h
|
||||
index 094815e0..be254e6b 100644
|
||||
--- a/sshkey.h
|
||||
+++ b/sshkey.h
|
||||
@@ -273,6 +273,7 @@ int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
|
||||
int sshkey_parse_pubkey_from_private_fileblob_type(struct sshbuf *blob,
|
||||
int type, struct sshkey **pubkeyp);
|
||||
|
||||
+int sshkey_check_rsa_length(const struct sshkey *, int);
|
||||
/* XXX should be internal, but used by ssh-keygen */
|
||||
int ssh_rsa_complete_crt_parameters(struct sshkey *, const BIGNUM *);
|
||||
|
||||
diff --git a/ssh.1 b/ssh.1
|
||||
index b4956aec..e255b9b9 100644
|
||||
--- a/ssh.1
|
||||
+++ b/ssh.1
|
||||
@@ -571,6 +571,7 @@ For full details of the options listed below, and their possible values, see
|
||||
.It RemoteCommand
|
||||
.It RemoteForward
|
||||
.It RequestTTY
|
||||
+.It RequiredRSASize
|
||||
.It SendEnv
|
||||
.It ServerAliveInterval
|
||||
.It ServerAliveCountMax
|
||||
diff --git a/ssh_config.5 b/ssh_config.5
|
||||
index 24a46460..d1ede18e 100644
|
||||
--- a/ssh_config.5
|
||||
+++ b/ssh_config.5
|
||||
@@ -1634,6 +1634,17 @@ and
|
||||
.Fl T
|
||||
flags for
|
||||
.Xr ssh 1 .
|
||||
+.It Cm RequiredRSASize
|
||||
+Specifies the minimum RSA key size (in bits) that
|
||||
+.Xr ssh 1
|
||||
+will accept.
|
||||
+User authentication keys smaller than this limit will be ignored.
|
||||
+Servers that present host keys smaller than this limit will cause the
|
||||
+connection to be terminated.
|
||||
+The default is
|
||||
+.Cm 1024
|
||||
+bits.
|
||||
+Note that this limit may only be raised from the default.
|
||||
.It Cm RevokedHostKeys
|
||||
Specifies revoked host public keys.
|
||||
Keys listed in this file will be refused for host authentication.
|
||||
diff --git a/sshd_config.5 b/sshd_config.5
|
||||
index 867a747d..f5a06637 100644
|
||||
--- a/sshd_config.5
|
||||
+++ b/sshd_config.5
|
||||
@@ -1596,6 +1596,16 @@ is
|
||||
.Cm default none ,
|
||||
which means that rekeying is performed after the cipher's default amount
|
||||
of data has been sent or received and no time based rekeying is done.
|
||||
+.It Cm RequiredRSASize
|
||||
+Specifies the minimum RSA key size (in bits) that
|
||||
+.Xr sshd 8
|
||||
+will accept.
|
||||
+User and host-based authentication keys smaller than this limit will be
|
||||
+refused.
|
||||
+The default is
|
||||
+.Cm 1024
|
||||
+bits.
|
||||
+Note that this limit may only be raised from the default.
|
||||
.It Cm RevokedKeys
|
||||
Specifies revoked public keys file, or
|
||||
.Cm none
|
||||
{ "channeltimeout", sChannelTimeout, SSHCFG_ALL },
|
||||
{ "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL },
|
||||
{ "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL },
|
||||
|
||||
@ -1,63 +1,118 @@
|
||||
diff --color -rup a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh
|
||||
--- a/regress/hostkey-agent.sh 2021-08-20 06:03:49.000000000 +0200
|
||||
+++ b/regress/hostkey-agent.sh 2022-07-14 11:58:12.172786060 +0200
|
||||
@@ -13,8 +13,12 @@ r=$?
|
||||
grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
|
||||
echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig
|
||||
diff -up openssh-9.3p1/regress/hostkey-agent.sh.xxx openssh-9.3p1/regress/hostkey-agent.sh
|
||||
--- openssh-9.3p1/regress/hostkey-agent.sh.xxx 2023-05-29 18:15:56.311236887 +0200
|
||||
+++ openssh-9.3p1/regress/hostkey-agent.sh 2023-05-29 18:16:07.598503551 +0200
|
||||
@@ -17,8 +17,21 @@ trace "make CA key"
|
||||
|
||||
${SSHKEYGEN} -qt ed25519 -f $OBJ/agent-ca -N '' || fatal "ssh-keygen CA"
|
||||
|
||||
+PUBKEY_ACCEPTED_ALGOS=`$SSH -G "example.com" | \
|
||||
+ grep -i "PubkeyAcceptedAlgorithms" | cut -d ' ' -f2- | tr "," "|"`
|
||||
+SSH_ACCEPTED_KEYTYPES=`echo "$SSH_KEYTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"`
|
||||
+echo $PUBKEY_ACCEPTED_ALGOS | grep "rsa"
|
||||
+r=$?
|
||||
+if [ $r == 0 ]; then
|
||||
+echo $SSH_ACCEPTED_KEYTYPES | grep "rsa"
|
||||
+r=$?
|
||||
+if [ $r -ne 0 ]; then
|
||||
+SSH_ACCEPTED_KEYTYPES="$SSH_ACCEPTED_KEYTYPES ssh-rsa"
|
||||
+fi
|
||||
+fi
|
||||
+
|
||||
trace "load hostkeys"
|
||||
-for k in $SSH_KEYTYPES ; do
|
||||
+for k in $SSH_ACCEPTED_KEYTYPES ; do
|
||||
${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
|
||||
(
|
||||
printf 'localhost-with-alias,127.0.0.1,::1 '
|
||||
@@ -31,7 +35,7 @@ cp $OBJ/known_hosts.orig $OBJ/known_host
|
||||
${SSHKEYGEN} -s $OBJ/agent-ca -qh -n localhost-with-alias \
|
||||
-I localhost-with-alias $OBJ/agent-key.$k.pub || \
|
||||
@@ -32,12 +48,16 @@ rm $OBJ/agent-ca # Don't need CA private
|
||||
|
||||
unset SSH_AUTH_SOCK
|
||||
|
||||
for ps in yes; do
|
||||
- for k in $SSH_KEYTYPES ; do
|
||||
+ for k in $SSH_ACCEPTED_KEYTYPES ; do
|
||||
verbose "key type $k privsep=$ps"
|
||||
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
|
||||
echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
|
||||
diff --color -rup a/sshconnect2.c b/sshconnect2.c
|
||||
--- a/sshconnect2.c 2022-07-14 10:10:07.262975710 +0200
|
||||
+++ b/sshconnect2.c 2022-07-14 10:10:32.068452067 +0200
|
||||
@@ -222,6 +222,7 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||
-for k in $SSH_KEYTYPES ; do
|
||||
+for k in $SSH_ACCEPTED_KEYTYPES ; do
|
||||
verbose "key type $k"
|
||||
+ hka=$k
|
||||
+ if [ $k = "ssh-rsa" ]; then
|
||||
+ hka="rsa-sha2-512"
|
||||
+ fi
|
||||
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
|
||||
- echo "HostKeyAlgorithms $k" >> $OBJ/sshd_proxy
|
||||
+ echo "HostKeyAlgorithms $hka" >> $OBJ/sshd_proxy
|
||||
echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy
|
||||
- opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy"
|
||||
+ opts="-oHostKeyAlgorithms=$hka -F $OBJ/ssh_proxy"
|
||||
( printf 'localhost-with-alias,127.0.0.1,::1 ' ;
|
||||
cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts
|
||||
SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'`
|
||||
@@ -50,15 +70,16 @@ for k in $SSH_KEYTYPES ; do
|
||||
done
|
||||
|
||||
SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com'`
|
||||
+SSH_ACCEPTED_CERTTYPES=`echo "$SSH_CERTTYPES" | egrep "$PUBKEY_ACCEPTED_ALGOS"`
|
||||
|
||||
# Prepare sshd_proxy for certificates.
|
||||
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
|
||||
HOSTKEYALGS=""
|
||||
-for k in $SSH_CERTTYPES ; do
|
||||
+for k in $SSH_ACCEPTED_CERTTYPES ; do
|
||||
test -z "$HOSTKEYALGS" || HOSTKEYALGS="${HOSTKEYALGS},"
|
||||
HOSTKEYALGS="${HOSTKEYALGS}${k}"
|
||||
done
|
||||
-for k in $SSH_KEYTYPES ; do
|
||||
+for k in $SSH_ACCEPTED_KEYTYPES ; do
|
||||
echo "Hostkey $OBJ/agent-key.${k}.pub" >> $OBJ/sshd_proxy
|
||||
echo "HostCertificate $OBJ/agent-key.${k}-cert.pub" >> $OBJ/sshd_proxy
|
||||
test -f $OBJ/agent-key.${k}.pub || fatal "no $k key"
|
||||
@@ -70,7 +93,7 @@ echo "HostKeyAlgorithms $HOSTKEYALGS" >>
|
||||
( printf '@cert-authority localhost-with-alias ' ;
|
||||
cat $OBJ/agent-ca.pub) > $OBJ/known_hosts
|
||||
|
||||
-for k in $SSH_CERTTYPES ; do
|
||||
+for k in $SSH_ACCEPTED_CERTTYPES ; do
|
||||
verbose "cert type $k"
|
||||
opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy"
|
||||
SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'`
|
||||
diff -up openssh-9.3p1/sshconnect2.c.xxx openssh-9.3p1/sshconnect2.c
|
||||
--- openssh-9.3p1/sshconnect2.c.xxx 2023-04-26 17:37:35.100827792 +0200
|
||||
+++ openssh-9.3p1/sshconnect2.c 2023-04-26 17:50:31.860748877 +0200
|
||||
@@ -221,7 +221,7 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||
const struct ssh_conn_info *cinfo)
|
||||
{
|
||||
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
|
||||
char *s, *all_key;
|
||||
+ char *hostkeyalgs = NULL, *pkalg = NULL;
|
||||
char *prop_kex = NULL, *prop_enc = NULL, *prop_hostkey = NULL;
|
||||
char *myproposal[PROPOSAL_MAX];
|
||||
- char *all_key, *hkalgs = NULL;
|
||||
+ char *all_key, *hkalgs = NULL, *filtered_algs = NULL;
|
||||
int r, use_known_hosts_order = 0;
|
||||
|
||||
@@ -264,14 +265,19 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||
myproposal[PROPOSAL_MAC_ALGS_STOC] = options.macs;
|
||||
if (use_known_hosts_order) {
|
||||
/* Query known_hosts and prefer algorithms that appear there */
|
||||
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
|
||||
- compat_pkalg_proposal(ssh,
|
||||
- order_hostkeyalgs(host, hostaddr, port, cinfo));
|
||||
+ if ((hostkeyalgs = order_hostkeyalgs(host, hostaddr, port, cinfo)) == NULL)
|
||||
+ fatal_f("order_hostkeyalgs");
|
||||
+ pkalg = match_filter_allowlist(hostkeyalgs, options.pubkey_accepted_algos);
|
||||
+ free(hostkeyalgs);
|
||||
} else {
|
||||
- /* Use specified HostkeyAlgorithms exactly */
|
||||
- myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
|
||||
- compat_pkalg_proposal(ssh, options.hostkeyalgorithms);
|
||||
+ /* Use specified HostkeyAlgorithms */
|
||||
+ pkalg = match_filter_allowlist(options.hostkeyalgorithms, options.pubkey_accepted_algos);
|
||||
}
|
||||
+ if (pkalg == NULL)
|
||||
+ fatal_f("match_filter_allowlist");
|
||||
+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = prop_hostkey =
|
||||
+ compat_pkalg_proposal(ssh, pkalg);
|
||||
+ free(pkalg);
|
||||
#if defined(GSSAPI) && defined(WITH_OPENSSL)
|
||||
@@ -260,10 +260,22 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||
if (use_known_hosts_order)
|
||||
hkalgs = order_hostkeyalgs(host, hostaddr, port, cinfo);
|
||||
|
||||
+ filtered_algs = hkalgs ? match_filter_allowlist(hkalgs, options.pubkey_accepted_algos)
|
||||
+ : match_filter_allowlist(options.hostkeyalgorithms,
|
||||
+ options.pubkey_accepted_algos);
|
||||
+ if (filtered_algs == NULL) {
|
||||
+ if (hkalgs)
|
||||
+ fatal_f("No match between algorithms for %s (host %s) and pubkey accepted algorithms %s",
|
||||
+ hkalgs, host, options.pubkey_accepted_algos);
|
||||
+ else
|
||||
+ fatal_f("No match between host key algorithms %s and pubkey accepted algorithms %s",
|
||||
+ options.hostkeyalgorithms, options.pubkey_accepted_algos);
|
||||
+ }
|
||||
+
|
||||
kex_proposal_populate_entries(ssh, myproposal,
|
||||
options.kex_algorithms, options.ciphers, options.macs,
|
||||
compression_alg_list(options.compression),
|
||||
- hkalgs ? hkalgs : options.hostkeyalgorithms);
|
||||
+ filtered_algs);
|
||||
|
||||
#if defined(GSSAPI) && defined(WITH_OPENSSL)
|
||||
if (options.gss_keyex) {
|
||||
@@ -303,6 +315,7 @@ ssh_kex2(struct ssh *ssh, char *host, st
|
||||
#endif
|
||||
|
||||
free(hkalgs);
|
||||
+ free(filtered_algs);
|
||||
|
||||
/* start key exchange */
|
||||
if ((r = kex_setup(ssh, myproposal)) != 0)
|
||||
|
||||
@ -94,47 +94,6 @@ diff -up openssh-8.7p1/monitor.c.sshrsacheck openssh-8.7p1/monitor.c
|
||||
is_proof ? "hostkey proof" : "KEX", siglen);
|
||||
|
||||
sshbuf_reset(m);
|
||||
diff -up openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck openssh-8.7p1/regress/cert-userkey.sh
|
||||
--- openssh-8.7p1/regress/cert-userkey.sh.sshrsacheck 2023-01-25 14:26:52.885963113 +0100
|
||||
+++ openssh-8.7p1/regress/cert-userkey.sh 2023-01-25 14:27:25.757219800 +0100
|
||||
@@ -7,7 +7,8 @@ rm -f $OBJ/authorized_keys_$USER $OBJ/us
|
||||
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
|
||||
cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
|
||||
|
||||
-PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
|
||||
+#ssh-dss keys are incompatible with DEFAULT crypto policy
|
||||
+PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss' | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
|
||||
EXTRA_TYPES=""
|
||||
rsa=""
|
||||
|
||||
diff -up openssh-8.7p1/regress/Makefile.sshrsacheck openssh-8.7p1/regress/Makefile
|
||||
--- openssh-8.7p1/regress/Makefile.sshrsacheck 2023-01-20 13:07:54.169676051 +0100
|
||||
+++ openssh-8.7p1/regress/Makefile 2023-01-20 13:07:54.290677074 +0100
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
tests: prep file-tests t-exec unit
|
||||
|
||||
-REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12
|
||||
+#ssh-dss tests will not pass on DEFAULT crypto-policy because of SHA1, skipping
|
||||
+REGRESS_TARGETS= t1 t2 t3 t4 t5 t7 t8 t9 t10 t11 t12
|
||||
|
||||
# File based tests
|
||||
file-tests: $(REGRESS_TARGETS)
|
||||
diff -up openssh-8.7p1/regress/test-exec.sh.sshrsacheck openssh-8.7p1/regress/test-exec.sh
|
||||
--- openssh-8.7p1/regress/test-exec.sh.sshrsacheck 2023-01-25 14:24:54.778040819 +0100
|
||||
+++ openssh-8.7p1/regress/test-exec.sh 2023-01-25 14:26:39.500858590 +0100
|
||||
@@ -581,8 +581,9 @@ maybe_filter_sk() {
|
||||
fi
|
||||
}
|
||||
|
||||
-SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk`
|
||||
-SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk`
|
||||
+#ssh-dss keys are incompatible with DEFAULT crypto policy
|
||||
+SSH_KEYTYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'`
|
||||
+SSH_HOSTKEY_TYPES=`$SSH -Q key-plain | maybe_filter_sk | grep -v 'ssh-dss'`
|
||||
|
||||
for t in ${SSH_KEYTYPES}; do
|
||||
# generate user key
|
||||
diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p1/regress/unittests/kex/test_kex.c
|
||||
--- openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck 2023-01-26 13:34:52.645743677 +0100
|
||||
+++ openssh-8.7p1/regress/unittests/kex/test_kex.c 2023-01-26 13:36:56.220745823 +0100
|
||||
@ -148,15 +107,6 @@ diff -up openssh-8.7p1/regress/unittests/kex/test_kex.c.sshrsacheck openssh-8.7p
|
||||
ASSERT_PTR_NE(keyname, NULL);
|
||||
kex_params.proposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = keyname;
|
||||
ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
|
||||
@@ -180,7 +181,7 @@ do_kex(char *kex)
|
||||
{
|
||||
#ifdef WITH_OPENSSL
|
||||
do_kex_with_key(kex, KEY_RSA, 2048);
|
||||
- do_kex_with_key(kex, KEY_DSA, 1024);
|
||||
+ /* do_kex_with_key(kex, KEY_DSA, 1024); */
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
do_kex_with_key(kex, KEY_ECDSA, 256);
|
||||
#endif /* OPENSSL_HAS_ECC */
|
||||
diff -up openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_file.c
|
||||
--- openssh-8.7p1/regress/unittests/sshkey/test_file.c.sshrsacheck 2023-01-26 12:04:55.946343408 +0100
|
||||
+++ openssh-8.7p1/regress/unittests/sshkey/test_file.c 2023-01-26 12:06:35.235164432 +0100
|
||||
@ -196,22 +146,6 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_fuzz.c.sshrsacheck openssh-
|
||||
|
||||
TEST_START("fuzz RSA SHA256 sig");
|
||||
buf = load_file("rsa_1");
|
||||
@@ -357,6 +358,7 @@ sshkey_fuzz_tests(void)
|
||||
sshkey_free(k1);
|
||||
TEST_DONE();
|
||||
|
||||
+ /* Skip this test, SHA1 signatures are not supported
|
||||
TEST_START("fuzz DSA sig");
|
||||
buf = load_file("dsa_1");
|
||||
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", &k1, NULL), 0);
|
||||
@@ -364,6 +366,7 @@ sshkey_fuzz_tests(void)
|
||||
sig_fuzz(k1, NULL);
|
||||
sshkey_free(k1);
|
||||
TEST_DONE();
|
||||
+ */
|
||||
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
TEST_START("fuzz ECDSA sig");
|
||||
diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c
|
||||
--- openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck 2023-01-26 11:02:52.339413463 +0100
|
||||
+++ openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c 2023-01-26 11:58:42.324253896 +0100
|
||||
@ -241,10 +175,10 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss
|
||||
{
|
||||
size_t len;
|
||||
u_char *sig;
|
||||
+ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp */
|
||||
+ int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? SSH_ERR_LIBCRYPTO_ERROR : 0;
|
||||
+ /* ssh-rsa implies SHA1, forbidden in DEFAULT cp in RHEL, permitted in Fedora */
|
||||
+ int expected = (sig_alg && strcmp(sig_alg, "ssh-rsa") == 0) ? sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0) : 0;
|
||||
+ if (k && (sshkey_type_plain(k->type) == KEY_DSA || sshkey_type_plain(k->type) == KEY_DSA_CERT))
|
||||
+ expected = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ expected = sshkey_sign(k, &sig, &len, d, l, sig_alg, NULL, NULL, 0);
|
||||
|
||||
ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, sig_alg,
|
||||
- NULL, NULL, 0), 0);
|
||||
@ -277,24 +211,17 @@ diff -up openssh-8.7p1/regress/unittests/sshkey/test_sshkey.c.sshrsacheck openss
|
||||
ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4),
|
||||
SSH_ERR_KEY_CERT_INVALID_SIGN_KEY);
|
||||
ASSERT_PTR_EQ(k4, NULL);
|
||||
diff -up openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck openssh-8.7p1/regress/unittests/sshsig/tests.c
|
||||
--- openssh-8.7p1/regress/unittests/sshsig/tests.c.sshrsacheck 2023-01-26 12:19:23.659513651 +0100
|
||||
+++ openssh-8.7p1/regress/unittests/sshsig/tests.c 2023-01-26 12:20:28.021044803 +0100
|
||||
@@ -102,9 +102,11 @@ tests(void)
|
||||
check_sig("rsa.pub", "rsa.sig", msg, namespace);
|
||||
TEST_DONE();
|
||||
|
||||
+ /* Skip this test, SHA1 signatures are not supported
|
||||
TEST_START("check DSA signature");
|
||||
check_sig("dsa.pub", "dsa.sig", msg, namespace);
|
||||
TEST_DONE();
|
||||
+ */
|
||||
|
||||
#ifdef OPENSSL_HAS_ECC
|
||||
TEST_START("check ECDSA signature");
|
||||
diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c
|
||||
--- openssh-8.7p1/serverloop.c.sshrsacheck 2023-01-12 14:57:08.118400073 +0100
|
||||
+++ openssh-8.7p1/serverloop.c 2023-01-12 14:59:17.330470518 +0100
|
||||
@@ -80,6 +80,7 @@
|
||||
#include "auth-options.h"
|
||||
#include "serverloop.h"
|
||||
#include "ssherr.h"
|
||||
+#include "compat.h"
|
||||
|
||||
extern ServerOptions options;
|
||||
|
||||
@@ -737,6 +737,10 @@ server_input_hostkeys_prove(struct ssh *
|
||||
else if (ssh->kex->flags & KEX_RSA_SHA2_256_SUPPORTED)
|
||||
sigalg = "rsa-sha2-256";
|
||||
@ -304,7 +231,7 @@ diff -up openssh-8.7p1/serverloop.c.sshrsacheck openssh-8.7p1/serverloop.c
|
||||
+ debug3_f("SHA1 signature is not supported, falling back to %s", sigalg);
|
||||
+ }
|
||||
debug3_f("sign %s key (index %d) using sigalg %s",
|
||||
sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg);
|
||||
sshkey_type(key), ndx, sigalg == NULL ? "default" : sigalg);
|
||||
if ((r = sshbuf_put_cstring(sigbuf,
|
||||
diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c
|
||||
--- openssh-8.7p1/sshconnect2.c.sshrsacheck 2023-01-25 15:33:29.140353651 +0100
|
||||
@ -318,99 +245,12 @@ diff -up openssh-8.7p1/sshconnect2.c.sshrsacheck openssh-8.7p1/sshconnect2.c
|
||||
+ debug3_f("trying to fallback to algorithm %s", rsa_safe_alg);
|
||||
+
|
||||
+ if ((r = sshkey_sign(sign_key, sigp, lenp, data, datalen,
|
||||
+ rsa_safe_alg, options.sk_provider, pin, compat)) != 0)
|
||||
+ rsa_safe_alg, options.sk_provider, pin, compat)) != 0)
|
||||
+ debug_fr(r, "sshkey_sign - RSA fallback");
|
||||
+ }
|
||||
goto out;
|
||||
}
|
||||
|
||||
diff -up openssh-8.7p1/sshd.c.sshrsacheck openssh-8.7p1/sshd.c
|
||||
--- openssh-8.7p1/sshd.c.sshrsacheck 2023-01-12 13:29:06.355711140 +0100
|
||||
+++ openssh-8.7p1/sshd.c 2023-01-12 13:29:06.358711178 +0100
|
||||
@@ -1640,6 +1651,7 @@ main(int ac, char **av)
|
||||
int keytype;
|
||||
Authctxt *authctxt;
|
||||
struct connection_info *connection_info = NULL;
|
||||
+ int forbid_ssh_rsa = 0;
|
||||
|
||||
#ifdef HAVE_SECUREWARE
|
||||
(void)set_auth_parameters(ac, av);
|
||||
@@ -1938,6 +1950,33 @@ main(int ac, char **av)
|
||||
key = NULL;
|
||||
continue;
|
||||
}
|
||||
+ if (key && (sshkey_type_plain(key->type) == KEY_RSA || sshkey_type_plain(key->type) == KEY_RSA_CERT)) {
|
||||
+ size_t sign_size = 0;
|
||||
+ u_char *tmp = NULL;
|
||||
+ u_char data[] = "Test SHA1 vector";
|
||||
+ int res;
|
||||
+
|
||||
+ res = sshkey_sign(key, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0);
|
||||
+ free(tmp);
|
||||
+ if (res == SSH_ERR_LIBCRYPTO_ERROR) {
|
||||
+ verbose_f("sshd: SHA1 in signatures is disabled for RSA keys");
|
||||
+ forbid_ssh_rsa = 1;
|
||||
+ }
|
||||
+ }
|
||||
+ if (key && (sshkey_type_plain(key->type) == KEY_DSA || sshkey_type_plain(key->type) == KEY_DSA_CERT)) {
|
||||
+ size_t sign_size = 0;
|
||||
+ u_char *tmp = NULL;
|
||||
+ u_char data[] = "Test SHA1 vector";
|
||||
+ int res;
|
||||
+
|
||||
+ res = sshkey_sign(key, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0);
|
||||
+ free(tmp);
|
||||
+ if (res == SSH_ERR_LIBCRYPTO_ERROR) {
|
||||
+ logit_f("sshd: ssh-dss is disabled, skipping key file %s", options.host_key_files[i]);
|
||||
+ key = NULL;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
if (sshkey_is_sk(key) &&
|
||||
key->sk_flags & SSH_SK_USER_PRESENCE_REQD) {
|
||||
debug("host key %s requires user presence, ignoring",
|
||||
@@ -2275,6 +2306,9 @@ main(int ac, char **av)
|
||||
|
||||
check_ip_options(ssh);
|
||||
|
||||
+ if (forbid_ssh_rsa)
|
||||
+ ssh->compat |= SSH_RH_RSASIGSHA;
|
||||
+
|
||||
/* Prepare the channels layer */
|
||||
channel_init_channels(ssh);
|
||||
channel_set_af(ssh, options.address_family);
|
||||
diff -Nur openssh-8.7p1/ssh-keygen.c openssh-8.7p1_patched/ssh-keygen.c
|
||||
--- openssh-8.7p1/ssh-keygen.c 2023-01-18 17:41:47.894515779 +0100
|
||||
+++ openssh-8.7p1_patched/ssh-keygen.c 2023-01-18 17:41:44.500488818 +0100
|
||||
@@ -491,6 +491,8 @@
|
||||
BIGNUM *dsa_pub_key = NULL, *dsa_priv_key = NULL;
|
||||
BIGNUM *rsa_n = NULL, *rsa_e = NULL, *rsa_d = NULL;
|
||||
BIGNUM *rsa_p = NULL, *rsa_q = NULL, *rsa_iqmp = NULL;
|
||||
+ char rsa_safe_alg[] = "rsa-sha2-256";
|
||||
+ char *alg = NULL;
|
||||
|
||||
if ((r = sshbuf_get_u32(b, &magic)) != 0)
|
||||
fatal_fr(r, "parse magic");
|
||||
@@ -590,6 +592,7 @@ do_convert_private_ssh2(struct sshbuf *b
|
||||
if ((r = ssh_rsa_complete_crt_parameters(key, rsa_iqmp)) != 0)
|
||||
fatal_fr(r, "generate RSA parameters");
|
||||
BN_clear_free(rsa_iqmp);
|
||||
+ alg = rsa_safe_alg;
|
||||
break;
|
||||
}
|
||||
rlen = sshbuf_len(b);
|
||||
@@ -598,9 +601,9 @@ do_convert_private_ssh2(struct sshbuf *b
|
||||
|
||||
/* try the key */
|
||||
if (sshkey_sign(key, &sig, &slen, data, sizeof(data),
|
||||
- NULL, NULL, NULL, 0) != 0 ||
|
||||
+ alg, NULL, NULL, 0) != 0 ||
|
||||
sshkey_verify(key, sig, slen, data, sizeof(data),
|
||||
- NULL, 0, NULL) != 0) {
|
||||
+ alg, 0, NULL) != 0) {
|
||||
sshkey_free(key);
|
||||
free(sig);
|
||||
return NULL;
|
||||
diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c
|
||||
--- openssh-8.7p1/ssh-rsa.c.sshrsacheck 2023-01-20 13:07:54.180676144 +0100
|
||||
+++ openssh-8.7p1/ssh-rsa.c 2023-01-20 13:07:54.290677074 +0100
|
||||
@ -424,3 +264,34 @@ diff -up openssh-8.7p1/ssh-rsa.c.sshrsacheck openssh-8.7p1/ssh-rsa.c
|
||||
ret = SSH_ERR_SIGNATURE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
diff -up openssh-9.8p1/sshd-session.c.xxx openssh-9.8p1/sshd-session.c
|
||||
--- openssh-9.8p1/sshd-session.c.xxx 2024-07-23 15:08:14.794350818 +0200
|
||||
+++ openssh-9.8p1/sshd-session.c 2024-07-23 15:40:21.658456636 +0200
|
||||
@@ -1305,6 +1305,27 @@ main(int ac, char **av)
|
||||
|
||||
check_ip_options(ssh);
|
||||
|
||||
+ {
|
||||
+ struct sshkey *rsakey = NULL;
|
||||
+ rsakey = get_hostkey_private_by_type(KEY_RSA, 0, ssh);
|
||||
+ if (rsakey == NULL)
|
||||
+ rsakey = get_hostkey_private_by_type(KEY_RSA_CERT, 0, ssh);
|
||||
+
|
||||
+ if (rsakey != NULL) {
|
||||
+ size_t sign_size = 0;
|
||||
+ u_char *tmp = NULL;
|
||||
+ u_char data[] = "Test SHA1 vector";
|
||||
+ int res;
|
||||
+
|
||||
+ res = sshkey_sign(rsakey, &tmp, &sign_size, data, sizeof(data), NULL, NULL, NULL, 0);
|
||||
+ free(tmp);
|
||||
+ if (res == SSH_ERR_LIBCRYPTO_ERROR) {
|
||||
+ verbose_f("SHA1 in signatures is disabled for RSA keys");
|
||||
+ ssh->compat |= SSH_RH_RSASIGSHA;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
/* Prepare the channels layer */
|
||||
channel_init_channels(ssh);
|
||||
channel_set_af(ssh, options.address_family);
|
||||
|
||||
@ -1,6 +1,16 @@
|
||||
diff -up openssh-8.7p1/log.c.xxx openssh-8.7p1/log.c
|
||||
--- openssh-8.7p1/log.c.xxx 2024-10-18 13:00:56.419560563 +0200
|
||||
+++ openssh-8.7p1/log.c 2024-10-18 13:22:35.954819016 +0200
|
||||
diff -up openssh-9.9p1/log.c.xxx openssh-9.9p1/log.c
|
||||
--- openssh-9.9p1/log.c.xxx 2024-10-22 11:55:44.281939275 +0200
|
||||
+++ openssh-9.9p1/log.c 2024-10-22 11:56:16.709676267 +0200
|
||||
@@ -52,6 +52,9 @@
|
||||
|
||||
#include "log.h"
|
||||
#include "match.h"
|
||||
+#ifdef WITH_OPENSSL
|
||||
+#include <openssl/err.h>
|
||||
+#endif
|
||||
|
||||
static LogLevel log_level = SYSLOG_LEVEL_INFO;
|
||||
static int log_on_stderr = 1;
|
||||
@@ -438,6 +438,26 @@ sshlog(const char *file, const char *fun
|
||||
va_end(args);
|
||||
}
|
||||
@ -38,7 +48,7 @@ diff -up openssh-8.7p1/log.h.xxx openssh-8.7p1/log.h
|
||||
+void sshlog_openssl(int);
|
||||
void sshlogv(const char *, const char *, int, int,
|
||||
LogLevel, const char *, const char *, va_list);
|
||||
void sshsigdie(const char *, const char *, int, int,
|
||||
void sshlogdie(const char *, const char *, int, int,
|
||||
diff -up openssh-8.7p1/auth2-pubkey.c.yyy openssh-8.7p1/auth2-pubkey.c
|
||||
--- openssh-8.7p1/auth2-pubkey.c.yyy 2024-10-18 13:27:00.709055845 +0200
|
||||
+++ openssh-8.7p1/auth2-pubkey.c 2024-10-18 13:27:31.638784460 +0200
|
||||
@ -63,3 +73,40 @@ diff -up openssh-8.7p1/dispatch.c.yyy openssh-8.7p1/dispatch.c
|
||||
sshpkt_fatal(ssh, r, "%s", __func__);
|
||||
+ }
|
||||
}
|
||||
diff -up openssh-9.9p1/Makefile.in.xxx openssh-9.9p1/Makefile.in
|
||||
--- openssh-9.9p1/Makefile.in.xxx 2025-01-27 12:56:58.533623367 +0100
|
||||
+++ openssh-9.9p1/Makefile.in 2025-01-27 12:57:41.635638843 +0100
|
||||
@@ -224,7 +224,7 @@ sshd-session$(EXEEXT): libssh.a $(LIBCOM
|
||||
$(LD) -o $@ $(SSHD_SESSION_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) $(CHANNELLIBS)
|
||||
|
||||
scp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SCP_OBJS)
|
||||
- $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||
+ $(LD) -o $@ $(SCP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lcrypto $(LIBS)
|
||||
|
||||
ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHADD_OBJS)
|
||||
$(LD) -o $@ $(SSHADD_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(CHANNELLIBS)
|
||||
@@ -245,20 +245,20 @@ ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) lib
|
||||
$(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) $(CHANNELLIBS)
|
||||
|
||||
ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o
|
||||
- $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(KEYCATLIBS) $(LIBS)
|
||||
+ $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lcrypto $(KEYCATLIBS) $(LIBS)
|
||||
|
||||
ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS)
|
||||
$(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) $(CHANNELLIBS)
|
||||
|
||||
sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTPSERVER_OBJS)
|
||||
- $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS)
|
||||
+ $(LD) -o $@ $(SFTPSERVER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lcrypto $(LIBS)
|
||||
|
||||
sftp$(EXEEXT): $(LIBCOMPAT) libssh.a $(SFTP_OBJS)
|
||||
- $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) $(LIBEDIT)
|
||||
+ $(LD) -o $@ $(SFTP_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lcrypto $(LIBS) $(LIBEDIT)
|
||||
|
||||
# test driver for the loginrec code - not built by default
|
||||
logintest: logintest.o $(LIBCOMPAT) libssh.a loginrec.o
|
||||
- $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh $(LIBS)
|
||||
+ $(LD) -o $@ logintest.o $(LDFLAGS) loginrec.o -lopenbsd-compat -lssh -lcrypto $(LIBS)
|
||||
|
||||
$(MANPAGES): $(MANPAGES_IN)
|
||||
if test "$(MANTYPE)" = "cat"; then \
|
||||
|
||||
@ -1,174 +1,182 @@
|
||||
diff -up openssh-8.7p1/scp.c.scp-sftpdirs openssh-8.7p1/scp.c
|
||||
--- openssh-8.7p1/scp.c.scp-sftpdirs 2022-02-07 12:31:07.407740407 +0100
|
||||
+++ openssh-8.7p1/scp.c 2022-02-07 12:31:07.409740424 +0100
|
||||
@@ -1324,7 +1324,7 @@ source_sftp(int argc, char *src, char *t
|
||||
|
||||
diff --git a/scp.c b/scp.c
|
||||
--- a/scp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||
+++ b/scp.c (date 1703111453316)
|
||||
@@ -1372,7 +1372,7 @@
|
||||
|
||||
if (src_is_dir && iamrecursive) {
|
||||
if (upload_dir(conn, src, abs_dst, pflag,
|
||||
- SFTP_PROGRESS_ONLY, 0, 0, 1) != 0) {
|
||||
+ SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
|
||||
error("failed to upload directory %s to %s",
|
||||
src, abs_dst);
|
||||
if (sftp_upload_dir(conn, src, abs_dst, pflag,
|
||||
- SFTP_PROGRESS_ONLY, 0, 0, 1, 1) != 0) {
|
||||
+ SFTP_PROGRESS_ONLY, 0, 0, 1, 1, 1) != 0) {
|
||||
error("failed to upload directory %s to %s", src, targ);
|
||||
errs = 1;
|
||||
diff -up openssh-8.7p1/sftp-client.c.scp-sftpdirs openssh-8.7p1/sftp-client.c
|
||||
--- openssh-8.7p1/sftp-client.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
|
||||
+++ openssh-8.7p1/sftp-client.c 2022-02-07 12:47:59.117516131 +0100
|
||||
@@ -971,7 +971,7 @@ do_fsetstat(struct sftp_conn *conn, cons
|
||||
|
||||
}
|
||||
diff --git a/sftp-client.c b/sftp-client.c
|
||||
--- a/sftp-client.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||
+++ b/sftp-client.c (date 1703169614263)
|
||||
@@ -1003,7 +1003,7 @@
|
||||
|
||||
/* Implements both the realpath and expand-path operations */
|
||||
static char *
|
||||
-do_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
|
||||
+do_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir)
|
||||
-sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand)
|
||||
+sftp_realpath_expand(struct sftp_conn *conn, const char *path, int expand, int create_dir)
|
||||
{
|
||||
struct sshbuf *msg;
|
||||
u_int expected_id, count, id;
|
||||
@@ -1012,9 +1012,38 @@ do_realpath_expand(struct sftp_conn *con
|
||||
|
||||
if ((r = sshbuf_get_u32(msg, &status)) != 0)
|
||||
@@ -1049,11 +1049,43 @@
|
||||
if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
|
||||
(r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
|
||||
fatal_fr(r, "parse status");
|
||||
- error("Couldn't canonicalize: %s", fx2txt(status));
|
||||
- error("%s %s: %s", expand ? "expand" : "realpath",
|
||||
- path, *errmsg == '\0' ? fx2txt(status) : errmsg);
|
||||
- free(errmsg);
|
||||
- sshbuf_free(msg);
|
||||
- return NULL;
|
||||
+ if ((status == SSH2_FX_NO_SUCH_FILE) && create_dir) {
|
||||
+ memset(&a, '\0', sizeof(a));
|
||||
+ if ((r = do_mkdir(conn, path, &a, 0)) != 0) {
|
||||
+ if ((r = sftp_mkdir(conn, path, &a, 0)) != 0) {
|
||||
+ sshbuf_free(msg);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+
|
||||
+ debug2("Sending SSH2_FXP_REALPATH \"%s\" - create dir", path);
|
||||
+ send_string_request(conn, id, SSH2_FXP_REALPATH,
|
||||
+ path, strlen(path));
|
||||
+
|
||||
+ get_msg(conn, msg);
|
||||
+ if ((r = sshbuf_get_u8(msg, &type)) != 0 ||
|
||||
+ (r = sshbuf_get_u32(msg, &id)) != 0)
|
||||
+ (r = sshbuf_get_u32(msg, &id)) != 0)
|
||||
+ fatal_fr(r, "parse");
|
||||
+
|
||||
+ if (id != expected_id)
|
||||
+ fatal("ID mismatch (%u != %u)", id, expected_id);
|
||||
+
|
||||
+ if (type == SSH2_FXP_STATUS) {
|
||||
+ u_int status;
|
||||
+ free(errmsg);
|
||||
+
|
||||
+ if ((r = sshbuf_get_u32(msg, &status)) != 0)
|
||||
+ if ((r = sshbuf_get_u32(msg, &status)) != 0 ||
|
||||
+ (r = sshbuf_get_cstring(msg, &errmsg, NULL)) != 0)
|
||||
+ fatal_fr(r, "parse status");
|
||||
+ error("Couldn't canonicalize: %s", fx2txt(status));
|
||||
+ error("%s %s: %s", expand ? "expand" : "realpath",
|
||||
+ path, *errmsg == '\0' ? fx2txt(status) : errmsg);
|
||||
+ free(errmsg);
|
||||
+ sshbuf_free(msg);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ } else {
|
||||
+ error("Couldn't canonicalize: %s", fx2txt(status));
|
||||
+ error("%s %s: %s", expand ? "expand" : "realpath",
|
||||
+ path, *errmsg == '\0' ? fx2txt(status) : errmsg);
|
||||
+ free(errmsg);
|
||||
+ sshbuf_free(msg);
|
||||
+ return NULL;
|
||||
+ }
|
||||
} else if (type != SSH2_FXP_NAME)
|
||||
fatal("Expected SSH2_FXP_NAME(%u) packet, got %u",
|
||||
SSH2_FXP_NAME, type);
|
||||
@@ -1039,9 +1067,9 @@ do_realpath_expand(struct sftp_conn *con
|
||||
@@ -1078,9 +1110,9 @@
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
-do_realpath(struct sftp_conn *conn, const char *path)
|
||||
+do_realpath(struct sftp_conn *conn, const char *path, int create_dir)
|
||||
-sftp_realpath(struct sftp_conn *conn, const char *path)
|
||||
+sftp_realpath(struct sftp_conn *conn, const char *path, int create_dir)
|
||||
{
|
||||
- return do_realpath_expand(conn, path, 0);
|
||||
+ return do_realpath_expand(conn, path, 0, create_dir);
|
||||
- return sftp_realpath_expand(conn, path, 0);
|
||||
+ return sftp_realpath_expand(conn, path, 0, create_dir);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
@@ -1055,9 +1083,9 @@ do_expand_path(struct sftp_conn *conn, c
|
||||
@@ -1094,9 +1126,9 @@
|
||||
{
|
||||
if (!can_expand_path(conn)) {
|
||||
if (!sftp_can_expand_path(conn)) {
|
||||
debug3_f("no server support, fallback to realpath");
|
||||
- return do_realpath_expand(conn, path, 0);
|
||||
+ return do_realpath_expand(conn, path, 0, 0);
|
||||
- return sftp_realpath_expand(conn, path, 0);
|
||||
+ return sftp_realpath_expand(conn, path, 0, 0);
|
||||
}
|
||||
- return do_realpath_expand(conn, path, 1);
|
||||
+ return do_realpath_expand(conn, path, 1, 0);
|
||||
- return sftp_realpath_expand(conn, path, 1);
|
||||
+ return sftp_realpath_expand(conn, path, 1, 0);
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
@@ -1807,7 +1835,7 @@ download_dir(struct sftp_conn *conn, con
|
||||
@@ -2016,7 +2048,7 @@
|
||||
char *src_canon;
|
||||
int ret;
|
||||
|
||||
- if ((src_canon = do_realpath(conn, src)) == NULL) {
|
||||
+ if ((src_canon = do_realpath(conn, src, 0)) == NULL) {
|
||||
error("Unable to canonicalize path \"%s\"", src);
|
||||
|
||||
- if ((src_canon = sftp_realpath(conn, src)) == NULL) {
|
||||
+ if ((src_canon = sftp_realpath(conn, src, 0)) == NULL) {
|
||||
error("download \"%s\": path canonicalization failed", src);
|
||||
return -1;
|
||||
}
|
||||
@@ -2115,12 +2143,12 @@ upload_dir_internal(struct sftp_conn *co
|
||||
@@ -2365,12 +2397,12 @@
|
||||
int
|
||||
upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
sftp_upload_dir(struct sftp_conn *conn, const char *src, const char *dst,
|
||||
int preserve_flag, int print_flag, int resume, int fsync_flag,
|
||||
- int follow_link_flag)
|
||||
+ int follow_link_flag, int create_dir)
|
||||
- int follow_link_flag, int inplace_flag)
|
||||
+ int follow_link_flag, int inplace_flag, int create_dir)
|
||||
{
|
||||
char *dst_canon;
|
||||
int ret;
|
||||
|
||||
- if ((dst_canon = do_realpath(conn, dst)) == NULL) {
|
||||
+ if ((dst_canon = do_realpath(conn, dst, create_dir)) == NULL) {
|
||||
error("Unable to canonicalize path \"%s\"", dst);
|
||||
|
||||
- if ((dst_canon = sftp_realpath(conn, dst)) == NULL) {
|
||||
+ if ((dst_canon = sftp_realpath(conn, dst, create_dir)) == NULL) {
|
||||
error("upload \"%s\": path canonicalization failed", dst);
|
||||
return -1;
|
||||
}
|
||||
@@ -2557,7 +2585,7 @@ crossload_dir(struct sftp_conn *from, st
|
||||
@@ -2825,7 +2857,7 @@
|
||||
char *from_path_canon;
|
||||
int ret;
|
||||
|
||||
- if ((from_path_canon = do_realpath(from, from_path)) == NULL) {
|
||||
+ if ((from_path_canon = do_realpath(from, from_path, 0)) == NULL) {
|
||||
error("Unable to canonicalize path \"%s\"", from_path);
|
||||
|
||||
- if ((from_path_canon = sftp_realpath(from, from_path)) == NULL) {
|
||||
+ if ((from_path_canon = sftp_realpath(from, from_path, 0)) == NULL) {
|
||||
error("crossload \"%s\": path canonicalization failed",
|
||||
from_path);
|
||||
return -1;
|
||||
}
|
||||
diff -up openssh-8.7p1/sftp-client.h.scp-sftpdirs openssh-8.7p1/sftp-client.h
|
||||
--- openssh-8.7p1/sftp-client.h.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
|
||||
+++ openssh-8.7p1/sftp-client.h 2022-02-07 12:31:07.410740433 +0100
|
||||
@@ -111,7 +111,7 @@ int do_fsetstat(struct sftp_conn *, cons
|
||||
int do_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
|
||||
|
||||
diff --git a/sftp-client.h b/sftp-client.h
|
||||
--- a/sftp-client.h (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||
+++ b/sftp-client.h (date 1703111691284)
|
||||
@@ -111,7 +111,7 @@
|
||||
int sftp_lsetstat(struct sftp_conn *conn, const char *path, Attrib *a);
|
||||
|
||||
/* Canonicalise 'path' - caller must free result */
|
||||
-char *do_realpath(struct sftp_conn *, const char *);
|
||||
+char *do_realpath(struct sftp_conn *, const char *, int);
|
||||
|
||||
-char *sftp_realpath(struct sftp_conn *, const char *);
|
||||
+char *sftp_realpath(struct sftp_conn *, const char *, int);
|
||||
|
||||
/* Canonicalisation with tilde expansion (requires server extension) */
|
||||
char *do_expand_path(struct sftp_conn *, const char *);
|
||||
@@ -159,7 +159,7 @@ int do_upload(struct sftp_conn *, const
|
||||
char *sftp_expand_path(struct sftp_conn *, const char *);
|
||||
@@ -163,7 +163,7 @@
|
||||
* times if 'pflag' is set
|
||||
*/
|
||||
int upload_dir(struct sftp_conn *, const char *, const char *, int, int, int,
|
||||
- int, int);
|
||||
+ int, int, int);
|
||||
|
||||
int sftp_upload_dir(struct sftp_conn *, const char *, const char *,
|
||||
- int, int, int, int, int, int);
|
||||
+ int, int, int, int, int, int, int);
|
||||
|
||||
/*
|
||||
* Download a 'from_path' from the 'from' connection and upload it to
|
||||
diff -up openssh-8.7p1/sftp.c.scp-sftpdirs openssh-8.7p1/sftp.c
|
||||
--- openssh-8.7p1/sftp.c.scp-sftpdirs 2021-08-20 06:03:49.000000000 +0200
|
||||
+++ openssh-8.7p1/sftp.c 2022-02-07 12:31:07.411740442 +0100
|
||||
@@ -760,7 +760,7 @@ process_put(struct sftp_conn *conn, cons
|
||||
if (globpath_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
|
||||
if (upload_dir(conn, g.gl_pathv[i], abs_dst,
|
||||
|
||||
diff --git a/sftp.c b/sftp.c
|
||||
--- a/sftp.c (revision 8241b9c0529228b4b86d88b1a6076fb9f97e4a99)
|
||||
+++ b/sftp.c (date 1703168795365)
|
||||
@@ -807,7 +807,7 @@
|
||||
(rflag || global_rflag)) {
|
||||
if (sftp_upload_dir(conn, g.gl_pathv[i], abs_dst,
|
||||
pflag || global_pflag, 1, resume,
|
||||
- fflag || global_fflag, 0) == -1)
|
||||
+ fflag || global_fflag, 0, 0) == -1)
|
||||
- fflag || global_fflag, 0, 0) == -1)
|
||||
+ fflag || global_fflag, 0, 0, 0) == -1)
|
||||
err = -1;
|
||||
} else {
|
||||
if (do_upload(conn, g.gl_pathv[i], abs_dst,
|
||||
@@ -1577,7 +1577,7 @@ parse_dispatch_command(struct sftp_conn
|
||||
if (sftp_upload(conn, g.gl_pathv[i], abs_dst,
|
||||
@@ -1642,7 +1642,7 @@
|
||||
if (path1 == NULL || *path1 == '\0')
|
||||
path1 = xstrdup(startdir);
|
||||
path1 = make_absolute(path1, *pwd);
|
||||
- if ((tmp = do_realpath(conn, path1)) == NULL) {
|
||||
+ if ((tmp = do_realpath(conn, path1, 0)) == NULL) {
|
||||
path1 = sftp_make_absolute(path1, *pwd);
|
||||
- if ((tmp = sftp_realpath(conn, path1)) == NULL) {
|
||||
+ if ((tmp = sftp_realpath(conn, path1, 0)) == NULL) {
|
||||
err = 1;
|
||||
break;
|
||||
}
|
||||
@@ -2160,7 +2160,7 @@ interactive_loop(struct sftp_conn *conn,
|
||||
@@ -2247,7 +2247,7 @@
|
||||
}
|
||||
#endif /* USE_LIBEDIT */
|
||||
|
||||
- remote_path = do_realpath(conn, ".");
|
||||
+ remote_path = do_realpath(conn, ".", 0);
|
||||
if (remote_path == NULL)
|
||||
|
||||
- if ((remote_path = sftp_realpath(conn, ".")) == NULL)
|
||||
+ if ((remote_path = sftp_realpath(conn, ".", 0)) == NULL)
|
||||
fatal("Need cwd");
|
||||
startdir = xstrdup(remote_path);
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
diff --color -ruNp a/ssh.c b/ssh.c
|
||||
--- a/ssh.c 2025-07-21 16:24:30.348843762 +0200
|
||||
+++ b/ssh.c 2025-07-21 16:27:20.477953307 +0200
|
||||
@@ -174,6 +174,17 @@ static int forward_confirms_pending = -1
|
||||
--- a/ssh.c 2025-07-17 14:08:37.880551301 +0200
|
||||
+++ b/ssh.c 2025-07-17 15:02:09.224627879 +0200
|
||||
@@ -175,6 +175,17 @@ static int forward_confirms_pending = -1
|
||||
extern int muxserver_sock;
|
||||
extern u_int muxclient_command;
|
||||
|
||||
@ -9,7 +9,7 @@ diff --color -ruNp a/ssh.c b/ssh.c
|
||||
+redhat_help_message(void)
|
||||
+{
|
||||
+ if (log_level_get() >= SYSLOG_LEVEL_DEBUG1 &&
|
||||
+ isatty(fileno(stderr))) {
|
||||
+ isatty(fileno(stderr))) {
|
||||
+ fprintf(stderr,
|
||||
+"\nThe link below provides guidance on resolving common SSH errors:\n"
|
||||
+" https://red.ht/support_rhel_ssh\n");
|
||||
@ -19,10 +19,10 @@ diff --color -ruNp a/ssh.c b/ssh.c
|
||||
/* Prints a help message to the user. This function never returns. */
|
||||
|
||||
static void
|
||||
@@ -1609,8 +1620,10 @@ main(int ac, char **av)
|
||||
@@ -1648,8 +1659,10 @@ main(int ac, char **av)
|
||||
/* Open a connection to the remote host. */
|
||||
if (ssh_connect(ssh, host, host_arg, addrs, &hostaddr, options.port,
|
||||
options.connection_attempts,
|
||||
if (ssh_connect(ssh, host, options.host_arg, addrs, &hostaddr,
|
||||
options.port, options.connection_attempts,
|
||||
- &timeout_ms, options.tcp_keep_alive) != 0)
|
||||
+ &timeout_ms, options.tcp_keep_alive) != 0) {
|
||||
+ redhat_help_message();
|
||||
|
||||
@ -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
|
||||
@ -13,8 +13,8 @@ diff -up openssh-8.7p1/scp.1.kill-scp openssh-8.7p1/scp.1
|
||||
--- openssh-8.7p1/scp.1.kill-scp 2021-09-16 12:09:02.646714578 +0200
|
||||
+++ openssh-8.7p1/scp.1 2021-09-16 12:26:49.978628226 +0200
|
||||
@@ -278,6 +278,13 @@ to print debugging messages about their
|
||||
This is helpful in
|
||||
debugging connection, authentication, and configuration problems.
|
||||
By default a 32KB buffer is used.
|
||||
.El
|
||||
.El
|
||||
+.Pp
|
||||
+Usage of SCP protocol can be blocked by creating a world-readable
|
||||
|
||||
@ -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,21 +0,0 @@
|
||||
diff --git a/ssh.c b/ssh.c
|
||||
index 89ca1940..559bf2af 100644
|
||||
--- a/ssh.c
|
||||
+++ b/ssh.c
|
||||
@@ -1124,6 +1124,8 @@ main(int ac, char **av)
|
||||
}
|
||||
}
|
||||
|
||||
+ ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
|
||||
+
|
||||
/*
|
||||
* Initialize "log" output. Since we are the client all output
|
||||
* goes to stderr unless otherwise specified by -y or -E.
|
||||
@@ -1652,7 +1654,6 @@ main(int ac, char **av)
|
||||
options.num_system_hostfiles);
|
||||
tilde_expand_paths(options.user_hostfiles, options.num_user_hostfiles);
|
||||
|
||||
- ssh_signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */
|
||||
ssh_signal(SIGCHLD, main_sigchld_handler);
|
||||
|
||||
/* Log into the remote system. Never returns if the login fails. */
|
||||
@ -14,9 +14,9 @@ diff --color -ru a/ssh.1 b/ssh.1
|
||||
.It ControlPersist
|
||||
.It DynamicForward
|
||||
+.It EnableSSHKeysign
|
||||
.It EnableEscapeCommandline
|
||||
.It EscapeChar
|
||||
.It ExitOnForwardFailure
|
||||
.It FingerprintHash
|
||||
@@ -538,6 +540,8 @@
|
||||
.It IdentitiesOnly
|
||||
.It IdentityAgent
|
||||
|
||||
@ -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-----
|
||||
595
SOURCES/openssh-9.0p1-evp-fips-kex.patch
Normal file
595
SOURCES/openssh-9.0p1-evp-fips-kex.patch
Normal file
@ -0,0 +1,595 @@
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/dh.c openssh-9.0p1-patched/dh.c
|
||||
--- openssh-9.0p1/dh.c 2023-05-25 09:24:28.730868316 +0200
|
||||
+++ openssh-9.0p1-patched/dh.c 2023-05-25 09:23:44.841379532 +0200
|
||||
@@ -37,6 +37,9 @@
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/fips.h>
|
||||
+#include <openssl/evp.h>
|
||||
+#include <openssl/core_names.h>
|
||||
+#include <openssl/param_build.h>
|
||||
|
||||
#include "dh.h"
|
||||
#include "pathnames.h"
|
||||
@@ -290,10 +293,15 @@
|
||||
int
|
||||
dh_gen_key(DH *dh, int need)
|
||||
{
|
||||
- int pbits;
|
||||
- const BIGNUM *dh_p, *pub_key;
|
||||
+ const BIGNUM *dh_p, *dh_g;
|
||||
+ BIGNUM *pub_key = NULL, *priv_key = NULL;
|
||||
+ EVP_PKEY *pkey = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ OSSL_PARAM *params = NULL;
|
||||
+ int pbits, r = 0;
|
||||
|
||||
- DH_get0_pqg(dh, &dh_p, NULL, NULL);
|
||||
+ DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
|
||||
|
||||
if (need < 0 || dh_p == NULL ||
|
||||
(pbits = BN_num_bits(dh_p)) <= 0 ||
|
||||
@@ -301,19 +309,85 @@
|
||||
return SSH_ERR_INVALID_ARGUMENT;
|
||||
if (need < 256)
|
||||
need = 256;
|
||||
+
|
||||
+ if ((param_bld = OSSL_PARAM_BLD_new()) == NULL ||
|
||||
+ (ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL) {
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ return SSH_ERR_ALLOC_FAIL;
|
||||
+ }
|
||||
+
|
||||
+ if (OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_FFC_P, dh_p) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_FFC_G, dh_g) != 1) {
|
||||
+ error_f("Could not set p,q,g parameters");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
/*
|
||||
* Pollard Rho, Big step/Little Step attacks are O(sqrt(n)),
|
||||
* so double requested need here.
|
||||
*/
|
||||
- if (!DH_set_length(dh, MINIMUM(need * 2, pbits - 1)))
|
||||
- return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
-
|
||||
- if (DH_generate_key(dh) == 0)
|
||||
- return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
- DH_get0_key(dh, &pub_key, NULL);
|
||||
- if (!dh_pub_is_valid(dh, pub_key))
|
||||
- return SSH_ERR_INVALID_FORMAT;
|
||||
- return 0;
|
||||
+ if (OSSL_PARAM_BLD_push_int(param_bld,
|
||||
+ OSSL_PKEY_PARAM_DH_PRIV_LEN,
|
||||
+ MINIMUM(need * 2, pbits - 1)) != 1 ||
|
||||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_fromdata_init(ctx) != 1) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_fromdata(ctx, &pkey,
|
||||
+ EVP_PKEY_KEY_PARAMETERS, params) != 1) {
|
||||
+ error_f("Failed key generation");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* reuse context for key generation */
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ ctx = NULL;
|
||||
+
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
|
||||
+ EVP_PKEY_keygen_init(ctx) != 1) {
|
||||
+ error_f("Could not create or init context");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_generate(ctx, &pkey) != 1) {
|
||||
+ error_f("Could not generate keys");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_public_check(ctx) != 1) {
|
||||
+ error_f("The public key is incorrect");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if (EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PUB_KEY,
|
||||
+ &pub_key) != 1 ||
|
||||
+ EVP_PKEY_get_bn_param(pkey, OSSL_PKEY_PARAM_PRIV_KEY,
|
||||
+ &priv_key) != 1 ||
|
||||
+ DH_set0_key(dh, pub_key, priv_key) != 1) {
|
||||
+ error_f("Could not set pub/priv keys to DH struct");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* transferred */
|
||||
+ pub_key = NULL;
|
||||
+ priv_key = NULL;
|
||||
+out:
|
||||
+ OSSL_PARAM_free(params);
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ BN_clear_free(pub_key);
|
||||
+ BN_clear_free(priv_key);
|
||||
+ return r;
|
||||
}
|
||||
|
||||
DH *
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.c openssh-9.0p1-patched/kex.c
|
||||
--- openssh-9.0p1/kex.c 2023-05-25 09:24:28.731868327 +0200
|
||||
+++ openssh-9.0p1-patched/kex.c 2023-05-25 09:23:44.841379532 +0200
|
||||
@@ -1623,3 +1623,142 @@
|
||||
return r;
|
||||
}
|
||||
|
||||
+#ifdef WITH_OPENSSL
|
||||
+/*
|
||||
+ * Creates an EVP_PKEY from the given parameters and keys.
|
||||
+ * The private key can be omitted.
|
||||
+ */
|
||||
+EVP_PKEY *
|
||||
+sshkey_create_evp(OSSL_PARAM_BLD *param_bld, EVP_PKEY_CTX *ctx)
|
||||
+{
|
||||
+ EVP_PKEY *ret = NULL;
|
||||
+ OSSL_PARAM *params = NULL;
|
||||
+ if (param_bld == NULL || ctx == NULL) {
|
||||
+ debug2_f("param_bld or ctx is NULL");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if ((params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
|
||||
+ debug2_f("Could not build param list");
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ if (EVP_PKEY_fromdata_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_fromdata(ctx, &ret, EVP_PKEY_KEYPAIR, params) != 1) {
|
||||
+ debug2_f("EVP_PKEY_fromdata failed");
|
||||
+ OSSL_PARAM_free(params);
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+kex_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey)
|
||||
+{
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ BN_CTX *bn_ctx = NULL;
|
||||
+ uint8_t *pub_ser = NULL;
|
||||
+ const char *group_name;
|
||||
+ const EC_POINT *pub = NULL;
|
||||
+ const BIGNUM *priv = NULL;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ if (k == NULL)
|
||||
+ return SSH_ERR_INVALID_ARGUMENT;
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL ||
|
||||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL ||
|
||||
+ (bn_ctx = BN_CTX_new()) == NULL) {
|
||||
+ ret = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((group_name = OSSL_EC_curve_nid2name(ecdsa_nid)) == NULL ||
|
||||
+ OSSL_PARAM_BLD_push_utf8_string(param_bld,
|
||||
+ OSSL_PKEY_PARAM_GROUP_NAME,
|
||||
+ group_name,
|
||||
+ strlen(group_name)) != 1) {
|
||||
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if ((pub = EC_KEY_get0_public_key(k)) != NULL) {
|
||||
+ const EC_GROUP *group;
|
||||
+ size_t len;
|
||||
+
|
||||
+ group = EC_KEY_get0_group(k);
|
||||
+ len = EC_POINT_point2oct(group, pub,
|
||||
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
|
||||
+ if ((pub_ser = malloc(len)) == NULL) {
|
||||
+ ret = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ EC_POINT_point2oct(group,
|
||||
+ pub,
|
||||
+ POINT_CONVERSION_UNCOMPRESSED,
|
||||
+ pub_ser,
|
||||
+ len,
|
||||
+ bn_ctx);
|
||||
+ if (OSSL_PARAM_BLD_push_octet_string(param_bld,
|
||||
+ OSSL_PKEY_PARAM_PUB_KEY,
|
||||
+ pub_ser,
|
||||
+ len) != 1) {
|
||||
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+ if ((priv = EC_KEY_get0_private_key(k)) != NULL &&
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) {
|
||||
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL) {
|
||||
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ BN_CTX_free(bn_ctx);
|
||||
+ free(pub_ser);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
+kex_create_evp_dh(EVP_PKEY **pkey, const BIGNUM *p, const BIGNUM *q,
|
||||
+ const BIGNUM *g, const BIGNUM *pub, const BIGNUM *priv)
|
||||
+{
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ int r = 0;
|
||||
+
|
||||
+ /* create EVP_PKEY-DH key */
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL)) == NULL ||
|
||||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL) {
|
||||
+ error_f("EVP_PKEY_CTX or PARAM_BLD init failed");
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_P, p) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_Q, q) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld, OSSL_PKEY_PARAM_FFC_G, g) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_PUB_KEY, pub) != 1) {
|
||||
+ error_f("Failed pushing params to OSSL_PARAM_BLD");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (priv != NULL &&
|
||||
+ OSSL_PARAM_BLD_push_BN(param_bld,
|
||||
+ OSSL_PKEY_PARAM_PRIV_KEY, priv) != 1) {
|
||||
+ error_f("Failed pushing private key to OSSL_PARAM_BLD");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if ((*pkey = sshkey_create_evp(param_bld, ctx)) == NULL)
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+out:
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ return r;
|
||||
+}
|
||||
+#endif /* WITH_OPENSSL */
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kexdh.c openssh-9.0p1-patched/kexdh.c
|
||||
--- openssh-9.0p1/kexdh.c 2023-05-25 09:24:28.674867692 +0200
|
||||
+++ openssh-9.0p1-patched/kexdh.c 2023-05-25 09:25:28.494533889 +0200
|
||||
@@ -35,6 +35,10 @@
|
||||
|
||||
#include "openbsd-compat/openssl-compat.h"
|
||||
#include <openssl/dh.h>
|
||||
+#include <openssl/err.h>
|
||||
+#include <openssl/evp.h>
|
||||
+#include <openssl/core_names.h>
|
||||
+#include <openssl/param_build.h>
|
||||
|
||||
#include "sshkey.h"
|
||||
#include "kex.h"
|
||||
@@ -83,9 +87,12 @@
|
||||
kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
|
||||
{
|
||||
BIGNUM *shared_secret = NULL;
|
||||
+ const BIGNUM *pub, *priv, *p, *q, *g;
|
||||
+ EVP_PKEY *pkey = NULL, *dh_pkey = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
u_char *kbuf = NULL;
|
||||
size_t klen = 0;
|
||||
- int kout, r;
|
||||
+ int r = 0;
|
||||
|
||||
#ifdef DEBUG_KEXDH
|
||||
fprintf(stderr, "dh_pub= ");
|
||||
@@ -100,24 +107,59 @@
|
||||
r = SSH_ERR_MESSAGE_INCOMPLETE;
|
||||
goto out;
|
||||
}
|
||||
- klen = DH_size(kex->dh);
|
||||
+
|
||||
+ DH_get0_key(kex->dh, &pub, &priv);
|
||||
+ DH_get0_pqg(kex->dh, &p, &q, &g);
|
||||
+ /* import key */
|
||||
+ r = kex_create_evp_dh(&pkey, p, q, g, pub, priv);
|
||||
+ if (r != 0) {
|
||||
+ error_f("Could not create EVP_PKEY for dh");
|
||||
+ ERR_print_errors_fp(stderr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* import peer key
|
||||
+ * the parameters should be the same as with pkey
|
||||
+ */
|
||||
+ r = kex_create_evp_dh(&dh_pkey, p, q, g, dh_pub, NULL);
|
||||
+ if (r != 0) {
|
||||
+ error_f("Could not import peer key for dh");
|
||||
+ ERR_print_errors_fp(stderr);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL) {
|
||||
+ error_f("Could not init EVP_PKEY_CTX for dh");
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_derive_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 ||
|
||||
+ EVP_PKEY_derive(ctx, NULL, &klen) != 1) {
|
||||
+ error_f("Could not get key size");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
if ((kbuf = malloc(klen)) == NULL ||
|
||||
(shared_secret = BN_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
- if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
|
||||
- BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
|
||||
+ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1 ||
|
||||
+ BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
|
||||
+ error_f("Could not derive key");
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_KEXDH
|
||||
- dump_digest("shared secret", kbuf, kout);
|
||||
+ dump_digest("shared secret", kbuf, klen);
|
||||
#endif
|
||||
r = sshbuf_put_bignum2(out, shared_secret);
|
||||
out:
|
||||
freezero(kbuf, klen);
|
||||
BN_clear_free(shared_secret);
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_free(dh_pkey);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
return r;
|
||||
}
|
||||
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac openssh-9.0p1/kex.h openssh-9.0p1-patched/kex.h
|
||||
--- openssh-9.0p1/kex.h 2023-05-25 09:24:28.725868260 +0200
|
||||
+++ openssh-9.0p1-patched/kex.h 2023-05-25 09:23:44.841379532 +0200
|
||||
@@ -33,6 +33,9 @@
|
||||
# include <openssl/bn.h>
|
||||
# include <openssl/dh.h>
|
||||
# include <openssl/ecdsa.h>
|
||||
+# include <openssl/evp.h>
|
||||
+# include <openssl/core_names.h>
|
||||
+# include <openssl/param_build.h>
|
||||
# ifdef OPENSSL_HAS_ECC
|
||||
# include <openssl/ec.h>
|
||||
# else /* OPENSSL_HAS_ECC */
|
||||
@@ -283,6 +286,9@@
|
||||
const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int)
|
||||
__attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
|
||||
__attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
|
||||
+int kex_create_evp_dh(EVP_PKEY **, const BIGNUM *, const BIGNUM *,
|
||||
+ const BIGNUM *, const BIGNUM *, const BIGNUM *);
|
||||
+int kex_create_evp_ec(EC_KEY *k, int ecdsa_nid, EVP_PKEY **pkey);
|
||||
|
||||
#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
|
||||
void dump_digest(const char *, const u_char *, int);
|
||||
diff --color -ru -x regress -x autom4te.cache -x '*.o' -x '*.lo' -x Makefile -x config.status -x configure~ -x configure.ac ../openssh-8.7p1/kexecdh.c ./kexecdh.c
|
||||
--- ../openssh-8.7p1/kexecdh.c 2021-08-20 06:03:49.000000000 +0200
|
||||
+++ ./kexecdh.c 2023-04-13 14:30:14.882449593 +0200
|
||||
@@ -35,17 +35,57 @@
|
||||
#include <signal.h>
|
||||
|
||||
#include <openssl/ecdh.h>
|
||||
+#include <openssl/evp.h>
|
||||
+#include <openssl/core_names.h>
|
||||
+#include <openssl/param_build.h>
|
||||
+#include <openssl/err.h>
|
||||
|
||||
#include "sshkey.h"
|
||||
#include "kex.h"
|
||||
#include "sshbuf.h"
|
||||
#include "digest.h"
|
||||
#include "ssherr.h"
|
||||
+#include "log.h"
|
||||
|
||||
static int
|
||||
kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key,
|
||||
const EC_GROUP *, struct sshbuf **);
|
||||
|
||||
+static EC_KEY *
|
||||
+generate_ec_keys(int ec_nid)
|
||||
+{
|
||||
+ EC_KEY *client_key = NULL;
|
||||
+ EVP_PKEY *pkey = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ OSSL_PARAM *params = NULL;
|
||||
+ const char *group_name;
|
||||
+
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_name(NULL, "EC", NULL)) == NULL ||
|
||||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL)
|
||||
+ goto out;
|
||||
+ if ((group_name = OSSL_EC_curve_nid2name(ec_nid)) == NULL ||
|
||||
+ OSSL_PARAM_BLD_push_utf8_string(param_bld,
|
||||
+ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 ||
|
||||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
|
||||
+ error_f("Could not create OSSL_PARAM");
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_keygen_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_CTX_set_params(ctx, params) != 1 ||
|
||||
+ EVP_PKEY_generate(ctx, &pkey) != 1 ||
|
||||
+ (client_key = EVP_PKEY_get1_EC_KEY(pkey)) == NULL) {
|
||||
+ error_f("Could not generate ec keys");
|
||||
+ goto out;
|
||||
+ }
|
||||
+out:
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ OSSL_PARAM_free(params);
|
||||
+ return client_key;
|
||||
+}
|
||||
+
|
||||
int
|
||||
kex_ecdh_keypair(struct kex *kex)
|
||||
{
|
||||
@@ -55,11 +95,7 @@
|
||||
struct sshbuf *buf = NULL;
|
||||
int r;
|
||||
|
||||
- if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
|
||||
- r = SSH_ERR_ALLOC_FAIL;
|
||||
- goto out;
|
||||
- }
|
||||
- if (EC_KEY_generate_key(client_key) != 1) {
|
||||
+ if ((client_key = generate_ec_keys(kex->ec_nid)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
@@ -101,11 +137,7 @@
|
||||
*server_blobp = NULL;
|
||||
*shared_secretp = NULL;
|
||||
|
||||
- if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
|
||||
- r = SSH_ERR_ALLOC_FAIL;
|
||||
- goto out;
|
||||
- }
|
||||
- if (EC_KEY_generate_key(server_key) != 1) {
|
||||
+ if ((server_key = generate_ec_keys(kex->ec_nid)) == NULL) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
@@ -140,11 +172,21 @@
|
||||
{
|
||||
struct sshbuf *buf = NULL;
|
||||
BIGNUM *shared_secret = NULL;
|
||||
- EC_POINT *dh_pub = NULL;
|
||||
- u_char *kbuf = NULL;
|
||||
- size_t klen = 0;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ EVP_PKEY *pkey = NULL, *dh_pkey = NULL;
|
||||
+ OSSL_PARAM_BLD *param_bld = NULL;
|
||||
+ OSSL_PARAM *params = NULL;
|
||||
+ u_char *kbuf = NULL, *pub = NULL;
|
||||
+ size_t klen = 0, publen;
|
||||
+ const char *group_name;
|
||||
int r;
|
||||
|
||||
+ /* import EC_KEY to EVP_PKEY */
|
||||
+ if ((r = kex_create_evp_ec(key, kex->ec_nid, &pkey)) != 0) {
|
||||
+ error_f("Could not create EVP_PKEY");
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
*shared_secretp = NULL;
|
||||
|
||||
if ((buf = sshbuf_new()) == NULL) {
|
||||
@@ -153,45 +195,82 @@
|
||||
}
|
||||
if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0)
|
||||
goto out;
|
||||
- if ((dh_pub = EC_POINT_new(group)) == NULL) {
|
||||
+
|
||||
+ /* the public key is in the buffer in octet string UNCOMPRESSED
|
||||
+ * format. See sshbuf_put_ec */
|
||||
+ if ((r = sshbuf_get_string(buf, &pub, &publen)) != 0)
|
||||
+ goto out;
|
||||
+ sshbuf_reset(buf);
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
|
||||
+ (param_bld = OSSL_PARAM_BLD_new()) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
- if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) {
|
||||
+ if ((group_name = OSSL_EC_curve_nid2name(kex->ec_nid)) == NULL) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (OSSL_PARAM_BLD_push_octet_string(param_bld,
|
||||
+ OSSL_PKEY_PARAM_PUB_KEY, pub, publen) != 1 ||
|
||||
+ OSSL_PARAM_BLD_push_utf8_string(param_bld,
|
||||
+ OSSL_PKEY_PARAM_GROUP_NAME, group_name, 0) != 1 ||
|
||||
+ (params = OSSL_PARAM_BLD_to_param(param_bld)) == NULL) {
|
||||
+ error_f("Failed to set params for dh_pkey");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (EVP_PKEY_fromdata_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_fromdata(ctx, &dh_pkey,
|
||||
+ EVP_PKEY_PUBLIC_KEY, params) != 1 ||
|
||||
+ EVP_PKEY_public_check(ctx) != 1) {
|
||||
+ error_f("Peer public key import failed");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
- sshbuf_reset(buf);
|
||||
|
||||
#ifdef DEBUG_KEXECDH
|
||||
fputs("public key:\n", stderr);
|
||||
- sshkey_dump_ec_point(group, dh_pub);
|
||||
+ EVP_PKEY_print_public_fp(stderr, dh_pkey, 0, NULL);
|
||||
#endif
|
||||
- if (sshkey_ec_validate_public(group, dh_pub) != 0) {
|
||||
- r = SSH_ERR_MESSAGE_INCOMPLETE;
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ ctx = NULL;
|
||||
+ if ((ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL)) == NULL ||
|
||||
+ EVP_PKEY_derive_init(ctx) != 1 ||
|
||||
+ EVP_PKEY_derive_set_peer(ctx, dh_pkey) != 1 ||
|
||||
+ EVP_PKEY_derive(ctx, NULL, &klen) != 1) {
|
||||
+ error_f("Failed to get derive information");
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
- klen = (EC_GROUP_get_degree(group) + 7) / 8;
|
||||
- if ((kbuf = malloc(klen)) == NULL ||
|
||||
- (shared_secret = BN_new()) == NULL) {
|
||||
+ if ((kbuf = malloc(klen)) == NULL) {
|
||||
r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
- if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen ||
|
||||
- BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
|
||||
+ if (EVP_PKEY_derive(ctx, kbuf, &klen) != 1) {
|
||||
r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
goto out;
|
||||
}
|
||||
#ifdef DEBUG_KEXECDH
|
||||
dump_digest("shared secret", kbuf, klen);
|
||||
#endif
|
||||
+ if ((shared_secret = BN_new()) == NULL ||
|
||||
+ (BN_bin2bn(kbuf, klen, shared_secret) == NULL)) {
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0)
|
||||
goto out;
|
||||
*shared_secretp = buf;
|
||||
buf = NULL;
|
||||
out:
|
||||
- EC_POINT_clear_free(dh_pub);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_free(dh_pkey);
|
||||
+ OSSL_PARAM_BLD_free(param_bld);
|
||||
+ OSSL_PARAM_free(params);
|
||||
BN_clear_free(shared_secret);
|
||||
freezero(kbuf, klen);
|
||||
+ freezero(pub, publen);
|
||||
sshbuf_free(buf);
|
||||
return r;
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
32
SOURCES/openssh-9.6p1-pam-rhost.patch
Normal file
32
SOURCES/openssh-9.6p1-pam-rhost.patch
Normal file
@ -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),
|
||||
68
SOURCES/openssh-9.9p1-bad-hostkey.patch
Normal file
68
SOURCES/openssh-9.9p1-bad-hostkey.patch
Normal file
@ -0,0 +1,68 @@
|
||||
diff --color -ruNp a/hostfile.c b/hostfile.c
|
||||
--- a/hostfile.c 2024-09-20 00:20:48.000000000 +0200
|
||||
+++ b/hostfile.c 2025-04-30 15:52:02.792091018 +0200
|
||||
@@ -63,6 +63,14 @@
|
||||
#include "hmac.h"
|
||||
#include "sshbuf.h"
|
||||
|
||||
+static int required_rsa_size = SSH_RSA_MINIMUM_MODULUS_SIZE;
|
||||
+
|
||||
+void
|
||||
+hostfile_set_minimum_rsa_size(int size)
|
||||
+{
|
||||
+ required_rsa_size = size;
|
||||
+}
|
||||
+
|
||||
/* XXX hmac is too easy to dictionary attack; use bcrypt? */
|
||||
|
||||
static int
|
||||
@@ -233,6 +241,7 @@ record_hostkey(struct hostkey_foreach_li
|
||||
struct load_callback_ctx *ctx = (struct load_callback_ctx *)_ctx;
|
||||
struct hostkeys *hostkeys = ctx->hostkeys;
|
||||
struct hostkey_entry *tmp;
|
||||
+ int r = 0;
|
||||
|
||||
if (l->status == HKF_STATUS_INVALID) {
|
||||
/* XXX make this verbose() in the future */
|
||||
@@ -241,6 +250,12 @@ record_hostkey(struct hostkey_foreach_li
|
||||
return 0;
|
||||
}
|
||||
|
||||
+ if ((r = sshkey_check_rsa_length(l->key, required_rsa_size)) != 0) {
|
||||
+ debug2_f("%s:%ld: ignoring hostkey: %s",
|
||||
+ l->path, l->linenum, ssh_err(r));
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
debug3_f("found %skey type %s in file %s:%lu",
|
||||
l->marker == MRK_NONE ? "" :
|
||||
(l->marker == MRK_CA ? "ca " : "revoked "),
|
||||
diff --color -ruNp a/hostfile.h b/hostfile.h
|
||||
--- a/hostfile.h 2024-09-20 00:20:48.000000000 +0200
|
||||
+++ b/hostfile.h 2025-04-30 15:17:44.789206468 +0200
|
||||
@@ -119,5 +119,6 @@ int hostkeys_foreach_file(const char *pa
|
||||
const char *host, const char *ip, u_int options, u_int note);
|
||||
|
||||
void hostfile_create_user_ssh_dir(const char *, int);
|
||||
+void hostfile_set_minimum_rsa_size(int);
|
||||
|
||||
#endif
|
||||
diff --color -ruNp a/ssh.c b/ssh.c
|
||||
--- a/ssh.c 2025-04-29 15:40:27.916735894 +0200
|
||||
+++ b/ssh.c 2025-04-30 15:19:48.856855308 +0200
|
||||
@@ -109,6 +109,7 @@
|
||||
#include "ssherr.h"
|
||||
#include "myproposal.h"
|
||||
#include "utf8.h"
|
||||
+#include "hostfile.h"
|
||||
|
||||
#ifdef ENABLE_PKCS11
|
||||
#include "ssh-pkcs11.h"
|
||||
@@ -1395,6 +1396,7 @@ main(int ac, char **av)
|
||||
options.update_hostkeys = 0;
|
||||
}
|
||||
}
|
||||
+ hostfile_set_minimum_rsa_size(options.required_rsa_size);
|
||||
if (options.connection_attempts <= 0)
|
||||
fatal("Invalid number of ConnectionAttempts");
|
||||
|
||||
120
SOURCES/openssh-9.9p1-canonical-match-user.patch
Normal file
120
SOURCES/openssh-9.9p1-canonical-match-user.patch
Normal file
@ -0,0 +1,120 @@
|
||||
diff --color -ruNp a/auth.c b/auth.c
|
||||
--- a/auth.c 2025-10-29 09:57:20.440640281 +0100
|
||||
+++ b/auth.c 2025-10-29 09:57:54.747956792 +0100
|
||||
@@ -476,8 +476,12 @@ getpwnamallow(struct ssh *ssh, const cha
|
||||
u_int i;
|
||||
|
||||
ci = server_get_connection_info(ssh, 1, options.use_dns);
|
||||
- ci->user = user;
|
||||
- ci->user_invalid = getpwnam(user) == NULL;
|
||||
+ pw = getpwnam(user);
|
||||
+ if (pw != NULL && options.canonical_match_user)
|
||||
+ ci->user = pw->pw_name;
|
||||
+ else
|
||||
+ ci->user = user;
|
||||
+ ci->user_invalid = pw == NULL;
|
||||
parse_server_match_config(&options, &includes, ci);
|
||||
log_change_level(options.log_level);
|
||||
log_verbose_reset();
|
||||
diff --color -ruNp a/servconf.c b/servconf.c
|
||||
--- a/servconf.c 2025-10-29 09:57:20.502465586 +0100
|
||||
+++ b/servconf.c 2025-10-29 09:57:54.748205464 +0100
|
||||
@@ -225,6 +225,7 @@ initialize_server_options(ServerOptions
|
||||
options->unused_connection_timeout = -1;
|
||||
options->sshd_session_path = NULL;
|
||||
options->refuse_connection = -1;
|
||||
+ options->canonical_match_user = -1;
|
||||
}
|
||||
|
||||
/* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
|
||||
@@ -526,6 +527,8 @@ fill_default_server_options(ServerOption
|
||||
options->sshd_session_path = xstrdup(_PATH_SSHD_SESSION);
|
||||
if (options->refuse_connection == -1)
|
||||
options->refuse_connection = 0;
|
||||
+ if (options->canonical_match_user == -1)
|
||||
+ options->canonical_match_user = 0;
|
||||
|
||||
assemble_algorithms(options);
|
||||
|
||||
@@ -609,7 +612,7 @@ typedef enum {
|
||||
sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
|
||||
sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider,
|
||||
sRequiredRSASize, sChannelTimeout, sUnusedConnectionTimeout,
|
||||
- sSshdSessionPath, sRefuseConnection,
|
||||
+ sSshdSessionPath, sRefuseConnection, sCanonicalMatchUser,
|
||||
sDeprecated, sIgnore, sUnsupported
|
||||
} ServerOpCodes;
|
||||
|
||||
@@ -798,6 +801,7 @@ static struct {
|
||||
{ "unusedconnectiontimeout", sUnusedConnectionTimeout, SSHCFG_ALL },
|
||||
{ "sshdsessionpath", sSshdSessionPath, SSHCFG_GLOBAL },
|
||||
{ "refuseconnection", sRefuseConnection, SSHCFG_ALL },
|
||||
+ { "canonicalmatchuser", sCanonicalMatchUser, SSHCFG_GLOBAL },
|
||||
{ NULL, sBadOption, 0 }
|
||||
};
|
||||
|
||||
@@ -2807,6 +2811,11 @@ process_server_config_line_depth(ServerO
|
||||
multistate_ptr = multistate_flag;
|
||||
goto parse_multistate;
|
||||
|
||||
+ case sCanonicalMatchUser:
|
||||
+ intptr = &options->canonical_match_user;
|
||||
+ multistate_ptr = multistate_flag;
|
||||
+ goto parse_multistate;
|
||||
+
|
||||
case sDeprecated:
|
||||
case sIgnore:
|
||||
case sUnsupported:
|
||||
@@ -3028,6 +3037,7 @@ copy_set_server_options(ServerOptions *d
|
||||
M_CP_INTOPT(required_rsa_size);
|
||||
M_CP_INTOPT(unused_connection_timeout);
|
||||
M_CP_INTOPT(refuse_connection);
|
||||
+ M_CP_INTOPT(canonical_match_user);
|
||||
|
||||
/*
|
||||
* The bind_mask is a mode_t that may be unsigned, so we can't use
|
||||
@@ -3368,6 +3378,7 @@ dump_config(ServerOptions *o)
|
||||
dump_cfg_fmtint(sFingerprintHash, o->fingerprint_hash);
|
||||
dump_cfg_fmtint(sExposeAuthInfo, o->expose_userauth_info);
|
||||
dump_cfg_fmtint(sRefuseConnection, o->refuse_connection);
|
||||
+ dump_cfg_fmtint(sCanonicalMatchUser, o->canonical_match_user);
|
||||
|
||||
/* string arguments */
|
||||
dump_cfg_string(sPidFile, o->pid_file);
|
||||
diff --color -ruNp a/servconf.h b/servconf.h
|
||||
--- a/servconf.h 2025-10-29 09:57:20.503199202 +0100
|
||||
+++ b/servconf.h 2025-10-29 09:57:54.749236422 +0100
|
||||
@@ -261,6 +261,8 @@ typedef struct {
|
||||
char *sshd_session_path;
|
||||
|
||||
int refuse_connection;
|
||||
+
|
||||
+ int canonical_match_user;
|
||||
} ServerOptions;
|
||||
|
||||
/* Information about the incoming connection as used by Match */
|
||||
diff --color -ruNp a/sshd_config.5 b/sshd_config.5
|
||||
--- a/sshd_config.5 2025-10-29 09:57:20.503465608 +0100
|
||||
+++ b/sshd_config.5 2025-10-29 09:57:54.749544972 +0100
|
||||
@@ -1384,6 +1384,7 @@ Available keywords are
|
||||
.Cm PubkeyAuthentication ,
|
||||
.Cm PubkeyAuthOptions ,
|
||||
.Cm RefuseConnection ,
|
||||
+.Cm CanonicalMatchUser ,
|
||||
.Cm RekeyLimit ,
|
||||
.Cm RevokedKeys ,
|
||||
.Cm RDomain ,
|
||||
@@ -1828,6 +1829,13 @@ are enabled.
|
||||
This option is only really useful in a
|
||||
.Cm Match
|
||||
block.
|
||||
+.It Cm CanonicalMatchUser
|
||||
+Some password databases allow users to define aliases for their username.
|
||||
+This directive indicates that
|
||||
+.Xr sshd 8
|
||||
+should attempt to first obtain a canonical username from a password database before evaluating a
|
||||
+.Cm Match User
|
||||
+conditional block.
|
||||
.It Cm RekeyLimit
|
||||
Specifies the maximum amount of data that may be transmitted or received
|
||||
before the session key is renegotiated, optionally followed by a maximum
|
||||
101
SOURCES/openssh-9.9p1-compat-mlkem.patch
Normal file
101
SOURCES/openssh-9.9p1-compat-mlkem.patch
Normal file
@ -0,0 +1,101 @@
|
||||
diff -up openssh-9.9p1/compat.c.xxx openssh-9.9p1/compat.c
|
||||
--- openssh-9.9p1/compat.c.xxx 2026-02-25 12:58:14.083760269 +0100
|
||||
+++ openssh-9.9p1/compat.c 2026-02-25 13:28:21.154300255 +0100
|
||||
@@ -36,6 +36,9 @@
|
||||
#include "compat.h"
|
||||
#include "log.h"
|
||||
#include "match.h"
|
||||
+#include <openssl/err.h>
|
||||
+#include <openssl/evp.h>
|
||||
+#include <openssl/fips.h>
|
||||
|
||||
/* determine bug flags from SSH protocol banner */
|
||||
void
|
||||
@@ -143,13 +145,40 @@ compat_banner(struct ssh *ssh, const cha
|
||||
ssh->compat |= SSH_RH_RSASIGSHA;
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * 0 - unavailable
|
||||
+ * 1 - available in non-FIPS mode
|
||||
+ * 2 - available always
|
||||
+ */
|
||||
+static int is_mlkem768_available()
|
||||
+{
|
||||
+ static int is_fetched = -1;
|
||||
+
|
||||
+ if (is_fetched == -1) {
|
||||
+ EVP_KEM *mlkem768 = NULL;
|
||||
+
|
||||
+ ERR_set_mark();
|
||||
+ mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", NULL);
|
||||
+ is_fetched = (mlkem768 == NULL) ? 0 : 2;
|
||||
+ if (is_fetched == 0 && FIPS_mode() == 1) {
|
||||
+ mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", "provider=default,-fips");
|
||||
+ is_fetched = (mlkem768 == NULL) ? 0 : 1;
|
||||
+ }
|
||||
+ EVP_KEM_free(mlkem768);
|
||||
+ ERR_pop_to_mark();
|
||||
+ }
|
||||
+
|
||||
+ return is_fetched;
|
||||
+}
|
||||
+
|
||||
/* Always returns pointer to allocated memory, caller must free. */
|
||||
char *
|
||||
compat_kex_proposal(struct ssh *ssh, const char *p)
|
||||
{
|
||||
char *cp = NULL, *cp2 = NULL;
|
||||
+ int ml_kem_available = is_mlkem768_available();
|
||||
|
||||
- if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0)
|
||||
+ if ((ssh->compat & (SSH_BUG_CURVE25519PAD|SSH_OLD_DHGEX)) == 0 && is_mlkem768_available() == 2)
|
||||
return xstrdup(p);
|
||||
debug2_f("original KEX proposal: %s", p);
|
||||
if ((ssh->compat & SSH_BUG_CURVE25519PAD) != 0)
|
||||
@@ -164,6 +199,25 @@ compat_kex_proposal(struct ssh *ssh, con
|
||||
free(cp);
|
||||
cp = cp2;
|
||||
}
|
||||
+ if (ml_kem_available == 2)
|
||||
+ return cp ? cp : xstrdup(p);
|
||||
+ if (ml_kem_available == 1 && FIPS_mode()) {
|
||||
+ if ((cp2 = match_filter_denylist(cp ? cp : p,
|
||||
+ "mlkem768x25519-sha256")) == NULL)
|
||||
+ fatal("match_filter_denylist failed");
|
||||
+ free(cp);
|
||||
+ cp = cp2;
|
||||
+ }
|
||||
+ if (ml_kem_available == 0) {
|
||||
+ if ((cp2 = match_filter_denylist(cp ? cp : p,
|
||||
+ "mlkem768x25519-sha256,"
|
||||
+ "mlkem768nistp256-sha256,"
|
||||
+ "mlkem1024nistp384-sha384")) == NULL)
|
||||
+ fatal("match_filter_denylist failed");
|
||||
+ free(cp);
|
||||
+ cp = cp2;
|
||||
+ }
|
||||
+
|
||||
if (cp == NULL || *cp == '\0')
|
||||
fatal("No supported key exchange algorithms found");
|
||||
debug2_f("compat KEX proposal: %s", cp);
|
||||
diff -up openssh-9.9p1/kex-names.c.xxx openssh-9.9p1/kex-names.c
|
||||
--- openssh-9.9p1/kex-names.c.xxx 2026-02-25 14:52:59.802597974 +0100
|
||||
+++ openssh-9.9p1/kex-names.c 2026-02-25 15:31:13.376020525 +0100
|
||||
@@ -291,8 +291,14 @@ kex_names_valid(const char *names)
|
||||
for ((p = strsep(&cp, ",")); p && *p != '\0';
|
||||
(p = strsep(&cp, ","))) {
|
||||
if (kex_alg_by_name(p) == NULL) {
|
||||
- if (FIPS_mode())
|
||||
- error("\"%.100s\" is not allowed in FIPS mode", p);
|
||||
+ if (FIPS_mode()) {
|
||||
+ if ((strcmp(p, KEX_MLKEM768X25519_SHA256) == 0)) {
|
||||
+ debug("\"%.100s\" is not allowed in FIPS mode", p);
|
||||
+ continue;
|
||||
+ }
|
||||
+ else
|
||||
+ error("\"%.100s\" is not allowed in FIPS mode", p);
|
||||
+ }
|
||||
else
|
||||
error("Unsupported KEX algorithm \"%.100s\"", p);
|
||||
free(s);
|
||||
13
SOURCES/openssh-9.9p1-compression-directive.patch
Normal file
13
SOURCES/openssh-9.9p1-compression-directive.patch
Normal file
@ -0,0 +1,13 @@
|
||||
diff --git a/readconf.c b/readconf.c
|
||||
index 9f559269..777739d6 100644
|
||||
--- a/readconf.c
|
||||
+++ b/readconf.c
|
||||
@@ -3410,6 +3410,8 @@ fmt_intarg(OpCodes code, int val)
|
||||
switch (code) {
|
||||
case oAddressFamily:
|
||||
return fmt_multistate_int(val, multistate_addressfamily);
|
||||
+ case oCompression:
|
||||
+ return fmt_multistate_int(val, multistate_compression);
|
||||
case oVerifyHostKeyDNS:
|
||||
case oUpdateHostkeys:
|
||||
return fmt_multistate_int(val, multistate_yesnoask);
|
||||
22
SOURCES/openssh-9.9p1-disable-forwarding.patch
Normal file
22
SOURCES/openssh-9.9p1-disable-forwarding.patch
Normal file
@ -0,0 +1,22 @@
|
||||
diff --color -ruNp a/session.c b/session.c
|
||||
--- a/session.c 2025-04-29 11:20:59.475107377 +0200
|
||||
+++ b/session.c 2025-04-29 11:23:16.638538968 +0200
|
||||
@@ -2284,7 +2284,8 @@ session_auth_agent_req(struct ssh *ssh,
|
||||
if ((r = sshpkt_get_end(ssh)) != 0)
|
||||
sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
|
||||
if (!auth_opts->permit_agent_forwarding_flag ||
|
||||
- !options.allow_agent_forwarding) {
|
||||
+ !options.allow_agent_forwarding ||
|
||||
+ options.disable_forwarding) {
|
||||
debug_f("agent forwarding disabled");
|
||||
return 0;
|
||||
}
|
||||
@@ -2709,7 +2710,7 @@ session_setup_x11fwd(struct ssh *ssh, Se
|
||||
ssh_packet_send_debug(ssh, "X11 forwarding disabled by key options.");
|
||||
return 0;
|
||||
}
|
||||
- if (!options.x11_forwarding) {
|
||||
+ if (!options.x11_forwarding || options.disable_forwarding) {
|
||||
debug("X11 forwarding disabled in server configuration file.");
|
||||
return 0;
|
||||
}
|
||||
42
SOURCES/openssh-9.9p1-fips-gss.patch
Normal file
42
SOURCES/openssh-9.9p1-fips-gss.patch
Normal file
@ -0,0 +1,42 @@
|
||||
diff -up openssh-9.9p1-build/openssh-9.9p1/gss-genr.c.xxx openssh-9.9p1-build/openssh-9.9p1/gss-genr.c
|
||||
--- a/gss-genr.c.xxx 2025-09-01 17:15:41.070677784 +0200
|
||||
+++ b/gss-genr.c 2025-09-01 17:31:20.376362078 +0200
|
||||
@@ -149,19 +149,29 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup
|
||||
for (i = 0; i < gss_supported->count; i++) {
|
||||
if (gss_supported->elements[i].length < 128 &&
|
||||
(*check)(NULL, &(gss_supported->elements[i]), host, client)) {
|
||||
+ EVP_MD_CTX * ctx = NULL;
|
||||
+ EVP_MD *md5 = NULL; /* Here we don't use MD5 for crypto purposes */
|
||||
+ unsigned int md_size = sizeof(digest);
|
||||
|
||||
deroid[0] = SSH_GSS_OIDTYPE;
|
||||
deroid[1] = gss_supported->elements[i].length;
|
||||
-
|
||||
- if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
|
||||
- (r = ssh_digest_update(md, deroid, 2)) != 0 ||
|
||||
- (r = ssh_digest_update(md,
|
||||
- gss_supported->elements[i].elements,
|
||||
- gss_supported->elements[i].length)) != 0 ||
|
||||
- (r = ssh_digest_final(md, digest, sizeof(digest))) != 0)
|
||||
+ if ((md5 = EVP_MD_fetch(NULL, "MD5", "provider=default,-fips")) == NULL)
|
||||
+ fatal_fr(r, "MD5 fetch failed");
|
||||
+ if ((ctx = EVP_MD_CTX_new()) == NULL) {
|
||||
+ EVP_MD_free(md5);
|
||||
+ fatal_fr(r, "digest ctx failed");
|
||||
+ }
|
||||
+ if (EVP_DigestInit(ctx, md5) <= 0
|
||||
+ || EVP_DigestUpdate(ctx, deroid, 2) <= 0
|
||||
+ || EVP_DigestUpdate(ctx, gss_supported->elements[i].elements,
|
||||
+ gss_supported->elements[i].length) <= 0
|
||||
+ || EVP_DigestFinal(ctx, digest, &md_size) <= 0) {
|
||||
+ EVP_MD_free(md5);
|
||||
+ EVP_MD_CTX_free(ctx);
|
||||
fatal_fr(r, "digest failed");
|
||||
- ssh_digest_free(md);
|
||||
- md = NULL;
|
||||
+ }
|
||||
+ EVP_MD_free(md5); md5 = NULL;
|
||||
+ EVP_MD_CTX_free(ctx); ctx = NULL;
|
||||
|
||||
encoded = xmalloc(ssh_digest_bytes(SSH_DIGEST_MD5)
|
||||
* 2);
|
||||
471
SOURCES/openssh-9.9p1-match-regression.patch
Normal file
471
SOURCES/openssh-9.9p1-match-regression.patch
Normal file
@ -0,0 +1,471 @@
|
||||
diff --git a/misc.c b/misc.c
|
||||
index afdf5142..1b4b55c5 100644
|
||||
--- a/misc.c
|
||||
+++ b/misc.c
|
||||
@@ -107,6 +107,27 @@ rtrim(char *s)
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * returns pointer to character after 'prefix' in 's' or otherwise NULL
|
||||
+ * if the prefix is not present.
|
||||
+ */
|
||||
+const char *
|
||||
+strprefix(const char *s, const char *prefix, int ignorecase)
|
||||
+{
|
||||
+ size_t prefixlen;
|
||||
+
|
||||
+ if ((prefixlen = strlen(prefix)) == 0)
|
||||
+ return s;
|
||||
+ if (ignorecase) {
|
||||
+ if (strncasecmp(s, prefix, prefixlen) != 0)
|
||||
+ return NULL;
|
||||
+ } else {
|
||||
+ if (strncmp(s, prefix, prefixlen) != 0)
|
||||
+ return NULL;
|
||||
+ }
|
||||
+ return s + prefixlen;
|
||||
+}
|
||||
+
|
||||
/* set/unset filedescriptor to non-blocking */
|
||||
int
|
||||
set_nonblock(int fd)
|
||||
diff --git a/misc.h b/misc.h
|
||||
index 11340389..efecdf1a 100644
|
||||
--- a/misc.h
|
||||
+++ b/misc.h
|
||||
@@ -56,6 +56,7 @@ struct ForwardOptions {
|
||||
char *chop(char *);
|
||||
void rtrim(char *);
|
||||
void skip_space(char **);
|
||||
+const char *strprefix(const char *, const char *, int);
|
||||
char *strdelim(char **);
|
||||
char *strdelimw(char **);
|
||||
int set_nonblock(int);
|
||||
diff --git a/readconf.c b/readconf.c
|
||||
index 3d9cc6db..9f559269 100644
|
||||
--- a/readconf.c
|
||||
+++ b/readconf.c
|
||||
@@ -710,7 +710,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
|
||||
struct passwd *pw, const char *host_arg, const char *original_host,
|
||||
int final_pass, int *want_final_pass, const char *filename, int linenum)
|
||||
{
|
||||
- char *arg, *oattrib, *attrib, *cmd, *host, *criteria;
|
||||
+ char *arg, *oattrib = NULL, *attrib = NULL, *cmd, *host, *criteria;
|
||||
const char *ruser;
|
||||
int r, this_result, result = 1, attributes = 0, negate;
|
||||
|
||||
@@ -731,7 +731,8 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
|
||||
|
||||
debug2("checking match for '%s' host %s originally %s",
|
||||
full_line, host, original_host);
|
||||
- while ((oattrib = attrib = argv_next(acp, avp)) != NULL) {
|
||||
+ while ((attrib = argv_next(acp, avp)) != NULL) {
|
||||
+ attrib = oattrib = xstrdup(attrib);
|
||||
/* Terminate on comment */
|
||||
if (*attrib == '#') {
|
||||
argv_consume(acp);
|
||||
@@ -777,9 +778,23 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
|
||||
this_result ? "" : "not ", oattrib);
|
||||
continue;
|
||||
}
|
||||
+
|
||||
+ /* Keep this list in sync with below */
|
||||
+ if (strprefix(attrib, "host=", 1) != NULL ||
|
||||
+ strprefix(attrib, "originalhost=", 1) != NULL ||
|
||||
+ strprefix(attrib, "user=", 1) != NULL ||
|
||||
+ strprefix(attrib, "localuser=", 1) != NULL ||
|
||||
+ strprefix(attrib, "localnetwork=", 1) != NULL ||
|
||||
+ strprefix(attrib, "tagged=", 1) != NULL ||
|
||||
+ strprefix(attrib, "exec=", 1) != NULL) {
|
||||
+ arg = strchr(attrib, '=');
|
||||
+ *(arg++) = '\0';
|
||||
+ } else {
|
||||
+ arg = argv_next(acp, avp);
|
||||
+ }
|
||||
+
|
||||
/* All other criteria require an argument */
|
||||
- if ((arg = argv_next(acp, avp)) == NULL ||
|
||||
- *arg == '\0' || *arg == '#') {
|
||||
+ if (arg == NULL || *arg == '\0' || *arg == '#') {
|
||||
error("Missing Match criteria for %s", attrib);
|
||||
result = -1;
|
||||
goto out;
|
||||
@@ -856,6 +871,8 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
|
||||
criteria == NULL ? "" : criteria,
|
||||
criteria == NULL ? "" : "\"");
|
||||
free(criteria);
|
||||
+ free(oattrib);
|
||||
+ oattrib = attrib = NULL;
|
||||
}
|
||||
if (attributes == 0) {
|
||||
error("One or more attributes required for Match");
|
||||
@@ -865,6 +882,7 @@ match_cfg_line(Options *options, const char *full_line, int *acp, char ***avp,
|
||||
out:
|
||||
if (result != -1)
|
||||
debug2("match %sfound", result ? "" : "not ");
|
||||
+ free(oattrib);
|
||||
free(host);
|
||||
return result;
|
||||
}
|
||||
diff --git a/servconf.c b/servconf.c
|
||||
index 89b8413e..dd774f46 100644
|
||||
--- a/servconf.c
|
||||
+++ b/servconf.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: servconf.c,v 1.418 2024/09/15 03:09:44 djm Exp $ */
|
||||
+/* $OpenBSD: servconf.c,v 1.419 2024/09/25 01:24:04 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||
* All rights reserved
|
||||
@@ -1033,7 +1033,7 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
|
||||
int line, struct connection_info *ci)
|
||||
{
|
||||
int result = 1, attributes = 0, port;
|
||||
- char *arg, *attrib;
|
||||
+ char *arg, *attrib = NULL, *oattrib;
|
||||
|
||||
if (ci == NULL)
|
||||
debug3("checking syntax for 'Match %s'", full_line);
|
||||
@@ -1047,7 +1047,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
|
||||
ci->laddress ? ci->laddress : "(null)", ci->lport);
|
||||
}
|
||||
|
||||
- while ((attrib = argv_next(acp, avp)) != NULL) {
|
||||
+ while ((oattrib = argv_next(acp, avp)) != NULL) {
|
||||
+ attrib = xstrdup(oattrib);
|
||||
/* Terminate on comment */
|
||||
if (*attrib == '#') {
|
||||
argv_consume(acp); /* mark all arguments consumed */
|
||||
@@ -1062,16 +1063,20 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
|
||||
*arg != '\0' && *arg != '#')) {
|
||||
error("'all' cannot be combined with other "
|
||||
"Match attributes");
|
||||
- return -1;
|
||||
+ result = -1;
|
||||
+ goto out;
|
||||
}
|
||||
if (arg != NULL && *arg == '#')
|
||||
argv_consume(acp); /* consume remaining args */
|
||||
- return 1;
|
||||
+ result = 1;
|
||||
+ goto out;
|
||||
}
|
||||
/* Criterion "invalid-user" also has no argument */
|
||||
if (strcasecmp(attrib, "invalid-user") == 0) {
|
||||
- if (ci == NULL)
|
||||
+ if (ci == NULL) {
|
||||
+ result = 0;
|
||||
continue;
|
||||
+ }
|
||||
if (ci->user_invalid == 0)
|
||||
result = 0;
|
||||
else
|
||||
@@ -1078,11 +1081,26 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
|
||||
debug("matched invalid-user at line %d", line);
|
||||
continue;
|
||||
}
|
||||
+
|
||||
+ /* Keep this list in sync with below */
|
||||
+ if (strprefix(attrib, "user=", 1) != NULL ||
|
||||
+ strprefix(attrib, "group=", 1) != NULL ||
|
||||
+ strprefix(attrib, "host=", 1) != NULL ||
|
||||
+ strprefix(attrib, "address=", 1) != NULL ||
|
||||
+ strprefix(attrib, "localaddress=", 1) != NULL ||
|
||||
+ strprefix(attrib, "localport=", 1) != NULL ||
|
||||
+ strprefix(attrib, "rdomain=", 1) != NULL) {
|
||||
+ arg = strchr(attrib, '=');
|
||||
+ *(arg++) = '\0';
|
||||
+ } else {
|
||||
+ arg = argv_next(acp, avp);
|
||||
+ }
|
||||
+
|
||||
/* All other criteria require an argument */
|
||||
- if ((arg = argv_next(acp, avp)) == NULL ||
|
||||
- *arg == '\0' || *arg == '#') {
|
||||
+ if (arg == NULL || *arg == '\0' || *arg == '#') {
|
||||
error("Missing Match criteria for %s", attrib);
|
||||
- return -1;
|
||||
+ result = -1;
|
||||
+ goto out;
|
||||
}
|
||||
if (strcasecmp(attrib, "user") == 0) {
|
||||
if (ci == NULL || (ci->test && ci->user == NULL)) {
|
||||
@@ -1105,7 +1123,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
|
||||
match_test_missing_fatal("Group", "user");
|
||||
switch (match_cfg_line_group(arg, line, ci->user)) {
|
||||
case -1:
|
||||
- return -1;
|
||||
+ result = -1;
|
||||
+ goto out;
|
||||
case 0:
|
||||
result = 0;
|
||||
}
|
||||
@@ -1141,7 +1160,8 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
|
||||
result = 0;
|
||||
break;
|
||||
case -2:
|
||||
- return -1;
|
||||
+ result = -1;
|
||||
+ goto out;
|
||||
}
|
||||
} else if (strcasecmp(attrib, "localaddress") == 0){
|
||||
if (ci == NULL || (ci->test && ci->laddress == NULL)) {
|
||||
@@ -1166,13 +1186,15 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
|
||||
result = 0;
|
||||
break;
|
||||
case -2:
|
||||
- return -1;
|
||||
+ result = -1;
|
||||
+ goto out;
|
||||
}
|
||||
} else if (strcasecmp(attrib, "localport") == 0) {
|
||||
if ((port = a2port(arg)) == -1) {
|
||||
error("Invalid LocalPort '%s' on Match line",
|
||||
arg);
|
||||
- return -1;
|
||||
+ result = -1;
|
||||
+ goto out;
|
||||
}
|
||||
if (ci == NULL || (ci->test && ci->lport == -1)) {
|
||||
result = 0;
|
||||
@@ -1200,16 +1222,21 @@ match_cfg_line(const char *full_line, int *acp, char ***avp,
|
||||
debug("user %.100s matched 'RDomain %.100s' at "
|
||||
"line %d", ci->rdomain, arg, line);
|
||||
} else {
|
||||
- error("Unsupported Match attribute %s", attrib);
|
||||
- return -1;
|
||||
+ error("Unsupported Match attribute %s", oattrib);
|
||||
+ result = -1;
|
||||
+ goto out;
|
||||
}
|
||||
+ free(attrib);
|
||||
+ attrib = NULL;
|
||||
}
|
||||
if (attributes == 0) {
|
||||
error("One or more attributes required for Match");
|
||||
return -1;
|
||||
}
|
||||
- if (ci != NULL)
|
||||
+ out:
|
||||
+ if (ci != NULL && result != -1)
|
||||
debug3("match %sfound", result ? "" : "not ");
|
||||
+ free(attrib);
|
||||
return result;
|
||||
}
|
||||
|
||||
diff --git a/regress/cfginclude.sh b/regress/cfginclude.sh
|
||||
index d442cdd6..97fd816f 100644
|
||||
--- a/regress/cfginclude.sh
|
||||
+++ b/regress/cfginclude.sh
|
||||
@@ -1,4 +1,4 @@
|
||||
-# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $
|
||||
+# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="config include"
|
||||
@@ -10,7 +10,7 @@ cat > $OBJ/ssh_config.i << _EOF
|
||||
Match host a
|
||||
Hostname aa
|
||||
|
||||
-Match host b # comment
|
||||
+Match host=b # comment
|
||||
Hostname bb
|
||||
Include $OBJ/ssh_config.i.*
|
||||
|
||||
@@ -18,7 +18,7 @@ Match host c
|
||||
Include $OBJ/ssh_config.i.*
|
||||
Hostname cc
|
||||
|
||||
-Match host m
|
||||
+Match host=m !user xxxyfake
|
||||
Include $OBJ/ssh_config.i.* # comment
|
||||
|
||||
Host d
|
||||
@@ -41,7 +41,7 @@ Match host xxxxxx
|
||||
_EOF
|
||||
|
||||
cat > $OBJ/ssh_config.i.1 << _EOF
|
||||
-Match host a
|
||||
+Match host=a
|
||||
Hostname aaa
|
||||
|
||||
Match host b
|
||||
@@ -64,10 +64,10 @@ cat > $OBJ/ssh_config.i.2 << _EOF
|
||||
Match host a
|
||||
Hostname aaaa
|
||||
|
||||
-Match host b
|
||||
+Match host=b !user blahblahfake
|
||||
Hostname bbbb
|
||||
|
||||
-Match host c
|
||||
+Match host=c
|
||||
Hostname cccc
|
||||
|
||||
Host d
|
||||
@@ -142,7 +142,7 @@ trial a aa
|
||||
|
||||
# cleanup
|
||||
rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out
|
||||
-# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $
|
||||
+# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="config include"
|
||||
diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh
|
||||
index 05a66685..2737a5f9 100644
|
||||
--- a/regress/cfgmatch.sh
|
||||
+++ b/regress/cfgmatch.sh
|
||||
@@ -1,4 +1,4 @@
|
||||
-# $OpenBSD: cfgmatch.sh,v 1.13 2021/06/08 06:52:43 djm Exp $
|
||||
+# $OpenBSD: cfgmatch.sh,v 1.14 2024/09/27 01:05:54 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
|
||||
tid="sshd_config match"
|
||||
@@ -26,7 +26,7 @@ start_client()
|
||||
kill $client_pid
|
||||
fatal "timeout waiting for background ssh"
|
||||
fi
|
||||
- done
|
||||
+ done
|
||||
}
|
||||
|
||||
stop_client()
|
||||
@@ -119,40 +119,42 @@ stop_client
|
||||
# requires knowledge of actual group memberships user running the test).
|
||||
params="user:user:u1 host:host:h1 address:addr:1.2.3.4 \
|
||||
localaddress:laddr:5.6.7.8 rdomain:rdomain:rdom1"
|
||||
-cp $OBJ/sshd_proxy_bak $OBJ/sshd_config
|
||||
-echo 'Banner /nomatch' >>$OBJ/sshd_config
|
||||
-for i in $params; do
|
||||
- config=`echo $i | cut -f1 -d:`
|
||||
- criteria=`echo $i | cut -f2 -d:`
|
||||
- value=`echo $i | cut -f3 -d:`
|
||||
- cat >>$OBJ/sshd_config <<EOD
|
||||
- Match $config $value
|
||||
- Banner /$value
|
||||
+for separator in " " "=" ; do
|
||||
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_config
|
||||
+ echo 'Banner /nomatch' >>$OBJ/sshd_config
|
||||
+ for i in $params; do
|
||||
+ config=`echo $i | cut -f1 -d:`
|
||||
+ criteria=`echo $i | cut -f2 -d:`
|
||||
+ value=`echo $i | cut -f3 -d:`
|
||||
+ cat >>$OBJ/sshd_config <<EOD
|
||||
+ Match ${config}${separator}${value}
|
||||
+ Banner /$value
|
||||
EOD
|
||||
-done
|
||||
+ done
|
||||
|
||||
-${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \
|
||||
- fail "validate config for w/out spec"
|
||||
-
|
||||
-# Test matching each criteria.
|
||||
-for i in $params; do
|
||||
- testcriteria=`echo $i | cut -f2 -d:`
|
||||
- expected=/`echo $i | cut -f3 -d:`
|
||||
- spec=""
|
||||
- for j in $params; do
|
||||
- config=`echo $j | cut -f1 -d:`
|
||||
- criteria=`echo $j | cut -f2 -d:`
|
||||
- value=`echo $j | cut -f3 -d:`
|
||||
- if [ "$criteria" = "$testcriteria" ]; then
|
||||
- spec="$criteria=$value,$spec"
|
||||
- else
|
||||
- spec="$criteria=1$value,$spec"
|
||||
+ ${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \
|
||||
+ fail "validate config for w/out spec"
|
||||
+
|
||||
+ # Test matching each criteria.
|
||||
+ for i in $params; do
|
||||
+ testcriteria=`echo $i | cut -f2 -d:`
|
||||
+ expected=/`echo $i | cut -f3 -d:`
|
||||
+ spec=""
|
||||
+ for j in $params; do
|
||||
+ config=`echo $j | cut -f1 -d:`
|
||||
+ criteria=`echo $j | cut -f2 -d:`
|
||||
+ value=`echo $j | cut -f3 -d:`
|
||||
+ if [ "$criteria" = "$testcriteria" ]; then
|
||||
+ spec="$criteria=$value,$spec"
|
||||
+ else
|
||||
+ spec="$criteria=1$value,$spec"
|
||||
+ fi
|
||||
+ done
|
||||
+ trace "test spec $spec"
|
||||
+ result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \
|
||||
+ awk '$1=="banner"{print $2}'`
|
||||
+ if [ "$result" != "$expected" ]; then
|
||||
+ fail "match $config expected $expected got $result"
|
||||
fi
|
||||
done
|
||||
- trace "test spec $spec"
|
||||
- result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \
|
||||
- awk '$1=="banner"{print $2}'`
|
||||
- if [ "$result" != "$expected" ]; then
|
||||
- fail "match $config expected $expected got $result"
|
||||
- fi
|
||||
done
|
||||
diff --git a/regress/servcfginclude.sh b/regress/servcfginclude.sh
|
||||
index 518a703d..f67c3caa 100644
|
||||
--- a/regress/servcfginclude.sh
|
||||
+++ b/regress/servcfginclude.sh
|
||||
@@ -4,14 +4,14 @@ tid="server config include"
|
||||
|
||||
cat > $OBJ/sshd_config.i << _EOF
|
||||
HostKey $OBJ/host.ssh-ed25519
|
||||
-Match host a
|
||||
+Match host=a
|
||||
Banner /aa
|
||||
|
||||
Match host b
|
||||
Banner /bb
|
||||
Include $OBJ/sshd_config.i.* # comment
|
||||
|
||||
-Match host c
|
||||
+Match host=c
|
||||
Include $OBJ/sshd_config.i.* # comment
|
||||
Banner /cc
|
||||
|
||||
@@ -25,7 +25,7 @@ Match Host e
|
||||
Banner /ee
|
||||
Include $OBJ/sshd_config.i.*
|
||||
|
||||
-Match Host f
|
||||
+Match Host=f
|
||||
Include $OBJ/sshd_config.i.*
|
||||
Banner /ff
|
||||
|
||||
@@ -47,13 +47,13 @@ Match host b
|
||||
Match host c
|
||||
Banner /ccc
|
||||
|
||||
-Match Host d
|
||||
+Match Host=d
|
||||
Banner /ddd
|
||||
|
||||
Match Host e
|
||||
Banner /eee
|
||||
|
||||
-Match Host f
|
||||
+Match Host=f
|
||||
Banner /fff
|
||||
_EOF
|
||||
|
||||
@@ -61,13 +61,13 @@ cat > $OBJ/sshd_config.i.2 << _EOF
|
||||
Match host a
|
||||
Banner /aaaa
|
||||
|
||||
-Match host b
|
||||
+Match host=b
|
||||
Banner /bbbb
|
||||
|
||||
Match host c # comment
|
||||
Banner /cccc
|
||||
|
||||
-Match Host d
|
||||
+Match Host=d
|
||||
Banner /dddd
|
||||
|
||||
Match Host e
|
||||
98
SOURCES/openssh-9.9p1-mlkembe.patch
Normal file
98
SOURCES/openssh-9.9p1-mlkembe.patch
Normal file
@ -0,0 +1,98 @@
|
||||
diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c
|
||||
index 679446e9..2b5d3960 100644
|
||||
--- a/kexmlkem768x25519.c
|
||||
+++ b/kexmlkem768x25519.c
|
||||
@@ -1,4 +1,4 @@
|
||||
-/* $OpenBSD: kexmlkem768x25519.c,v 1.1 2024/09/02 12:13:56 djm Exp $ */
|
||||
+/* $OpenBSD: kexmlkem768x25519.c,v 1.2 2024/10/27 02:06:59 djm Exp $ */
|
||||
/*
|
||||
* Copyright (c) 2023 Markus Friedl. All rights reserved.
|
||||
*
|
||||
@@ -34,6 +34,9 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
+#ifdef HAVE_ENDIAN_H
|
||||
+# include <endian.h>
|
||||
+#endif
|
||||
|
||||
#include "sshkey.h"
|
||||
#include "kex.h"
|
||||
diff --git a/libcrux_mlkem768_sha3.h b/libcrux_mlkem768_sha3.h
|
||||
index a82d60e8..b8ac1436 100644
|
||||
--- a/libcrux_mlkem768_sha3.h
|
||||
+++ b/libcrux_mlkem768_sha3.h
|
||||
@@ -1,4 +1,5 @@
|
||||
-/* $OpenBSD: libcrux_mlkem768_sha3.h,v 1.1 2024/09/02 12:13:56 djm Exp $ */
|
||||
+/* $OpenBSD: libcrux_mlkem768_sha3.h,v 1.2 2024/10/27 02:06:01 djm Exp $ */
|
||||
+
|
||||
/* Extracted from libcrux revision 84c5d87b3092c59294345aa269ceefe0eb97cc35 */
|
||||
|
||||
/*
|
||||
@@ -160,18 +161,19 @@ static inline void Eurydice_slice_to_array3(uint8_t *dst_tag, char *dst_ok,
|
||||
// CORE STUFF (conversions, endianness, ...)
|
||||
|
||||
static inline void core_num__u64_9__to_le_bytes(uint64_t v, uint8_t buf[8]) {
|
||||
+ v = htole64(v);
|
||||
memcpy(buf, &v, sizeof(v));
|
||||
}
|
||||
static inline uint64_t core_num__u64_9__from_le_bytes(uint8_t buf[8]) {
|
||||
uint64_t v;
|
||||
memcpy(&v, buf, sizeof(v));
|
||||
- return v;
|
||||
+ return le64toh(v);
|
||||
}
|
||||
|
||||
static inline uint32_t core_num__u32_8__from_le_bytes(uint8_t buf[4]) {
|
||||
uint32_t v;
|
||||
memcpy(&v, buf, sizeof(v));
|
||||
- return v;
|
||||
+ return le32toh(v);
|
||||
}
|
||||
|
||||
static inline uint32_t core_num__u8_6__count_ones(uint8_t x0) {
|
||||
diff --git a/mlkem768.sh b/mlkem768.sh
|
||||
index 2fdc2831..3d12b2ed 100644
|
||||
--- a/mlkem768.sh
|
||||
+++ b/mlkem768.sh
|
||||
@@ -1,9 +1,10 @@
|
||||
#!/bin/sh
|
||||
-# $OpenBSD: mlkem768.sh,v 1.2 2024/09/04 05:11:33 djm Exp $
|
||||
+# $OpenBSD: mlkem768.sh,v 1.3 2024/10/27 02:06:01 djm Exp $
|
||||
# Placed in the Public Domain.
|
||||
#
|
||||
|
||||
-WANT_LIBCRUX_REVISION="origin/main"
|
||||
+#WANT_LIBCRUX_REVISION="origin/main"
|
||||
+WANT_LIBCRUX_REVISION="84c5d87b3092c59294345aa269ceefe0eb97cc35"
|
||||
|
||||
FILES="
|
||||
libcrux/libcrux-ml-kem/cg/eurydice_glue.h
|
||||
@@ -47,6 +48,7 @@ echo '#define KRML_NOINLINE __attribute__((noinline, unused))'
|
||||
echo '#define KRML_HOST_EPRINTF(...)'
|
||||
echo '#define KRML_HOST_EXIT(x) fatal_f("internal error")'
|
||||
echo
|
||||
+
|
||||
for i in $FILES; do
|
||||
echo "/* from $i */"
|
||||
# Changes to all files:
|
||||
@@ -56,11 +58,16 @@ for i in $FILES; do
|
||||
-e 's/[ ]*$//' \
|
||||
$i | \
|
||||
case "$i" in
|
||||
- # XXX per-file handling goes here.
|
||||
+ */libcrux-ml-kem/cg/eurydice_glue.h)
|
||||
+ # Replace endian functions with versions that work.
|
||||
+ perl -0777 -pe 's/(static inline void core_num__u64_9__to_le_bytes.*\n)([^}]*\n)/\1 v = htole64(v);\n\2/' |
|
||||
+ perl -0777 -pe 's/(static inline uint64_t core_num__u64_9__from_le_bytes.*?)return v;/\1return le64toh(v);/s' |
|
||||
+ perl -0777 -pe 's/(static inline uint32_t core_num__u32_8__from_le_bytes.*?)return v;/\1return le32toh(v);/s'
|
||||
+ ;;
|
||||
# Default: pass through.
|
||||
*)
|
||||
- cat
|
||||
- ;;
|
||||
+ cat
|
||||
+ ;;
|
||||
esac
|
||||
echo
|
||||
done
|
||||
12
SOURCES/openssh-9.9p1-non-supported-keys-err-msg.patch
Normal file
12
SOURCES/openssh-9.9p1-non-supported-keys-err-msg.patch
Normal file
@ -0,0 +1,12 @@
|
||||
diff --color -ruNp a/sshkey.c b/sshkey.c
|
||||
--- a/sshkey.c 2025-04-29 11:20:59.484832762 +0200
|
||||
+++ b/sshkey.c 2025-04-29 11:28:32.349323029 +0200
|
||||
@@ -3599,6 +3599,8 @@ translate_libcrypto_error(unsigned long
|
||||
}
|
||||
case ERR_LIB_ASN1:
|
||||
return SSH_ERR_INVALID_FORMAT;
|
||||
+ case ERR_LIB_OSSL_DECODER:
|
||||
+ return SSH_ERR_INVALID_FORMAT;
|
||||
}
|
||||
return SSH_ERR_LIBCRYPTO_ERROR;
|
||||
}
|
||||
385
SOURCES/openssh-9.9p1-openssl-mlkem.patch
Normal file
385
SOURCES/openssh-9.9p1-openssl-mlkem.patch
Normal file
@ -0,0 +1,385 @@
|
||||
diff --git a/kex-names.c b/kex-names.c
|
||||
index ec840c1f..c0d3be11 100644
|
||||
--- a/kex-names.c
|
||||
+++ b/kex-names.c
|
||||
@@ -90,6 +90,19 @@ static const struct kexalg kexalgs[] = {
|
||||
{ NULL, 0, -1, -1},
|
||||
};
|
||||
|
||||
+static int is_mlkem768_available()
|
||||
+{
|
||||
+ static int is_fetched = -1;
|
||||
+
|
||||
+ if (is_fetched == -1) {
|
||||
+ EVP_KEM *mlkem768 = EVP_KEM_fetch(NULL, "mlkem768", NULL);
|
||||
+ is_fetched = mlkem768 != NULL ? 1 : 0;
|
||||
+ EVP_KEM_free(mlkem768);
|
||||
+ }
|
||||
+
|
||||
+ return is_fetched;
|
||||
+}
|
||||
+
|
||||
static char *
|
||||
kex_alg_list_internal(char sep, const struct kexalg *algs)
|
||||
{
|
||||
@@ -98,6 +111,9 @@ kex_alg_list_internal(char sep, const struct kexalg *algs)
|
||||
const struct kexalg *k;
|
||||
|
||||
for (k = algs; k->name != NULL; k++) {
|
||||
+ if (strcmp(k->name, KEX_MLKEM768X25519_SHA256) == 0
|
||||
+ && !is_mlkem768_available())
|
||||
+ continue;
|
||||
if (ret != NULL)
|
||||
ret[rlen++] = sep;
|
||||
nlen = strlen(k->name);
|
||||
@@ -117,6 +133,10 @@ kex_alg_by_name(const char *name)
|
||||
{
|
||||
const struct kexalg *k;
|
||||
|
||||
+ if (strcmp(name, KEX_MLKEM768X25519_SHA256) == 0
|
||||
+ && !is_mlkem768_available())
|
||||
+ return NULL;
|
||||
+
|
||||
for (k = kexalgs; k->name != NULL; k++) {
|
||||
if (strcmp(k->name, name) == 0)
|
||||
return k;
|
||||
diff --git a/kexmlkem768x25519.c b/kexmlkem768x25519.c
|
||||
index 2b5d3960..670049dc 100644
|
||||
--- a/kexmlkem768x25519.c
|
||||
+++ b/kexmlkem768x25519.c
|
||||
@@ -48,10 +48,127 @@
|
||||
#ifdef USE_MLKEM768X25519
|
||||
|
||||
#include "libcrux_mlkem768_sha3.h"
|
||||
+#include <openssl/err.h>
|
||||
+#include <openssl/evp.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+static int
|
||||
+mlkem768_keypair_gen(unsigned char *pubkeybuf, unsigned char *privkeybuf)
|
||||
+{
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ EVP_PKEY *pkey = NULL;
|
||||
+ int ret = SSH_ERR_INTERNAL_ERROR;
|
||||
+ size_t pubkey_size = crypto_kem_mlkem768_PUBLICKEYBYTES, privkey_size = crypto_kem_mlkem768_SECRETKEYBYTES;
|
||||
+
|
||||
+ ctx = EVP_PKEY_CTX_new_from_name(NULL, "mlkem768", NULL);
|
||||
+ if (ctx == NULL) {
|
||||
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (EVP_PKEY_keygen_init(ctx) <= 0
|
||||
+ || EVP_PKEY_keygen(ctx, &pkey) <= 0) {
|
||||
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (EVP_PKEY_get_raw_public_key(pkey, pubkeybuf, &pubkey_size) <= 0
|
||||
+ || EVP_PKEY_get_raw_private_key(pkey, privkeybuf, &privkey_size) <= 0) {
|
||||
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ if (privkey_size != crypto_kem_mlkem768_SECRETKEYBYTES
|
||||
+ || pubkey_size != crypto_kem_mlkem768_PUBLICKEYBYTES) {
|
||||
+ ret = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ ret = 0;
|
||||
+
|
||||
+ err:
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ if (ret == SSH_ERR_LIBCRYPTO_ERROR)
|
||||
+ ERR_print_errors_fp(stderr);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mlkem768_encap_secret(const u_char *pubkeybuf, u_char *secret, u_char *out)
|
||||
+{
|
||||
+ EVP_PKEY *pkey = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ int r = SSH_ERR_INTERNAL_ERROR;
|
||||
+ size_t outlen = crypto_kem_mlkem768_CIPHERTEXTBYTES,
|
||||
+ secretlen = crypto_kem_mlkem768_BYTES;
|
||||
+
|
||||
+ pkey = EVP_PKEY_new_raw_public_key_ex(NULL, "mlkem768", NULL,
|
||||
+ pubkeybuf, crypto_kem_mlkem768_PUBLICKEYBYTES);
|
||||
+ if (pkey == NULL) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
|
||||
+ if (ctx == NULL
|
||||
+ || EVP_PKEY_encapsulate_init(ctx, NULL) <= 0
|
||||
+ || EVP_PKEY_encapsulate(ctx, out, &outlen, secret, &secretlen) <= 0
|
||||
+ || secretlen != crypto_kem_mlkem768_BYTES
|
||||
+ || outlen != crypto_kem_mlkem768_CIPHERTEXTBYTES) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ r = 0;
|
||||
+
|
||||
+ err:
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+ if (r == SSH_ERR_LIBCRYPTO_ERROR)
|
||||
+ ERR_print_errors_fp(stderr);
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mlkem768_decap_secret(const u_char *privkeybuf, const u_char *wrapped, u_char *secret)
|
||||
+{
|
||||
+ EVP_PKEY *pkey = NULL;
|
||||
+ EVP_PKEY_CTX *ctx = NULL;
|
||||
+ int r = SSH_ERR_INTERNAL_ERROR;
|
||||
+ size_t wrappedlen = crypto_kem_mlkem768_CIPHERTEXTBYTES,
|
||||
+ secretlen = crypto_kem_mlkem768_BYTES;
|
||||
+
|
||||
+ pkey = EVP_PKEY_new_raw_private_key_ex(NULL, "mlkem768", NULL,
|
||||
+ privkeybuf, crypto_kem_mlkem768_SECRETKEYBYTES);
|
||||
+ if (pkey == NULL) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto err;
|
||||
+ }
|
||||
+
|
||||
+ ctx = EVP_PKEY_CTX_new_from_pkey(NULL, pkey, NULL);
|
||||
+ if (ctx == NULL
|
||||
+ || EVP_PKEY_decapsulate_init(ctx, NULL) <= 0
|
||||
+ || EVP_PKEY_decapsulate(ctx, secret, &secretlen, wrapped, wrappedlen) <= 0
|
||||
+ || secretlen != crypto_kem_mlkem768_BYTES) {
|
||||
+ r = SSH_ERR_LIBCRYPTO_ERROR;
|
||||
+ goto err;
|
||||
+ }
|
||||
+ r = 0;
|
||||
+
|
||||
+ err:
|
||||
+ EVP_PKEY_free(pkey);
|
||||
+ EVP_PKEY_CTX_free(ctx);
|
||||
+
|
||||
+ if (r == SSH_ERR_LIBCRYPTO_ERROR)
|
||||
+ ERR_print_errors_fp(stderr);
|
||||
+
|
||||
+ return r;
|
||||
+}
|
||||
|
||||
int
|
||||
kex_kem_mlkem768x25519_keypair(struct kex *kex)
|
||||
{
|
||||
+#if 0
|
||||
struct sshbuf *buf = NULL;
|
||||
u_char rnd[LIBCRUX_ML_KEM_KEY_PAIR_PRNG_LEN], *cp = NULL;
|
||||
size_t need;
|
||||
@@ -86,6 +203,36 @@ kex_kem_mlkem768x25519_keypair(struct kex *kex)
|
||||
explicit_bzero(rnd, sizeof(rnd));
|
||||
sshbuf_free(buf);
|
||||
return r;
|
||||
+#else
|
||||
+ struct sshbuf *buf = NULL;
|
||||
+ u_char *cp = NULL;
|
||||
+ size_t need;
|
||||
+ int r = SSH_ERR_INTERNAL_ERROR;
|
||||
+
|
||||
+ if ((buf = sshbuf_new()) == NULL)
|
||||
+ return SSH_ERR_ALLOC_FAIL;
|
||||
+ need = crypto_kem_mlkem768_PUBLICKEYBYTES + CURVE25519_SIZE;
|
||||
+ if ((r = sshbuf_reserve(buf, need, &cp)) != 0)
|
||||
+ goto out;
|
||||
+ if ((r = mlkem768_keypair_gen(cp, kex->mlkem768_client_key)) != 0)
|
||||
+ goto out;
|
||||
+#ifdef DEBUG_KEXECDH
|
||||
+ dump_digest("client public key mlkem768:", cp,
|
||||
+ crypto_kem_mlkem768_PUBLICKEYBYTES);
|
||||
+#endif
|
||||
+ cp += crypto_kem_mlkem768_PUBLICKEYBYTES;
|
||||
+ kexc25519_keygen(kex->c25519_client_key, cp);
|
||||
+#ifdef DEBUG_KEXECDH
|
||||
+ dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
|
||||
+#endif
|
||||
+ /* success */
|
||||
+ r = 0;
|
||||
+ kex->client_pub = buf;
|
||||
+ buf = NULL;
|
||||
+ out:
|
||||
+ sshbuf_free(buf);
|
||||
+ return r;
|
||||
+#endif
|
||||
}
|
||||
|
||||
int
|
||||
@@ -93,6 +240,7 @@ kex_kem_mlkem768x25519_enc(struct kex *kex,
|
||||
const struct sshbuf *client_blob, struct sshbuf **server_blobp,
|
||||
struct sshbuf **shared_secretp)
|
||||
{
|
||||
+#if 0
|
||||
struct sshbuf *server_blob = NULL;
|
||||
struct sshbuf *buf = NULL;
|
||||
const u_char *client_pub;
|
||||
@@ -185,12 +333,97 @@ kex_kem_mlkem768x25519_enc(struct kex *kex,
|
||||
sshbuf_free(server_blob);
|
||||
sshbuf_free(buf);
|
||||
return r;
|
||||
+#else
|
||||
+ struct sshbuf *server_blob = NULL;
|
||||
+ struct sshbuf *buf = NULL;
|
||||
+ const u_char *client_pub;
|
||||
+ u_char server_pub[CURVE25519_SIZE], server_key[CURVE25519_SIZE];
|
||||
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
|
||||
+ size_t need;
|
||||
+ int r = SSH_ERR_INTERNAL_ERROR;
|
||||
+ struct libcrux_mlkem768_enc_result enc; /* FIXME */
|
||||
+
|
||||
+ *server_blobp = NULL;
|
||||
+ *shared_secretp = NULL;
|
||||
+
|
||||
+ /* client_blob contains both KEM and ECDH client pubkeys */
|
||||
+ need = crypto_kem_mlkem768_PUBLICKEYBYTES + CURVE25519_SIZE;
|
||||
+ if (sshbuf_len(client_blob) != need) {
|
||||
+ r = SSH_ERR_SIGNATURE_INVALID;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ client_pub = sshbuf_ptr(client_blob);
|
||||
+#ifdef DEBUG_KEXECDH
|
||||
+ dump_digest("client public key mlkem768:", client_pub,
|
||||
+ crypto_kem_mlkem768_PUBLICKEYBYTES);
|
||||
+ dump_digest("client public key 25519:",
|
||||
+ client_pub + crypto_kem_mlkem768_PUBLICKEYBYTES,
|
||||
+ CURVE25519_SIZE);
|
||||
+#endif
|
||||
+
|
||||
+ /* allocate buffer for concatenation of KEM key and ECDH shared key */
|
||||
+ /* the buffer will be hashed and the result is the shared secret */
|
||||
+ if ((buf = sshbuf_new()) == NULL) {
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ /* allocate space for encrypted KEM key and ECDH pub key */
|
||||
+ if ((server_blob = sshbuf_new()) == NULL) {
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ if (mlkem768_encap_secret(client_pub, enc.snd, enc.fst.value) != 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ /* generate ECDH key pair, store server pubkey after ciphertext */
|
||||
+ kexc25519_keygen(server_key, server_pub);
|
||||
+ if ((r = sshbuf_put(buf, enc.snd, sizeof(enc.snd))) != 0 ||
|
||||
+ (r = sshbuf_put(server_blob, enc.fst.value, sizeof(enc.fst.value))) != 0 ||
|
||||
+ (r = sshbuf_put(server_blob, server_pub, sizeof(server_pub))) != 0)
|
||||
+ goto out;
|
||||
+ /* append ECDH shared key */
|
||||
+ client_pub += crypto_kem_mlkem768_PUBLICKEYBYTES;
|
||||
+ if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 1)) < 0)
|
||||
+ goto out;
|
||||
+ if ((r = ssh_digest_buffer(kex->hash_alg, buf, hash, sizeof(hash))) != 0)
|
||||
+ goto out;
|
||||
+#ifdef DEBUG_KEXECDH
|
||||
+ dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
|
||||
+ dump_digest("server cipher text:",
|
||||
+ enc.fst.value, sizeof(enc.fst.value));
|
||||
+ dump_digest("server kem key:", enc.snd, sizeof(enc.snd));
|
||||
+ dump_digest("concatenation of KEM key and ECDH shared key:",
|
||||
+ sshbuf_ptr(buf), sshbuf_len(buf));
|
||||
+#endif
|
||||
+ /* string-encoded hash is resulting shared secret */
|
||||
+ sshbuf_reset(buf);
|
||||
+ if ((r = sshbuf_put_string(buf, hash,
|
||||
+ ssh_digest_bytes(kex->hash_alg))) != 0)
|
||||
+ goto out;
|
||||
+#ifdef DEBUG_KEXECDH
|
||||
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
|
||||
+#endif
|
||||
+ /* success */
|
||||
+ r = 0;
|
||||
+ *server_blobp = server_blob;
|
||||
+ *shared_secretp = buf;
|
||||
+ server_blob = NULL;
|
||||
+ buf = NULL;
|
||||
+ out:
|
||||
+ explicit_bzero(hash, sizeof(hash));
|
||||
+ explicit_bzero(server_key, sizeof(server_key));
|
||||
+ explicit_bzero(&enc, sizeof(enc));
|
||||
+ sshbuf_free(server_blob);
|
||||
+ sshbuf_free(buf);
|
||||
+ return r;
|
||||
+#endif
|
||||
}
|
||||
|
||||
int
|
||||
kex_kem_mlkem768x25519_dec(struct kex *kex,
|
||||
const struct sshbuf *server_blob, struct sshbuf **shared_secretp)
|
||||
{
|
||||
+#if 0
|
||||
struct sshbuf *buf = NULL;
|
||||
u_char mlkem_key[crypto_kem_mlkem768_BYTES];
|
||||
const u_char *ciphertext, *server_pub;
|
||||
@@ -258,6 +491,64 @@ kex_kem_mlkem768x25519_dec(struct kex *kex,
|
||||
explicit_bzero(mlkem_key, sizeof(mlkem_key));
|
||||
sshbuf_free(buf);
|
||||
return r;
|
||||
+#else
|
||||
+ struct sshbuf *buf = NULL;
|
||||
+ const u_char *ciphertext, *server_pub;
|
||||
+ u_char hash[SSH_DIGEST_MAX_LENGTH];
|
||||
+ u_char decap[crypto_kem_mlkem768_BYTES];
|
||||
+ size_t need;
|
||||
+ int r;
|
||||
+
|
||||
+ *shared_secretp = NULL;
|
||||
+
|
||||
+ need = crypto_kem_mlkem768_CIPHERTEXTBYTES + CURVE25519_SIZE;
|
||||
+ if (sshbuf_len(server_blob) != need) {
|
||||
+ r = SSH_ERR_SIGNATURE_INVALID;
|
||||
+ goto out;
|
||||
+ }
|
||||
+ ciphertext = sshbuf_ptr(server_blob);
|
||||
+ server_pub = ciphertext + crypto_kem_mlkem768_CIPHERTEXTBYTES;
|
||||
+ /* hash concatenation of KEM key and ECDH shared key */
|
||||
+ if ((buf = sshbuf_new()) == NULL) {
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+#ifdef DEBUG_KEXECDH
|
||||
+ dump_digest("server cipher text:", ciphertext, crypto_kem_mlkem768_CIPHERTEXTBYTES);
|
||||
+ dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
|
||||
+#endif
|
||||
+ if ((r = mlkem768_decap_secret(kex->mlkem768_client_key, ciphertext, decap)) != 0)
|
||||
+ goto out;
|
||||
+ if ((r = sshbuf_put(buf, decap, sizeof(decap))) != 0)
|
||||
+ goto out;
|
||||
+ if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
|
||||
+ buf, 1)) < 0)
|
||||
+ goto out;
|
||||
+ if ((r = ssh_digest_buffer(kex->hash_alg, buf,
|
||||
+ hash, sizeof(hash))) != 0)
|
||||
+ goto out;
|
||||
+#ifdef DEBUG_KEXECDH
|
||||
+ dump_digest("client kem key:", decap, sizeof(decap));
|
||||
+ dump_digest("concatenation of KEM key and ECDH shared key:",
|
||||
+ sshbuf_ptr(buf), sshbuf_len(buf));
|
||||
+#endif
|
||||
+ sshbuf_reset(buf);
|
||||
+ if ((r = sshbuf_put_string(buf, hash,
|
||||
+ ssh_digest_bytes(kex->hash_alg))) != 0)
|
||||
+ goto out;
|
||||
+#ifdef DEBUG_KEXECDH
|
||||
+ dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
|
||||
+#endif
|
||||
+ /* success */
|
||||
+ r = 0;
|
||||
+ *shared_secretp = buf;
|
||||
+ buf = NULL;
|
||||
+ out:
|
||||
+ explicit_bzero(hash, sizeof(hash));
|
||||
+ explicit_bzero(decap, sizeof(decap));
|
||||
+ sshbuf_free(buf);
|
||||
+ return r;
|
||||
+#endif
|
||||
}
|
||||
#else /* USE_MLKEM768X25519 */
|
||||
int
|
||||
59
SOURCES/openssh-9.9p1-reject-cntrl-chars-in-username.patch
Normal file
59
SOURCES/openssh-9.9p1-reject-cntrl-chars-in-username.patch
Normal file
@ -0,0 +1,59 @@
|
||||
diff --color -ruNp a/ssh.c b/ssh.c
|
||||
--- a/ssh.c 2025-12-03 15:22:36.754555231 +0100
|
||||
+++ b/ssh.c 2025-12-03 16:12:16.715320349 +0100
|
||||
@@ -662,6 +662,8 @@ valid_ruser(const char *s)
|
||||
if (*s == '-')
|
||||
return 0;
|
||||
for (i = 0; s[i] != 0; i++) {
|
||||
+ if (iscntrl((u_char)s[i]))
|
||||
+ return 0;
|
||||
if (strchr("'`\";&<>|(){}", s[i]) != NULL)
|
||||
return 0;
|
||||
/* Disallow '-' after whitespace */
|
||||
@@ -683,6 +685,7 @@ main(int ac, char **av)
|
||||
struct ssh *ssh = NULL;
|
||||
int i, r, opt, exit_status, use_syslog, direct, timeout_ms;
|
||||
int was_addr, config_test = 0, opt_terminated = 0, want_final_pass = 0;
|
||||
+ int user_on_commandline = 0;
|
||||
char *p, *cp, *line, *argv0, *logfile;
|
||||
char cname[NI_MAXHOST], thishost[NI_MAXHOST];
|
||||
struct stat st;
|
||||
@@ -1039,8 +1042,10 @@ main(int ac, char **av)
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
- if (options.user == NULL)
|
||||
+ if (options.user == NULL) {
|
||||
options.user = optarg;
|
||||
+ user_on_commandline = 1;
|
||||
+ }
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
@@ -1143,6 +1148,7 @@ main(int ac, char **av)
|
||||
if (options.user == NULL) {
|
||||
options.user = tuser;
|
||||
tuser = NULL;
|
||||
+ user_on_commandline = 1;
|
||||
}
|
||||
free(tuser);
|
||||
if (options.port == -1 && tport != -1)
|
||||
@@ -1157,6 +1163,7 @@ main(int ac, char **av)
|
||||
if (options.user == NULL) {
|
||||
options.user = p;
|
||||
p = NULL;
|
||||
+ user_on_commandline = 1;
|
||||
}
|
||||
*cp++ = '\0';
|
||||
host = xstrdup(cp);
|
||||
@@ -1459,6 +1466,10 @@ main(int ac, char **av)
|
||||
cinfo->locuser = xstrdup(pw->pw_name);
|
||||
cinfo->jmphost = xstrdup(options.jump_host == NULL ?
|
||||
"" : options.jump_host);
|
||||
+
|
||||
+ if (user_on_commandline && !valid_ruser(options.user))
|
||||
+ fatal("remote username contains invalid characters");
|
||||
+
|
||||
cinfo->conn_hash_hex = ssh_connection_hash(cinfo->thishost,
|
||||
cinfo->remhost, cinfo->portstr, cinfo->remuser, cinfo->jmphost);
|
||||
|
||||
24
SOURCES/openssh-9.9p1-reject-null-char-in-url-string.patch
Normal file
24
SOURCES/openssh-9.9p1-reject-null-char-in-url-string.patch
Normal file
@ -0,0 +1,24 @@
|
||||
diff --color -ruNp a/misc.c b/misc.c
|
||||
--- a/misc.c 2025-12-03 16:19:11.255135131 +0100
|
||||
+++ b/misc.c 2025-12-03 16:21:53.769590836 +0100
|
||||
@@ -998,7 +998,7 @@ urldecode(const char *src)
|
||||
size_t srclen;
|
||||
|
||||
if ((srclen = strlen(src)) >= SIZE_MAX)
|
||||
- fatal_f("input too large");
|
||||
+ return NULL;
|
||||
ret = xmalloc(srclen + 1);
|
||||
for (dst = ret; *src != '\0'; src++) {
|
||||
switch (*src) {
|
||||
@@ -1006,9 +1006,10 @@ urldecode(const char *src)
|
||||
*dst++ = ' ';
|
||||
break;
|
||||
case '%':
|
||||
+ /* note: don't allow \0 characters */
|
||||
if (!isxdigit((unsigned char)src[1]) ||
|
||||
!isxdigit((unsigned char)src[2]) ||
|
||||
- (ch = hexchar(src + 1)) == -1) {
|
||||
+ (ch = hexchar(src + 1)) == -1 || ch == 0) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
437
SOURCES/openssh-9.9p1-scp-traversing.patch
Normal file
437
SOURCES/openssh-9.9p1-scp-traversing.patch
Normal file
@ -0,0 +1,437 @@
|
||||
diff --color -ruNp a/regress/scp3.sh b/regress/scp3.sh
|
||||
--- a/regress/scp3.sh 2024-09-20 00:20:48.000000000 +0200
|
||||
+++ b/regress/scp3.sh 2025-10-29 16:00:59.815068193 +0100
|
||||
@@ -6,6 +6,12 @@ tid="scp3"
|
||||
COPY2=${OBJ}/copy2
|
||||
DIR=${COPY}.dd
|
||||
DIR2=${COPY}.dd2
|
||||
+DIFFOPT="-rN"
|
||||
+
|
||||
+# Figure out if diff does not understand "-N"
|
||||
+if ! diff -N ${SRC}/scp.sh ${SRC}/scp.sh 2>/dev/null; then
|
||||
+ DIFFOPT="-r"
|
||||
+fi
|
||||
|
||||
maybe_add_scp_path_to_sshd
|
||||
|
||||
@@ -63,6 +69,15 @@ for mode in scp sftp ; do
|
||||
echo b > ${COPY2}
|
||||
$SCP $scpopts -3 hostA:${DATA} hostA:${COPY} hostB:${COPY2}
|
||||
cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target"
|
||||
+
|
||||
+ # scp /blah/.. is only supported via the sftp protocol.
|
||||
+ # Original protocol scp just refuses it.
|
||||
+ test $mode != sftp && continue
|
||||
+ verbose "$tag: recursive .."
|
||||
+ forest
|
||||
+ $SCP $scpopts -r hostA:${DIR}/subdir/.. hostB:${DIR2} || \
|
||||
+ fail "copy failed"
|
||||
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
|
||||
done
|
||||
|
||||
scpclean
|
||||
diff --color -ruNp a/regress/scp.sh b/regress/scp.sh
|
||||
--- a/regress/scp.sh 2024-09-20 00:20:48.000000000 +0200
|
||||
+++ b/regress/scp.sh 2025-10-29 16:00:59.810765653 +0100
|
||||
@@ -199,6 +199,19 @@ for mode in scp sftp ; do
|
||||
echo b > ${COPY2}
|
||||
$SCP $scpopts ${DATA} ${COPY} ${COPY2}
|
||||
cmp ${COPY} ${COPY2} >/dev/null && fail "corrupt target"
|
||||
+
|
||||
+ # scp /blah/.. is only supported via the sftp protocol.
|
||||
+ # Original protocol scp just refuses it.
|
||||
+ test $mode != sftp && continue
|
||||
+ verbose "$tag: recursive local .. to remote dir"
|
||||
+ forest
|
||||
+ $SCP $scpopts -r ${DIR}/subdir/.. somehost:${DIR2} || fail "copy failed"
|
||||
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
|
||||
+
|
||||
+ verbose "$tag: recursive remote .. to local dir"
|
||||
+ forest
|
||||
+ $SCP $scpopts -r somehost:${DIR}/subdir/.. ${DIR2} || fail "copy failed"
|
||||
+ diff ${DIFFOPT} ${DIR} ${DIR2} || fail "corrupted copy"
|
||||
done
|
||||
|
||||
scpclean
|
||||
diff --color -ruNp a/regress/sftp-cmds.sh b/regress/sftp-cmds.sh
|
||||
--- a/regress/sftp-cmds.sh 2024-09-20 00:20:48.000000000 +0200
|
||||
+++ b/regress/sftp-cmds.sh 2025-10-29 16:00:59.813392901 +0100
|
||||
@@ -7,6 +7,12 @@
|
||||
|
||||
tid="sftp commands"
|
||||
|
||||
+DIFFOPT="-rN"
|
||||
+# Figure out if diff does not understand "-N"
|
||||
+if ! diff -N ${SRC}/sftp-cmds.sh ${SRC}/sftp-cmds.sh 2>/dev/null; then
|
||||
+ DIFFOPT="-r"
|
||||
+fi
|
||||
+
|
||||
# test that these files are readable!
|
||||
for i in `(cd /bin;echo l*)`
|
||||
do
|
||||
@@ -24,207 +30,246 @@ SPACECOPY_ARG="${COPY}\ this\ has\ space
|
||||
# File with glob metacharacters
|
||||
GLOBMETACOPY="${COPY} [metachar].txt"
|
||||
|
||||
+sftpserver() {
|
||||
+ ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1
|
||||
+}
|
||||
+
|
||||
+sftpserver_with_stdout() {
|
||||
+ ${SFTP} -D ${SFTPSERVER} 2>&1
|
||||
+}
|
||||
+
|
||||
+forest() {
|
||||
+ rm -rf ${COPY}.dd/*
|
||||
+ rm -rf ${COPY}.dd2
|
||||
+ mkdir -p ${COPY}.dd/a ${COPY}.dd/b ${COPY}.dd/c ${COPY}.dd/a/d
|
||||
+ echo 'A' > ${COPY}.dd/a/A
|
||||
+ echo 'B' > ${COPY}.dd/a/B
|
||||
+ echo 'C' > ${COPY}.dd/a/C
|
||||
+ echo 'D' > ${COPY}.dd/a/D
|
||||
+}
|
||||
+
|
||||
rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
|
||||
mkdir ${COPY}.dd
|
||||
|
||||
verbose "$tid: lls"
|
||||
-printf "lcd ${OBJ}\nlls\n" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
|
||||
+printf "lcd ${OBJ}\nlls\n" | sftpserver_with_stdout | \
|
||||
grep copy.dd >/dev/null || fail "lls failed"
|
||||
|
||||
verbose "$tid: lls w/path"
|
||||
-echo "lls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
|
||||
+echo "lls ${OBJ}" | sftpserver_with_stdout | \
|
||||
grep copy.dd >/dev/null || fail "lls w/path failed"
|
||||
|
||||
verbose "$tid: ls"
|
||||
-echo "ls ${OBJ}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "ls failed"
|
||||
+echo "ls ${OBJ}" | sftpserver || fail "ls failed"
|
||||
# XXX always successful
|
||||
|
||||
verbose "$tid: shell"
|
||||
-echo "!echo hi there" | ${SFTP} -D ${SFTPSERVER} 2>&1 | \
|
||||
+echo "!echo hi there" | sftpserver_with_stdout | \
|
||||
egrep '^hi there$' >/dev/null || fail "shell failed"
|
||||
|
||||
verbose "$tid: pwd"
|
||||
-echo "pwd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "pwd failed"
|
||||
+echo "pwd" | sftpserver || fail "pwd failed"
|
||||
# XXX always successful
|
||||
|
||||
verbose "$tid: lpwd"
|
||||
-echo "lpwd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "lpwd failed"
|
||||
+echo "lpwd" | sftpserver || fail "lpwd failed"
|
||||
# XXX always successful
|
||||
|
||||
verbose "$tid: quit"
|
||||
-echo "quit" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "quit failed"
|
||||
+echo "quit" | sftpserver || fail "quit failed"
|
||||
# XXX always successful
|
||||
|
||||
verbose "$tid: help"
|
||||
-echo "help" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "help failed"
|
||||
+echo "help" | sftpserver || fail "help failed"
|
||||
# XXX always successful
|
||||
|
||||
rm -f ${COPY}
|
||||
verbose "$tid: get"
|
||||
-echo "get $DATA $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "get failed"
|
||||
+echo "get $DATA $COPY" | sftpserver || fail "get failed"
|
||||
cmp $DATA ${COPY} || fail "corrupted copy after get"
|
||||
|
||||
rm -f ${COPY}
|
||||
verbose "$tid: get quoted"
|
||||
-echo "get \"$DATA\" $COPY" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "get failed"
|
||||
+echo "get \"$DATA\" $COPY" | sftpserver || fail "get failed"
|
||||
cmp $DATA ${COPY} || fail "corrupted copy after get"
|
||||
|
||||
rm -f ${QUOTECOPY}
|
||||
cp $DATA ${QUOTECOPY}
|
||||
verbose "$tid: get filename with quotes"
|
||||
-echo "get \"$QUOTECOPY_ARG\" ${COPY}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "get failed"
|
||||
+echo "get \"$QUOTECOPY_ARG\" ${COPY}" | sftpserver || fail "get failed"
|
||||
cmp ${COPY} ${QUOTECOPY} || fail "corrupted copy after get with quotes"
|
||||
rm -f ${QUOTECOPY} ${COPY}
|
||||
|
||||
rm -f "$SPACECOPY" ${COPY}
|
||||
cp $DATA "$SPACECOPY"
|
||||
verbose "$tid: get filename with spaces"
|
||||
-echo "get ${SPACECOPY_ARG} ${COPY}" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "get failed"
|
||||
+echo "get ${SPACECOPY_ARG} ${COPY}" | sftpserver || fail "get failed"
|
||||
cmp ${COPY} "$SPACECOPY" || fail "corrupted copy after get with spaces"
|
||||
|
||||
rm -f "$GLOBMETACOPY" ${COPY}
|
||||
cp $DATA "$GLOBMETACOPY"
|
||||
verbose "$tid: get filename with glob metacharacters"
|
||||
-echo "get \"${GLOBMETACOPY}\" ${COPY}" | \
|
||||
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "get failed"
|
||||
+echo "get \"${GLOBMETACOPY}\" ${COPY}" | sftpserver || fail "get failed"
|
||||
cmp ${COPY} "$GLOBMETACOPY" || \
|
||||
fail "corrupted copy after get with glob metacharacters"
|
||||
|
||||
-rm -f ${COPY}.dd/*
|
||||
+rm -rf ${COPY}.dd/*
|
||||
verbose "$tid: get to directory"
|
||||
-echo "get $DATA ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "get failed"
|
||||
+echo "get $DATA ${COPY}.dd" | sftpserver || fail "get failed"
|
||||
cmp $DATA ${COPY}.dd/${DATANAME} || fail "corrupted copy after get"
|
||||
|
||||
-rm -f ${COPY}.dd/*
|
||||
+rm -rf ${COPY}.dd/*
|
||||
verbose "$tid: glob get to directory"
|
||||
-echo "get /bin/l* ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "get failed"
|
||||
+echo "get /bin/l* ${COPY}.dd" | sftpserver || fail "get failed"
|
||||
for x in $GLOBFILES; do
|
||||
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after get"
|
||||
done
|
||||
|
||||
-rm -f ${COPY}.dd/*
|
||||
+rm -rf ${COPY}.dd/*
|
||||
verbose "$tid: get to local dir"
|
||||
-printf "lcd ${COPY}.dd\nget $DATA\n" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "get failed"
|
||||
+printf "lcd ${COPY}.dd\nget $DATA\n" | sftpserver || fail "get failed"
|
||||
cmp $DATA ${COPY}.dd/${DATANAME} || fail "corrupted copy after get"
|
||||
|
||||
-rm -f ${COPY}.dd/*
|
||||
+rm -rf ${COPY}.dd/*
|
||||
verbose "$tid: glob get to local dir"
|
||||
-printf "lcd ${COPY}.dd\nget /bin/l*\n" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "get failed"
|
||||
+printf "lcd ${COPY}.dd\nget /bin/l*\n" | sftpserver || fail "get failed"
|
||||
for x in $GLOBFILES; do
|
||||
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after get"
|
||||
done
|
||||
|
||||
+forest
|
||||
+verbose "$tid: get recursive absolute"
|
||||
+echo "get -R ${COPY}.dd ${COPY}.dd2" | sftpserver || fail "get failed"
|
||||
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
|
||||
+
|
||||
+forest
|
||||
+verbose "$tid: get recursive relative src"
|
||||
+printf "cd ${COPY}.dd\n get -R . ${COPY}.dd2\n" | sftpserver || \
|
||||
+ fail "get failed"
|
||||
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
|
||||
+
|
||||
+forest
|
||||
+verbose "$tid: get relative .."
|
||||
+printf "cd ${COPY}.dd/b\n get -R .. ${COPY}.dd2\n" | sftpserver || \
|
||||
+ fail "get failed"
|
||||
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
|
||||
+
|
||||
+forest
|
||||
+mkdir ${COPY}.dd2
|
||||
+verbose "$tid: get recursive relative .."
|
||||
+printf "cd ${COPY}.dd/b\n lcd ${COPY}.dd2\n get -R ..\n" | sftpserver || \
|
||||
+ fail "get failed"
|
||||
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
|
||||
+
|
||||
rm -f ${COPY}
|
||||
verbose "$tid: put"
|
||||
-echo "put $DATA $COPY" | \
|
||||
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
|
||||
+echo "put $DATA $COPY" | sftpserver || fail "put failed"
|
||||
cmp $DATA ${COPY} || fail "corrupted copy after put"
|
||||
|
||||
rm -f ${QUOTECOPY}
|
||||
verbose "$tid: put filename with quotes"
|
||||
-echo "put $DATA \"$QUOTECOPY_ARG\"" | \
|
||||
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
|
||||
+echo "put $DATA \"$QUOTECOPY_ARG\"" | sftpserver || fail "put failed"
|
||||
cmp $DATA ${QUOTECOPY} || fail "corrupted copy after put with quotes"
|
||||
|
||||
rm -f "$SPACECOPY"
|
||||
verbose "$tid: put filename with spaces"
|
||||
-echo "put $DATA ${SPACECOPY_ARG}" | \
|
||||
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "put failed"
|
||||
+echo "put $DATA ${SPACECOPY_ARG}" | sftpserver || fail "put failed"
|
||||
cmp $DATA "$SPACECOPY" || fail "corrupted copy after put with spaces"
|
||||
|
||||
-rm -f ${COPY}.dd/*
|
||||
+rm -rf ${COPY}.dd/*
|
||||
verbose "$tid: put to directory"
|
||||
-echo "put $DATA ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "put failed"
|
||||
+echo "put $DATA ${COPY}.dd" | sftpserver || fail "put failed"
|
||||
cmp $DATA ${COPY}.dd/${DATANAME} || fail "corrupted copy after put"
|
||||
|
||||
-rm -f ${COPY}.dd/*
|
||||
+rm -rf ${COPY}.dd/*
|
||||
verbose "$tid: glob put to directory"
|
||||
-echo "put /bin/l? ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "put failed"
|
||||
+echo "put /bin/l? ${COPY}.dd" | sftpserver || fail "put failed"
|
||||
for x in $GLOBFILES; do
|
||||
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after put"
|
||||
done
|
||||
|
||||
-rm -f ${COPY}.dd/*
|
||||
+rm -rf ${COPY}.dd/*
|
||||
verbose "$tid: put to local dir"
|
||||
-printf "cd ${COPY}.dd\nput $DATA\n" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "put failed"
|
||||
+printf "cd ${COPY}.dd\nput $DATA\n" | sftpserver || fail "put failed"
|
||||
cmp $DATA ${COPY}.dd/${DATANAME} || fail "corrupted copy after put"
|
||||
|
||||
-rm -f ${COPY}.dd/*
|
||||
+rm -rf ${COPY}.dd/*
|
||||
verbose "$tid: glob put to local dir"
|
||||
-printf "cd ${COPY}.dd\nput /bin/l*\n" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "put failed"
|
||||
+printf "cd ${COPY}.dd\nput /bin/l*\n" | sftpserver || fail "put failed"
|
||||
for x in $GLOBFILES; do
|
||||
cmp /bin/$x ${COPY}.dd/$x || fail "corrupted copy after put"
|
||||
done
|
||||
|
||||
+forest
|
||||
+verbose "$tid: put recursive absolute"
|
||||
+echo "put -R ${COPY}.dd ${COPY}.dd2" | sftpserver || fail "put failed"
|
||||
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
|
||||
+
|
||||
+forest
|
||||
+verbose "$tid: put recursive relative src"
|
||||
+printf "lcd ${COPY}.dd\n put -R . ${COPY}.dd2\n" | sftpserver || \
|
||||
+ fail "put failed"
|
||||
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
|
||||
+
|
||||
+forest
|
||||
+verbose "$tid: put recursive .."
|
||||
+printf "lcd ${COPY}.dd/b\n put -R .. ${COPY}.dd2\n" | sftpserver || \
|
||||
+ fail "put failed"
|
||||
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
|
||||
+
|
||||
+forest
|
||||
+mkdir ${COPY}.dd2
|
||||
+verbose "$tid: put recursive .. relative"
|
||||
+printf "lcd ${COPY}.dd/b\n cd ${COPY}.dd2\n put -R ..\n" | sftpserver || \
|
||||
+ fail "put failed"
|
||||
+diff ${DIFFOPT} ${COPY}.dd ${COPY}.dd2 || fail "corrupted copy"
|
||||
+
|
||||
verbose "$tid: rename"
|
||||
-echo "rename $COPY ${COPY}.1" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "rename failed"
|
||||
+echo "rename $COPY ${COPY}.1" | sftpserver || fail "rename failed"
|
||||
test -f ${COPY}.1 || fail "missing file after rename"
|
||||
cmp $DATA ${COPY}.1 >/dev/null 2>&1 || fail "corrupted copy after rename"
|
||||
|
||||
verbose "$tid: rename directory"
|
||||
-echo "rename ${COPY}.dd ${COPY}.dd2" | \
|
||||
- ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || \
|
||||
+rm -rf ${COPY}.dd2
|
||||
+echo "rename ${COPY}.dd ${COPY}.dd2" | sftpserver || \
|
||||
fail "rename directory failed"
|
||||
test -d ${COPY}.dd && fail "oldname exists after rename directory"
|
||||
test -d ${COPY}.dd2 || fail "missing newname after rename directory"
|
||||
|
||||
verbose "$tid: ln"
|
||||
-echo "ln ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln failed"
|
||||
+echo "ln ${COPY}.1 ${COPY}.2" | sftpserver || fail "ln failed"
|
||||
test -f ${COPY}.2 || fail "missing file after ln"
|
||||
cmp ${COPY}.1 ${COPY}.2 || fail "created file is not equal after ln"
|
||||
|
||||
verbose "$tid: ln -s"
|
||||
rm -f ${COPY}.2
|
||||
-echo "ln -s ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "ln -s failed"
|
||||
+echo "ln -s ${COPY}.1 ${COPY}.2" | sftpserver || fail "ln -s failed"
|
||||
test -h ${COPY}.2 || fail "missing file after ln -s"
|
||||
|
||||
verbose "$tid: cp"
|
||||
rm -f ${COPY}.2
|
||||
-echo "cp ${COPY}.1 ${COPY}.2" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 || fail "cp failed"
|
||||
+echo "cp ${COPY}.1 ${COPY}.2" | sftpserver || fail "cp failed"
|
||||
cmp ${COPY}.1 ${COPY}.2 || fail "created file is not equal after cp"
|
||||
|
||||
verbose "$tid: mkdir"
|
||||
-echo "mkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "mkdir failed"
|
||||
+echo "mkdir ${COPY}.dd" | sftpserver || fail "mkdir failed"
|
||||
test -d ${COPY}.dd || fail "missing directory after mkdir"
|
||||
|
||||
# XXX do more here
|
||||
verbose "$tid: chdir"
|
||||
-echo "chdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "chdir failed"
|
||||
+echo "chdir ${COPY}.dd" | sftpserver || fail "chdir failed"
|
||||
|
||||
verbose "$tid: rmdir"
|
||||
-echo "rmdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "rmdir failed"
|
||||
+echo "rmdir ${COPY}.dd" | sftpserver || fail "rmdir failed"
|
||||
test -d ${COPY}.1 && fail "present directory after rmdir"
|
||||
|
||||
verbose "$tid: lmkdir"
|
||||
-echo "lmkdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "lmkdir failed"
|
||||
+echo "lmkdir ${COPY}.dd" | sftpserver || fail "lmkdir failed"
|
||||
test -d ${COPY}.dd || fail "missing directory after lmkdir"
|
||||
|
||||
# XXX do more here
|
||||
verbose "$tid: lchdir"
|
||||
-echo "lchdir ${COPY}.dd" | ${SFTP} -D ${SFTPSERVER} >/dev/null 2>&1 \
|
||||
- || fail "lchdir failed"
|
||||
+echo "lchdir ${COPY}.dd" | sftpserver || fail "lchdir failed"
|
||||
|
||||
rm -rf ${COPY} ${COPY}.1 ${COPY}.2 ${COPY}.dd ${COPY}.dd2
|
||||
rm -rf ${QUOTECOPY} "$SPACECOPY" "$GLOBMETACOPY"
|
||||
diff --color -ruNp a/scp.c b/scp.c
|
||||
--- a/scp.c 2025-10-29 15:49:51.795813258 +0100
|
||||
+++ b/scp.c 2025-10-29 16:00:59.817393000 +0100
|
||||
@@ -1362,6 +1362,10 @@ source_sftp(int argc, char *src, char *t
|
||||
if ((filename = basename(src)) == NULL)
|
||||
fatal("basename \"%s\": %s", src, strerror(errno));
|
||||
|
||||
+ /* Special handling for source of '..' */
|
||||
+ if (strcmp(filename, "..") == 0)
|
||||
+ filename = "."; /* Upload to dest, not dest/.. */
|
||||
+
|
||||
/*
|
||||
* No need to glob here - the local shell already took care of
|
||||
* the expansions
|
||||
@@ -1635,6 +1639,10 @@ sink_sftp(int argc, char *dst, const cha
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ /* Special handling for destination of '..' */
|
||||
+ if (strcmp(filename, "..") == 0)
|
||||
+ filename = "."; /* Download to dest, not dest/.. */
|
||||
+
|
||||
if (dst_is_dir)
|
||||
abs_dst = sftp_path_append(dst, filename);
|
||||
else
|
||||
diff --color -ruNp a/sftp.c b/sftp.c
|
||||
--- a/sftp.c 2025-10-29 15:49:51.796907436 +0100
|
||||
+++ b/sftp.c 2025-10-29 16:00:59.819803948 +0100
|
||||
@@ -687,6 +687,10 @@ process_get(struct sftp_conn *conn, cons
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ /* Special handling for dest of '..' */
|
||||
+ if (strcmp(filename, "..") == 0)
|
||||
+ filename = "."; /* Download to dest, not dest/.. */
|
||||
+
|
||||
if (g.gl_matchc == 1 && dst) {
|
||||
if (local_is_dir(dst)) {
|
||||
abs_dst = sftp_path_append(dst, filename);
|
||||
@@ -781,6 +785,9 @@ process_put(struct sftp_conn *conn, cons
|
||||
err = -1;
|
||||
goto out;
|
||||
}
|
||||
+ /* Special handling for source of '..' */
|
||||
+ if (strcmp(filename, "..") == 0)
|
||||
+ filename = "."; /* Upload to dest, not dest/.. */
|
||||
|
||||
free(abs_dst);
|
||||
abs_dst = NULL;
|
||||
@ -0,0 +1,450 @@
|
||||
From 5d5a66e96ad03132f65371070f4fa475f10207d9 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
Date: Mon, 10 Jun 2024 23:00:03 +0300
|
||||
Subject: [PATCH] support authentication indicators in GSSAPI
|
||||
|
||||
RFC 6680 defines a set of GSSAPI extensions to handle attributes
|
||||
associated with the GSSAPI names. MIT Kerberos and FreeIPA use
|
||||
name attributes to add information about pre-authentication methods used
|
||||
to acquire the initial Kerberos ticket. The attribute 'auth-indicators'
|
||||
may contain list of strings that KDC has associated with the ticket
|
||||
issuance process.
|
||||
|
||||
Use authentication indicators to authorise or deny access to SSH server.
|
||||
GSSAPIIndicators setting allows to specify a list of possible indicators
|
||||
that a Kerberos ticket presented must or must not contain. More details
|
||||
on the syntax are provided in sshd_config(5) man page.
|
||||
|
||||
Fixes: https://bugzilla.mindrot.org/show_bug.cgi?id=2696
|
||||
|
||||
Signed-off-by: Alexander Bokovoy <abokovoy@redhat.com>
|
||||
---
|
||||
configure.ac | 1 +
|
||||
gss-serv-krb5.c | 64 +++++++++++++++++++++++++++---
|
||||
gss-serv.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++-
|
||||
servconf.c | 15 ++++++-
|
||||
servconf.h | 2 +
|
||||
ssh-gss.h | 7 ++++
|
||||
sshd_config.5 | 44 +++++++++++++++++++++
|
||||
7 files changed, 228 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index d92a85809..2cbe20bf3 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -5004,6 +5004,7 @@ AC_ARG_WITH([kerberos5],
|
||||
AC_CHECK_HEADERS([gssapi.h gssapi/gssapi.h])
|
||||
AC_CHECK_HEADERS([gssapi_krb5.h gssapi/gssapi_krb5.h])
|
||||
AC_CHECK_HEADERS([gssapi_generic.h gssapi/gssapi_generic.h])
|
||||
+ AC_CHECK_HEADERS([gssapi_ext.h gssapi/gssapi_ext.h])
|
||||
|
||||
AC_SEARCH_LIBS([k_hasafs], [kafs], [AC_DEFINE([USE_AFS], [1],
|
||||
[Define this if you want to use libkafs' AFS support])])
|
||||
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
|
||||
index 03188d9b3..2c786ef14 100644
|
||||
--- a/gss-serv-krb5.c
|
||||
+++ b/gss-serv-krb5.c
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "log.h"
|
||||
#include "misc.h"
|
||||
#include "servconf.h"
|
||||
+#include "match.h"
|
||||
|
||||
#include "ssh-gss.h"
|
||||
|
||||
@@ -87,6 +88,32 @@ ssh_gssapi_krb5_init(void)
|
||||
return 1;
|
||||
}
|
||||
|
||||
+/* Check if any of the indicators in the Kerberos ticket match
|
||||
+ * one of indicators in the list of allowed/denied rules.
|
||||
+ * In case of the match, apply the decision from the rule.
|
||||
+ * In case of no indicator from the ticket matching the rule, deny
|
||||
+ */
|
||||
+
|
||||
+static int
|
||||
+ssh_gssapi_check_indicators(ssh_gssapi_client *client, int *matched)
|
||||
+{
|
||||
+ int ret;
|
||||
+ u_int i;
|
||||
+
|
||||
+ /* Check indicators */
|
||||
+ for (i = 0; client->indicators[i] != NULL; i++) {
|
||||
+ ret = match_pattern_list(client->indicators[i],
|
||||
+ options.gss_indicators, 1);
|
||||
+ /* negative or positive match */
|
||||
+ if (ret != 0) {
|
||||
+ *matched = i;
|
||||
+ return ret;
|
||||
+ }
|
||||
+ }
|
||||
+ /* No rule matched */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* Check if this user is OK to login. This only works with krb5 - other
|
||||
* GSSAPI mechanisms will need their own.
|
||||
* Returns true if the user is OK to log in, otherwise returns 0
|
||||
@@ -193,7 +220,7 @@ static int
|
||||
ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
|
||||
{
|
||||
krb5_principal princ;
|
||||
- int retval;
|
||||
+ int retval, matched;
|
||||
const char *errmsg;
|
||||
int k5login_exists;
|
||||
|
||||
@@ -216,17 +243,42 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name)
|
||||
if (k5login_exists &&
|
||||
ssh_krb5_kuserok(krb_context, princ, name, k5login_exists)) {
|
||||
retval = 1;
|
||||
- logit("Authorized to %s, krb5 principal %s (krb5_kuserok)",
|
||||
- name, (char *)client->displayname.value);
|
||||
+ errmsg = "krb5_kuserok";
|
||||
} else if (ssh_gssapi_krb5_cmdok(princ, client->exportedname.value,
|
||||
name, k5login_exists)) {
|
||||
retval = 1;
|
||||
- logit("Authorized to %s, krb5 principal %s "
|
||||
- "(ssh_gssapi_krb5_cmdok)",
|
||||
- name, (char *)client->displayname.value);
|
||||
+ errmsg = "ssh_gssapi_krb5_cmdok";
|
||||
} else
|
||||
retval = 0;
|
||||
|
||||
+ if ((retval == 1) && (options.gss_indicators != NULL)) {
|
||||
+ /* At this point the configuration enforces presence of indicators
|
||||
+ * so we drop the authorization result again */
|
||||
+ retval = 0;
|
||||
+ if (client->indicators) {
|
||||
+ matched = -1;
|
||||
+ retval = ssh_gssapi_check_indicators(client, &matched);
|
||||
+ if (retval != 0) {
|
||||
+ retval = (retval == 1);
|
||||
+ logit("Ticket contains indicator %s, "
|
||||
+ "krb5 principal %s is %s",
|
||||
+ client->indicators[matched],
|
||||
+ (char *)client->displayname.value,
|
||||
+ retval ? "allowed" : "denied");
|
||||
+ goto cont;
|
||||
+ }
|
||||
+ }
|
||||
+ if (retval == 0) {
|
||||
+ logit("GSSAPI authentication indicators enforced "
|
||||
+ "but not matched. krb5 principal %s denied",
|
||||
+ (char *)client->displayname.value);
|
||||
+ }
|
||||
+ }
|
||||
+cont:
|
||||
+ if (retval == 1) {
|
||||
+ logit("Authorized to %s, krb5 principal %s (%s)",
|
||||
+ name, (char *)client->displayname.value, errmsg);
|
||||
+ }
|
||||
krb5_free_principal(krb_context, princ);
|
||||
return retval;
|
||||
}
|
||||
diff --git a/gss-serv.c b/gss-serv.c
|
||||
index 9d5435eda..5c0491cf1 100644
|
||||
--- a/gss-serv.c
|
||||
+++ b/gss-serv.c
|
||||
@@ -54,7 +54,7 @@ extern ServerOptions options;
|
||||
|
||||
static ssh_gssapi_client gssapi_client =
|
||||
{ GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL,
|
||||
- GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0};
|
||||
+ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0, NULL};
|
||||
|
||||
ssh_gssapi_mech gssapi_null_mech =
|
||||
{ NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL};
|
||||
@@ -296,6 +296,92 @@ ssh_gssapi_parse_ename(Gssctxt *ctx, gss_buffer_t ename, gss_buffer_t name)
|
||||
return GSS_S_COMPLETE;
|
||||
}
|
||||
|
||||
+
|
||||
+/* Extract authentication indicators from the Kerberos ticket. Authentication
|
||||
+ * indicators are GSSAPI name attributes for the name "auth-indicators".
|
||||
+ * Multiple indicators might be present in the ticket.
|
||||
+ * Each indicator is a utf8 string. */
|
||||
+
|
||||
+#define AUTH_INDICATORS_TAG "auth-indicators"
|
||||
+
|
||||
+/* Privileged (called from accept_secure_ctx) */
|
||||
+static OM_uint32
|
||||
+ssh_gssapi_getindicators(Gssctxt *ctx, gss_name_t gss_name, ssh_gssapi_client *client)
|
||||
+{
|
||||
+ gss_buffer_set_t attrs = GSS_C_NO_BUFFER_SET;
|
||||
+ gss_buffer_desc value = GSS_C_EMPTY_BUFFER;
|
||||
+ gss_buffer_desc display_value = GSS_C_EMPTY_BUFFER;
|
||||
+ int is_mechname, authenticated, complete, more;
|
||||
+ size_t count, i;
|
||||
+
|
||||
+ ctx->major = gss_inquire_name(&ctx->minor, gss_name,
|
||||
+ &is_mechname, NULL, &attrs);
|
||||
+ if (ctx->major != GSS_S_COMPLETE) {
|
||||
+ return (ctx->major);
|
||||
+ }
|
||||
+
|
||||
+ if (attrs == GSS_C_NO_BUFFER_SET) {
|
||||
+ /* No indicators in the ticket */
|
||||
+ return (0);
|
||||
+ }
|
||||
+
|
||||
+ count = 0;
|
||||
+ for (i = 0; i < attrs->count; i++) {
|
||||
+ /* skip anything but auth-indicators */
|
||||
+ if (((sizeof(AUTH_INDICATORS_TAG) - 1) != attrs->elements[i].length) ||
|
||||
+ strncmp(AUTH_INDICATORS_TAG,
|
||||
+ attrs->elements[i].value,
|
||||
+ sizeof(AUTH_INDICATORS_TAG) - 1) != 0)
|
||||
+ continue;
|
||||
+ count++;
|
||||
+ }
|
||||
+
|
||||
+ if (count == 0) {
|
||||
+ /* No auth-indicators in the ticket */
|
||||
+ (void) gss_release_buffer_set(&ctx->minor, &attrs);
|
||||
+ return (0);
|
||||
+ }
|
||||
+
|
||||
+ client->indicators = recallocarray(NULL, 0, count + 1, sizeof(char*));
|
||||
+ count = 0;
|
||||
+ for (i = 0; i < attrs->count; i++) {
|
||||
+ authenticated = 0;
|
||||
+ complete = 0;
|
||||
+ more = -1;
|
||||
+ /* skip anything but auth-indicators */
|
||||
+ if (((sizeof(AUTH_INDICATORS_TAG) - 1) != attrs->elements[i].length) ||
|
||||
+ strncmp(AUTH_INDICATORS_TAG,
|
||||
+ attrs->elements[i].value,
|
||||
+ sizeof(AUTH_INDICATORS_TAG) - 1) != 0)
|
||||
+ continue;
|
||||
+ /* retrieve all indicators */
|
||||
+ while (more != 0) {
|
||||
+ value.value = NULL;
|
||||
+ display_value.value = NULL;
|
||||
+ ctx->major = gss_get_name_attribute(&ctx->minor, gss_name,
|
||||
+ &attrs->elements[i], &authenticated,
|
||||
+ &complete, &value, &display_value, &more);
|
||||
+ if (ctx->major != GSS_S_COMPLETE) {
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((value.value != NULL) && authenticated) {
|
||||
+ client->indicators[count] = xmalloc(value.length + 1);
|
||||
+ memcpy(client->indicators[count], value.value, value.length);
|
||||
+ client->indicators[count][value.length] = '\0';
|
||||
+ count++;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ (void) gss_release_buffer(&ctx->minor, &value);
|
||||
+ (void) gss_release_buffer(&ctx->minor, &display_value);
|
||||
+ (void) gss_release_buffer_set(&ctx->minor, &attrs);
|
||||
+ return (ctx->major);
|
||||
+}
|
||||
+
|
||||
+
|
||||
/* Extract the client details from a given context. This can only reliably
|
||||
* be called once for a context */
|
||||
|
||||
@@ -385,6 +471,12 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
|
||||
}
|
||||
|
||||
gss_release_buffer(&ctx->minor, &ename);
|
||||
+ /* Retrieve authentication indicators, if they exist */
|
||||
+ if ((ctx->major = ssh_gssapi_getindicators(ctx,
|
||||
+ ctx->client, client))) {
|
||||
+ ssh_gssapi_error(ctx);
|
||||
+ return (ctx->major);
|
||||
+ }
|
||||
|
||||
/* We can't copy this structure, so we just move the pointer to it */
|
||||
client->creds = ctx->client_creds;
|
||||
@@ -447,6 +539,7 @@ int
|
||||
ssh_gssapi_userok(char *user, struct passwd *pw, int kex)
|
||||
{
|
||||
OM_uint32 lmin;
|
||||
+ size_t i;
|
||||
|
||||
(void) kex; /* used in privilege separation */
|
||||
|
||||
@@ -465,6 +558,14 @@ ssh_gssapi_userok(char *user, struct passwd *pw, int kex)
|
||||
gss_release_buffer(&lmin, &gssapi_client.displayname);
|
||||
gss_release_buffer(&lmin, &gssapi_client.exportedname);
|
||||
gss_release_cred(&lmin, &gssapi_client.creds);
|
||||
+
|
||||
+ if (gssapi_client.indicators != NULL) {
|
||||
+ for(i = 0; gssapi_client.indicators[i] != NULL; i++) {
|
||||
+ free(gssapi_client.indicators[i]);
|
||||
+ }
|
||||
+ free(gssapi_client.indicators);
|
||||
+ }
|
||||
+
|
||||
explicit_bzero(&gssapi_client,
|
||||
sizeof(ssh_gssapi_client));
|
||||
return 0;
|
||||
diff --git a/servconf.c b/servconf.c
|
||||
index e7e4ad046..aab653244 100644
|
||||
--- a/servconf.c
|
||||
+++ b/servconf.c
|
||||
@@ -147,6 +147,7 @@ initialize_server_options(ServerOptions *options)
|
||||
options->gss_strict_acceptor = -1;
|
||||
options->gss_store_rekey = -1;
|
||||
options->gss_kex_algorithms = NULL;
|
||||
+ options->gss_indicators = NULL;
|
||||
options->use_kuserok = -1;
|
||||
options->enable_k5users = -1;
|
||||
options->password_authentication = -1;
|
||||
@@ -598,7 +599,7 @@ typedef enum {
|
||||
sPerSourcePenalties, sPerSourcePenaltyExemptList,
|
||||
sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
|
||||
sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor,
|
||||
- sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey,
|
||||
+ sGssKeyEx, sGssIndicators, sGssKexAlgorithms, sGssStoreRekey,
|
||||
sAcceptEnv, sSetEnv, sPermitTunnel,
|
||||
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
|
||||
sUsePrivilegeSeparation, sAllowAgentForwarding,
|
||||
@@ -694,6 +695,7 @@ static struct {
|
||||
{ "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
|
||||
{ "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
|
||||
{ "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL },
|
||||
+ { "gssapiindicators", sGssIndicators, SSHCFG_ALL },
|
||||
#else
|
||||
{ "gssapiauthentication", sUnsupported, SSHCFG_ALL },
|
||||
{ "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
|
||||
@@ -703,6 +705,7 @@ static struct {
|
||||
{ "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
|
||||
{ "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
|
||||
{ "gssapienablek5users", sUnsupported, SSHCFG_ALL },
|
||||
+ { "gssapiindicators", sUnsupported, SSHCFG_ALL },
|
||||
#endif
|
||||
{ "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
|
||||
{ "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
|
||||
@@ -1730,6 +1733,15 @@ process_server_config_line_depth(ServerOptions *options, char *line,
|
||||
options->gss_kex_algorithms = xstrdup(arg);
|
||||
break;
|
||||
|
||||
+ case sGssIndicators:
|
||||
+ arg = argv_next(&ac, &av);
|
||||
+ if (!arg || *arg == '\0')
|
||||
+ fatal("%s line %d: %s missing argument.",
|
||||
+ filename, linenum, keyword);
|
||||
+ if (options->gss_indicators == NULL)
|
||||
+ options->gss_indicators = xstrdup(arg);
|
||||
+ break;
|
||||
+
|
||||
case sPasswordAuthentication:
|
||||
intptr = &options->password_authentication;
|
||||
goto parse_flag;
|
||||
@@ -3351,6 +3363,7 @@ dump_config(ServerOptions *o)
|
||||
dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
|
||||
dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
|
||||
dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms);
|
||||
+ dump_cfg_string(sGssIndicators, o->gss_indicators);
|
||||
#endif
|
||||
dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
|
||||
dump_cfg_fmtint(sKbdInteractiveAuthentication,
|
||||
diff --git a/servconf.h b/servconf.h
|
||||
index 7c7e5d434..7c41df417 100644
|
||||
--- a/servconf.h
|
||||
+++ b/servconf.h
|
||||
@@ -181,6 +181,7 @@ typedef struct {
|
||||
char **allow_groups;
|
||||
u_int num_deny_groups;
|
||||
char **deny_groups;
|
||||
+ char *gss_indicators;
|
||||
|
||||
u_int num_subsystems;
|
||||
char **subsystem_name;
|
||||
@@ -310,6 +311,7 @@ TAILQ_HEAD(include_list, include_item);
|
||||
M_CP_STROPT(routing_domain); \
|
||||
M_CP_STROPT(permit_user_env_allowlist); \
|
||||
M_CP_STROPT(pam_service_name); \
|
||||
+ M_CP_STROPT(gss_indicators); \
|
||||
M_CP_STRARRAYOPT(authorized_keys_files, num_authkeys_files); \
|
||||
M_CP_STRARRAYOPT(allow_users, num_allow_users); \
|
||||
M_CP_STRARRAYOPT(deny_users, num_deny_users); \
|
||||
diff --git a/ssh-gss.h b/ssh-gss.h
|
||||
index a894e23c9..59cf46d47 100644
|
||||
--- a/ssh-gss.h
|
||||
+++ b/ssh-gss.h
|
||||
@@ -34,6 +34,12 @@
|
||||
#include <gssapi/gssapi.h>
|
||||
#endif
|
||||
|
||||
+#ifdef HAVE_GSSAPI_EXT_H
|
||||
+#include <gssapi_ext.h>
|
||||
+#elif defined(HAVE_GSSAPI_GSSAPI_EXT_H)
|
||||
+#include <gssapi/gssapi_ext.h>
|
||||
+#endif
|
||||
+
|
||||
#ifdef KRB5
|
||||
# ifndef HEIMDAL
|
||||
# ifdef HAVE_GSSAPI_GENERIC_H
|
||||
@@ -107,6 +113,7 @@ typedef struct {
|
||||
ssh_gssapi_ccache store;
|
||||
int used;
|
||||
int updated;
|
||||
+ char **indicators; /* auth indicators */
|
||||
} ssh_gssapi_client;
|
||||
|
||||
typedef struct ssh_gssapi_mech_struct {
|
||||
diff --git a/sshd_config.5 b/sshd_config.5
|
||||
index 583a01cdb..90ab87edd 100644
|
||||
--- a/sshd_config.5
|
||||
+++ b/sshd_config.5
|
||||
@@ -785,6 +785,50 @@ gss-nistp256-sha256-
|
||||
gss-curve25519-sha256-
|
||||
.Ed
|
||||
This option only applies to connections using GSSAPI.
|
||||
+.It Cm GSSAPIIndicators
|
||||
+Specifies whether to accept or deny GSSAPI authenticated access if Kerberos
|
||||
+mechanism is used and Kerberos ticket contains a particular set of
|
||||
+authentication indicators. The values can be specified as a comma-separated list
|
||||
+.Cm [!]name1,[!]name2,... .
|
||||
+When indicator's name is prefixed with !, the authentication indicator 'name'
|
||||
+will deny access to the system. Otherwise, one of non-negated authentication
|
||||
+indicators must be present in the Kerberos ticket to allow access. If
|
||||
+.Cm GSSAPIIndicators
|
||||
+is defined, a Kerberos ticket that has indicators but does not match the
|
||||
+policy will get denial. If at least one indicator is configured, whether for
|
||||
+access or denial, tickets without authentication indicators will be explicitly
|
||||
+rejected.
|
||||
+.Pp
|
||||
+By default systems using MIT Kerberos 1.17 or later will not assign any
|
||||
+indicators. SPAKE and PKINIT methods add authentication indicators
|
||||
+to all successful authentications. The SPAKE pre-authentication method is
|
||||
+preferred over an encrypted timestamp pre-authentication when passwords used to
|
||||
+authenticate user principals. Kerberos KDCs built with Heimdal Kerberos
|
||||
+(including Samba AD DC built with Heimdal) do not add authentication
|
||||
+indicators. However, OpenSSH built against Heimdal Kerberos library is able to
|
||||
+inquire authentication indicators and thus can be used to check for their presence.
|
||||
+.Pp
|
||||
+Indicator name is case-sensitive and depends on the configuration of a
|
||||
+particular Kerberos deployment. Indicators available in MIT Kerberos and
|
||||
+FreeIPA environments:
|
||||
+.Pp
|
||||
+.Bl -tag -width XXXX -offset indent -compact
|
||||
+.It Cm hardened
|
||||
+SPAKE or encrypted timestamp pre-authentication mechanisms in MIT Kerberos and FreeIPA
|
||||
+.It Cm pkinit
|
||||
+smartcard or PKCS11 token-based pre-authentication in MIT Kerberos and FreeIPA
|
||||
+.It Cm radius
|
||||
+pre-authentication based on a RADIUS server in MIT Kerberos and FreeIPA
|
||||
+.It Cm otp
|
||||
+TOTP/HOTP-based two-factor pre-authentication in FreeIPA
|
||||
+.It Cm idp
|
||||
+OAuth2-based pre-authentication in FreeIPA using an external identity provider
|
||||
+and device authorization grant flow
|
||||
+.It Cm passkey
|
||||
+FIDO2-based pre-authentication in FreeIPA, using FIDO2 USB and NFC tokens
|
||||
+.El
|
||||
+.Pp
|
||||
+The default is to not use GSSAPI authentication indicators for access decisions.
|
||||
.It Cm HostbasedAcceptedAlgorithms
|
||||
The default is handled system-wide by
|
||||
.Xr crypto-policies 7 .
|
||||
--
|
||||
2.49.0
|
||||
|
||||
16
SOURCES/openssh-9.9p1.tar.gz.asc
Normal file
16
SOURCES/openssh-9.9p1.tar.gz.asc
Normal file
@ -0,0 +1,16 @@
|
||||
-----BEGIN PGP SIGNATURE-----
|
||||
|
||||
iQIzBAABCgAdFiEEcWi5g4FaXu9ZpK39Kj9BTnNgYLoFAmbspccACgkQKj9BTnNg
|
||||
YLppxRAAv7eU/Xd2w9MX9vWQdhugiPByEcKg7KuKXUUs9xJGy+HbLqPqUCvn1UW6
|
||||
qodKoSAdeBuSB7AjzuIQ1lTVX7C67OmZaVPRq25ar5b+Wq4SSlv23KMRq0b4EVyw
|
||||
pOW6R9tsxqYBwYaiXQ50APcYL8SpepnGU+b/iR15f7q3SU2XMVVtkVb149UdLOqK
|
||||
smfurbDGwUKFb2Q009MUfEV/d9zq31tdSjphvkqAXCcmxc8siuOYWYcByuysie+m
|
||||
NpaOpee0047L5JIxNSLsa2yZrJZhClP8LbTCH1Vfwr7l0KE5nvL2qAtPKI2XxGQC
|
||||
3jXrDLzp10RFxV8sCym+QlY9pZyzGj9d3G7vCHtxWGQ1Y0Qt+xs18OeBpjiehRhl
|
||||
WM3Y+cjoN35jBaGhOoHdh3ePZQdTUyZ16aSv0h/cUHOohiM7i/4XW+dQtkqsJsw4
|
||||
a81O0E64WrL8ho3Ju9mwcVZ9A0aEaftJsmJPDB+qYBjF/i7xcnH32LginzP5pel7
|
||||
/W0aS2C1ZNo3QKHezI6IA9MyENMZiAMy2ybvfmN0HgLBaBY1plJ8a5GvMwJc+Qwh
|
||||
iCHLCQ6Qgf/1hh+F6liTXnhtedtFHneJdyqvd7XOoardDEipZjxcnGa4HthbDFU+
|
||||
8XdHKnWWhn4BLA+y7KB3ZGURniQK+qibwkF6J63CuMU+LmG+bvQ=
|
||||
=Ukrb
|
||||
-----END PGP SIGNATURE-----
|
||||
@ -11,13 +11,96 @@ index e2efdf06..0d0f6953 100644
|
||||
goto out;
|
||||
}
|
||||
@@ -1059,6 +1060,7 @@ ssh_krl_from_blob(struct sshbuf *buf, struct ssh_krl **krlp)
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((krl = ssh_krl_init()) == NULL) {
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
error_f("alloc failed");
|
||||
goto out;
|
||||
}
|
||||
diff --git a/packet.c b/packet.c
|
||||
index 486f8515..9dea2cfc 100644
|
||||
--- a/packet.c
|
||||
+++ b/packet.c
|
||||
@@ -1864,6 +1864,14 @@ ssh_packet_read_poll_seqnr(struct ssh *ssh, u_char *typep, u_int32_t *seqnr_p)
|
||||
if ((r = sshpkt_get_string_direct(ssh, &d, &len)) != 0)
|
||||
return r;
|
||||
DBG(debug("Received SSH2_MSG_PING len %zu", len));
|
||||
+ if (!ssh->state->after_authentication) {
|
||||
+ DBG(debug("Won't reply to PING in preauth"));
|
||||
+ break;
|
||||
+ }
|
||||
+ if (ssh_packet_is_rekeying(ssh)) {
|
||||
+ DBG(debug("Won't reply to PING during KEX"));
|
||||
+ break;
|
||||
+ }
|
||||
if ((r = sshpkt_start(ssh, SSH2_MSG_PONG)) != 0 ||
|
||||
(r = sshpkt_put_string(ssh, d, len)) != 0 ||
|
||||
(r = sshpkt_send(ssh)) != 0)
|
||||
diff --git a/ssh-agent.c b/ssh-agent.c
|
||||
index 48973b2c..c27c5a95 100644
|
||||
--- a/ssh-agent.c
|
||||
+++ b/ssh-agent.c
|
||||
@@ -1220,6 +1220,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp,
|
||||
"restrict-destination-v00@openssh.com") == 0) {
|
||||
if (*dcsp != NULL) {
|
||||
error_f("%s already set", ext_name);
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshbuf_froms(m, &b)) != 0) {
|
||||
@@ -1229,6 +1230,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp,
|
||||
while (sshbuf_len(b) != 0) {
|
||||
if (*ndcsp >= AGENT_MAX_DEST_CONSTRAINTS) {
|
||||
error_f("too many %s constraints", ext_name);
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
*dcsp = xrecallocarray(*dcsp, *ndcsp, *ndcsp + 1,
|
||||
@@ -1246,6 +1248,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp,
|
||||
}
|
||||
if (*certs != NULL) {
|
||||
error_f("%s already set", ext_name);
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
if ((r = sshbuf_get_u8(m, &v)) != 0 ||
|
||||
@@ -1257,6 +1260,7 @@ parse_key_constraint_extension(struct sshbuf *m, char **sk_providerp,
|
||||
while (sshbuf_len(b) != 0) {
|
||||
if (*ncerts >= AGENT_MAX_EXT_CERTS) {
|
||||
error_f("too many %s constraints", ext_name);
|
||||
+ r = SSH_ERR_INVALID_FORMAT;
|
||||
goto out;
|
||||
}
|
||||
*certs = xrecallocarray(*certs, *ncerts, *ncerts + 1,
|
||||
@@ -1757,6 +1761,7 @@ process_ext_session_bind(SocketEntry *e)
|
||||
/* record new key/sid */
|
||||
if (e->nsession_ids >= AGENT_MAX_SESSION_IDS) {
|
||||
error_f("too many session IDs recorded");
|
||||
+ r = -1;
|
||||
goto out;
|
||||
}
|
||||
e->session_ids = xrecallocarray(e->session_ids, e->nsession_ids,
|
||||
diff --git a/ssh-sk-client.c b/ssh-sk-client.c
|
||||
index 321fe53a..06fad221 100644
|
||||
--- a/ssh-sk-client.c
|
||||
+++ b/ssh-sk-client.c
|
||||
@@ -439,6 +439,7 @@ sshsk_load_resident(const char *provider_path, const char *device,
|
||||
}
|
||||
if ((srk = calloc(1, sizeof(*srk))) == NULL) {
|
||||
error_f("calloc failed");
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
srk->key = key;
|
||||
@@ -450,6 +451,7 @@ sshsk_load_resident(const char *provider_path, const char *device,
|
||||
if ((tmp = recallocarray(srks, nsrks, nsrks + 1,
|
||||
sizeof(*srks))) == NULL) {
|
||||
error_f("recallocarray keys failed");
|
||||
+ r = SSH_ERR_ALLOC_FAIL;
|
||||
goto out;
|
||||
}
|
||||
debug_f("srks[%zu]: %s %s uidlen %zu", nsrks,
|
||||
diff --git a/sshconnect2.c b/sshconnect2.c
|
||||
index a69c4da1..1ee6000a 100644
|
||||
--- a/sshconnect2.c
|
||||
|
||||
@ -46,10 +46,10 @@
|
||||
%{?static_openssl:%global static_libcrypto 1}
|
||||
|
||||
# Do not forget to bump pam_ssh_agent_auth release if you rewind the main package release to 1
|
||||
%global openssh_ver 8.7p1
|
||||
%global openssh_rel 46
|
||||
%global openssh_ver 9.9p1
|
||||
%global openssh_rel 4
|
||||
%global pam_ssh_agent_ver 0.10.4
|
||||
%global pam_ssh_agent_rel 5
|
||||
%global pam_ssh_agent_rel 7
|
||||
|
||||
Summary: An open source implementation of SSH protocol version 2
|
||||
Name: openssh
|
||||
@ -133,12 +133,10 @@ Patch703: openssh-4.3p2-askpass-grab-info.patch
|
||||
Patch707: openssh-7.7p1-redhat.patch
|
||||
# warn users for unsupported UsePAM=no (#757545)
|
||||
Patch711: openssh-7.8p1-UsePAM-warning.patch
|
||||
# make aes-ctr ciphers use EVP engines such as AES-NI from OpenSSL
|
||||
Patch712: openssh-6.3p1-ctr-evp-fast.patch
|
||||
|
||||
# GSSAPI Key Exchange (RFC 4462 + RFC 8732)
|
||||
# from https://github.com/openssh-gsskex/openssh-gsskex/tree/fedora/master
|
||||
Patch800: openssh-8.0p1-gssapi-keyex.patch
|
||||
Patch800: openssh-9.6p1-gssapi-keyex.patch
|
||||
#http://www.mail-archive.com/kerberos@mit.edu/msg17591.html
|
||||
Patch801: openssh-6.6p1-force_krb.patch
|
||||
# add new option GSSAPIEnablek5users and disable using ~/.k5users by default (#1169843)
|
||||
@ -169,8 +167,6 @@ Patch926: openssh-6.7p1-sftp-force-permission.patch
|
||||
Patch939: openssh-7.2p2-s390-closefrom.patch
|
||||
# Move MAX_DISPLAYS to a configuration option (#1341302)
|
||||
Patch944: openssh-7.3p1-x11-max-displays.patch
|
||||
# Help systemd to track the running service
|
||||
Patch948: openssh-7.4p1-systemd.patch
|
||||
# Pass inetd flags for SELinux down to openbsd compat level
|
||||
Patch949: openssh-7.6p1-cleanup-selinux.patch
|
||||
# Sandbox adjustments for s390 and audit
|
||||
@ -183,8 +179,6 @@ Patch951: openssh-8.0p1-pkcs11-uri.patch
|
||||
Patch953: openssh-7.8p1-scp-ipv6.patch
|
||||
# Mention crypto-policies in manual pages (#1668325)
|
||||
Patch962: openssh-8.0p1-crypto-policies.patch
|
||||
# Use OpenSSL high-level API to produce and verify signatures (#1707485)
|
||||
Patch963: openssh-8.0p1-openssl-evp.patch
|
||||
# Use OpenSSL KDF (#1631761)
|
||||
Patch964: openssh-8.0p1-openssl-kdf.patch
|
||||
# sk-dummy.so built with -fvisibility=hidden does not work
|
||||
@ -195,20 +189,8 @@ Patch966: openssh-8.2p1-x11-without-ipv6.patch
|
||||
Patch974: openssh-8.0p1-keygen-strip-doseol.patch
|
||||
# sshd provides PAM an incorrect error code (#1879503)
|
||||
Patch975: openssh-8.0p1-preserve-pam-errors.patch
|
||||
# Use SFTP protocol by default for scp command
|
||||
Patch976: openssh-8.7p1-sftp-default-protocol.patch
|
||||
# Implement kill switch for SCP protocol
|
||||
Patch977: openssh-8.7p1-scp-kill-switch.patch
|
||||
# CVE-2021-41617
|
||||
Patch978: openssh-8.7p1-upstream-cve-2021-41617.patch
|
||||
# fix for `ssh-keygen -Y find-principals -f /dev/null -s /dev/null` (#2024902)
|
||||
Patch979: openssh-8.7p1-find-principals-fix.patch
|
||||
# Create non-existent directories when scp works in sftp mode and some more minor fixes
|
||||
# upstream commits:
|
||||
# ba61123eef9c6356d438c90c1199a57a0d7bcb0a
|
||||
# 63670d4e9030bcee490d5a9cce561373ac5b3b23
|
||||
# ac7c9ec894ed0825d04ef69c55babb49bab1d32e
|
||||
Patch980: openssh-8.7p1-sftpscp-dir-create.patch
|
||||
# Workaround for lack of sftp_realpath in older versions of RHEL
|
||||
# https://bugzilla.redhat.com/show_bug.cgi?id=2038854
|
||||
# https://github.com/openssh/openssh-portable/pull/299
|
||||
@ -216,90 +198,53 @@ Patch980: openssh-8.7p1-sftpscp-dir-create.patch
|
||||
Patch981: openssh-8.7p1-recursive-scp.patch
|
||||
# https://github.com/djmdjm/openssh-wip/pull/13
|
||||
Patch982: openssh-8.7p1-minrsabits.patch
|
||||
# downstream only
|
||||
Patch983: openssh-8.7p1-evpgenkey.patch
|
||||
# downstream only, IBMCA tentative fix
|
||||
# From https://bugzilla.redhat.com/show_bug.cgi?id=1976202#c14
|
||||
Patch984: openssh-8.7p1-ibmca.patch
|
||||
# Upstream ff89b1bed80721295555bd083b173247a9c0484e, 5062ad48814b06162511c4f5924a33d97b6b2566
|
||||
Patch986: openssh-9.1p1-sshbanner.patch
|
||||
|
||||
# Minimize the use of SHA1 as a proof of possession for RSA key (#2031868)
|
||||
# upstream commits:
|
||||
# 291721bc7c840d113a49518f3fca70e86248b8e8
|
||||
# 0fa33683223c76289470a954404047bc762be84c
|
||||
# Avoid dubious diagnostics on update known hosts (#2115246)
|
||||
# 8832402bd500d1661ccc80a476fd563335ef6cdc
|
||||
Patch1000: openssh-8.7p1-minimize-sha1-use.patch
|
||||
# Fix for scp clearing file when src and dest are the same (#2056884)
|
||||
# upstream commits:
|
||||
# 7b1cbcb7599d9f6a3bbad79d412604aa1203b5ee
|
||||
Patch1001: openssh-8.7p1-scp-clears-file.patch
|
||||
# Add missing options from ssh_config into ssh manpage
|
||||
# upstream bug:
|
||||
# https://bugzilla.mindrot.org/show_bug.cgi?id=3455
|
||||
Patch1002: openssh-8.7p1-ssh-manpage.patch
|
||||
# Always return allocated strings from the kex filtering so that we can free them
|
||||
# upstream commits:
|
||||
# 486c4dc3b83b4b67d663fb0fa62bc24138ec3946
|
||||
# 6c31ba10e97b6953c4f325f526f3e846dfea647a
|
||||
# 322964f8f2e9c321e77ebae1e4d2cd0ccc5c5a0b
|
||||
Patch1003: openssh-8.7p1-mem-leak.patch
|
||||
# Reenable MONITOR_REQ_GSSCHECKMIC after gssapi-with-mic failures
|
||||
# upstream MR:
|
||||
# https://github.com/openssh-gsskex/openssh-gsskex/pull/21
|
||||
Patch1004: openssh-8.7p1-gssapi-auth.patch
|
||||
# Fix host-based authentication with rsa keys
|
||||
# upstream commits:
|
||||
# 7aa7b096cf2bafe2777085abdeed5ce00581f641
|
||||
# d9dbb5d9a0326e252d3c7bc13beb9c2434f59409
|
||||
# fdb1d58d0d3888b042e5a500f6ce524486aaf782
|
||||
Patch1005: openssh-8.7p1-host-based-auth.patch
|
||||
# Don't propose disallowed algorithms during hostkey negotiation
|
||||
# upstream MR:
|
||||
# https://github.com/openssh/openssh-portable/pull/323
|
||||
Patch1006: openssh-8.7p1-negotiate-supported-algs.patch
|
||||
#
|
||||
Patch1007: openssh-8.7p1-nohostsha1proof.patch
|
||||
# CVE-2023-25136
|
||||
# upstream 12da7823336434a403f25c7cc0c2c6aed0737a35
|
||||
# to fix 1005
|
||||
Patch1008: openssh-8.7p1-CVE-2023-25136.patch
|
||||
|
||||
# fips compliance for signing, dh, ecdh
|
||||
Patch1009: openssh-8.7p1-evp-fips-compl-sign.patch
|
||||
Patch1010: openssh-8.7p1-evp-fips-compl-dh.patch
|
||||
Patch1011: openssh-8.7p1-evp-fips-compl-ecdh.patch
|
||||
Patch1012: openssh-8.7p1-evp-pkcs11.patch
|
||||
|
||||
# clarify rhbz#2068423 on the man page of ssh_config
|
||||
Patch1013: openssh-8.7p1-man-hostkeyalgos.patch
|
||||
# upstream commits
|
||||
# ec1ddb72a146fd66d18df9cd423517453a5d8044
|
||||
# b98a42afb69d60891eb0488935990df6ee571c4
|
||||
# a00f59a645072e5f5a8d207af15916a7b23e2642
|
||||
Patch1014: openssh-8.7p1-UTC-time-parse.patch
|
||||
# upsream commit
|
||||
# b23fe83f06ee7e721033769cfa03ae840476d280
|
||||
Patch1015: openssh-9.3p1-upstream-cve-2023-38408.patch
|
||||
#upstream commit b7afd8a4ecaca8afd3179b55e9db79c0ff210237
|
||||
Patch1016: openssh-9.3p1-openssl-compat.patch
|
||||
#upstream commit 01dbf3d46651b7d6ddf5e45d233839bbfffaeaec
|
||||
Patch1017: openssh-9.4p2-limit-delay.patch
|
||||
#upstream commit 1edb00c58f8a6875fad6a497aa2bacf37f9e6cd5
|
||||
Patch1018: openssh-9.6p1-CVE-2023-48795.patch
|
||||
#upstream commit 7ef3787c84b6b524501211b11a26c742f829af1a
|
||||
Patch1019: openssh-9.6p1-CVE-2023-51385.patch
|
||||
#upstream commit 96faa0de6c673a2ce84736eba37fc9fb723d9e5c
|
||||
Patch1020: openssh-8.7p1-sigpipe.patch
|
||||
Patch1021: openssh-9.8p1-upstream-cve-2024-6387.patch
|
||||
Patch1012: openssh-9.0p1-evp-fips-kex.patch
|
||||
Patch1015: openssh-9.6p1-pam-rhost.patch
|
||||
Patch1022: openssh-8.7p1-redhat-help.patch
|
||||
Patch1023: openssh-8.7p1-openssl-log.patch
|
||||
#upstream commit 52dfe3c72d98503d8b7c6f64fc7e19d685636c0b
|
||||
Patch1024: openssh-8.7p1-allow-duplicate-subsystem.patch
|
||||
# upstream 6ce00f0c2ecbb9f75023dbe627ee6460bcec78c2
|
||||
# upstream 0832aac79517611dd4de93ad0a83577994d9c907
|
||||
Patch1025: openssh-9.9p2-error_processing.patch
|
||||
# upstream cf3e48ee8ba1beeccddd2f203b558fa102be67a2
|
||||
# upstream 0c3927c45f8a57b511c874c4d51a8c89414f74ef
|
||||
Patch1026: openssh-9.9p1-mlkembe.patch
|
||||
# upstream 3f02368e8e9121847727c46b280efc280e5eb615
|
||||
# upstream 67a115e7a56dbdc3f5a58c64b29231151f3670f5
|
||||
Patch1027: openssh-9.9p1-match-regression.patch
|
||||
# Downstream patch, OpenSSL based MLKEM implementation
|
||||
Patch1028: openssh-9.9p1-openssl-mlkem.patch
|
||||
# upstream 8eabd2ae2ca1d7756417a1ee5b41f09c5d997634
|
||||
Patch1029: openssh-9.9p1-compression-directive.patch
|
||||
# upstream fc86875e6acb36401dfc1dfb6b628a9d1460f367
|
||||
Patch1030: openssh-9.9p1-disable-forwarding.patch
|
||||
Patch1031: openssh-9.9p1-non-supported-keys-err-msg.patch
|
||||
Patch1032: openssh-9.9p1-bad-hostkey.patch
|
||||
# https://github.com/openssh/openssh-portable/pull/500
|
||||
Patch1033: openssh-9.9p1-support-authentication-indicators-in-GSSAPI.patch
|
||||
#
|
||||
Patch1034: openssh-9.9p1-fips-gss.patch
|
||||
#upstream 6432b9f6a216d0f5fb43df500e9bc30bebb3f58b
|
||||
#upstream 4f14ca8633a2c8c0a1a19165663421f0ab32f6ab
|
||||
Patch1035: openssh-9.9p1-scp-traversing.patch
|
||||
Patch1036: openssh-9.9p1-canonical-match-user.patch
|
||||
# upstream 35d5917652106aede47621bb3f64044604164043
|
||||
Patch1037: openssh-9.9p1-reject-cntrl-chars-in-username.patch
|
||||
# upstream 43b3bff47bb029f2299bacb6a36057981b39fdb0
|
||||
Patch1038: openssh-9.9p1-reject-null-char-in-url-string.patch
|
||||
Patch1039: openssh-9.9p1-compat-mlkem.patch
|
||||
|
||||
License: BSD
|
||||
Requires: /sbin/nologin
|
||||
@ -454,7 +399,6 @@ popd
|
||||
%patch703 -p1 -b .grab-info
|
||||
%patch707 -p1 -b .redhat
|
||||
%patch711 -p1 -b .log-usepam-no
|
||||
%patch712 -p1 -b .evp-ctr
|
||||
#
|
||||
%patch800 -p1 -b .gsskex
|
||||
%patch801 -p1 -b .force_krb
|
||||
@ -471,65 +415,51 @@ popd
|
||||
%patch926 -p1 -b .sftp-force-mode
|
||||
%patch939 -p1 -b .s390-dev
|
||||
%patch944 -p1 -b .x11max
|
||||
%patch948 -p1 -b .systemd
|
||||
%patch949 -p1 -b .refactor
|
||||
%patch950 -p1 -b .sandbox
|
||||
%patch951 -p1 -b .pkcs11-uri
|
||||
%patch953 -p1 -b .scp-ipv6
|
||||
%patch962 -p1 -b .crypto-policies
|
||||
%patch963 -p1 -b .openssl-evp
|
||||
%patch964 -p1 -b .openssl-kdf
|
||||
%patch965 -p1 -b .visibility
|
||||
%patch966 -p1 -b .x11-ipv6
|
||||
%patch974 -p1 -b .keygen-strip-doseol
|
||||
%patch975 -p1 -b .preserve-pam-errors
|
||||
%patch976 -p1 -b .sftp-by-default
|
||||
%patch977 -p1 -b .kill-scp
|
||||
%patch978 -p1 -b .cve-2021-41617
|
||||
%patch979 -p1 -b .find-principals
|
||||
%patch980 -p1 -b .sftpdirs
|
||||
%patch981 -p1 -b .scp-sftpdirs
|
||||
%patch982 -p1 -b .minrsabits
|
||||
%patch983 -p1 -b .evpgenrsa
|
||||
%patch984 -p1 -b .ibmca
|
||||
%patch986 -p1 -b .91cleanup
|
||||
|
||||
%patch200 -p1 -b .audit
|
||||
%patch201 -p1 -b .audit-race
|
||||
%patch202 -p1 -b .audit-hostname
|
||||
%patch700 -p1 -b .fips
|
||||
|
||||
%patch1000 -p1 -b .minimize-sha1-use
|
||||
%patch1001 -p1 -b .scp-clears-file
|
||||
%patch1002 -p1 -b .ssh-manpage
|
||||
%patch1003 -p1 -b .mem-leak
|
||||
%patch1004 -p1 -b .gssapi-auth
|
||||
%patch1005 -p1 -b .host-based-auth
|
||||
%patch1006 -p1 -b .negotiate-supported-algs
|
||||
|
||||
%patch100 -p1 -b .coverity
|
||||
|
||||
%patch1007 -p1 -b .sshrsacheck
|
||||
%patch1008 -p1 -b .cve-2023-25136
|
||||
|
||||
%patch1009 -p1 -b .evp_fips_sign
|
||||
%patch1010 -p1 -b .evp_fips_dh
|
||||
%patch1011 -p1 -b .evp_fips_ecdh
|
||||
%patch1012 -p1 -b .evp_pkcs11
|
||||
|
||||
%patch1013 -p1 -b .man-hostkeyalgos
|
||||
%patch1014 -p1 -b .utc_parse
|
||||
%patch1015 -p1 -b .cve-2023-38408
|
||||
%patch1016 -p1 -b .openssl3compat
|
||||
%patch1017 -p1 -b .limitdelay
|
||||
%patch1018 -p1 -b .cve-2023-48795
|
||||
%patch1019 -p1 -b .cve-2023-51385
|
||||
%patch1020 -p1 -b .earlypipe
|
||||
%patch1021 -p1 -b .cve-2024-6387
|
||||
%patch1012 -p1 -b .evp-fips-kex
|
||||
%patch1015 -p1 -b .pam-rhost
|
||||
%patch1022 -p1 -b .redhat-help
|
||||
%patch1023 -p1 -b .openssl-log
|
||||
%patch1024 -p1 -b .allow-dup-subsystem
|
||||
%patch1025 -p1 -b .errcode_set
|
||||
%patch1026 -p1 -b .mlkembe
|
||||
%patch1027 -p1 -b .match
|
||||
%patch1028 -p1 -b .openssl-mlkem
|
||||
%patch1029 -p1 -b .compression
|
||||
%patch1030 -p1 -b .disable-forwarding
|
||||
%patch1031 -p1 -b .non-supported-keys-err-msg
|
||||
%patch1032 -p1 -b .bad-hostkey
|
||||
%patch1033 -p1 -b .gss-indicators
|
||||
%patch1034 -p1 -b .gss-fips
|
||||
%patch1035 -p1 -b .scp-traversing
|
||||
%patch1036 -p1 -b .canonical-match-user
|
||||
%patch1037 -p1 -b .reject-cntrl-chars-in-username
|
||||
%patch1038 -p1 -b .reject-null-char-in-url-string
|
||||
%patch1039 -p1 -b .skip-mlkem-when-na
|
||||
|
||||
autoreconf
|
||||
pushd pam_ssh_agent_auth-pam_ssh_agent_auth-%{pam_ssh_agent_ver}
|
||||
@ -582,10 +512,10 @@ fi
|
||||
--with-ipaddr-display \
|
||||
--with-pie=no \
|
||||
--without-hardening `# The hardening flags are configured by system` \
|
||||
--with-systemd \
|
||||
--with-default-pkcs11-provider=yes \
|
||||
--with-security-key-builtin=yes \
|
||||
--with-pam \
|
||||
--enable-dsa-keys \
|
||||
%if %{WITH_SELINUX}
|
||||
--with-selinux --with-audit=linux \
|
||||
--with-sandbox=seccomp_filter \
|
||||
@ -776,6 +706,7 @@ test -f %{sysconfig_anaconda} && \
|
||||
%files server
|
||||
%dir %attr(0711,root,root) %{_datadir}/empty.sshd
|
||||
%attr(0755,root,root) %{_sbindir}/sshd
|
||||
%attr(0755,root,root) %{_libexecdir}/openssh/sshd-session
|
||||
%attr(0755,root,root) %{_libexecdir}/openssh/sftp-server
|
||||
%attr(0755,root,root) %{_libexecdir}/openssh/sshd-keygen
|
||||
%attr(0644,root,root) %{_mandir}/man5/sshd_config.5*
|
||||
@ -817,6 +748,28 @@ test -f %{sysconfig_anaconda} && \
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Feb 25 2026 Dmitry Belyavskiy <dbelyavs@redhat.com> - 9.9p1-4
|
||||
- Provide a way to skip unsupported ML-KEM hybrid algorithms in FIPS mode
|
||||
Resolves: RHEL-151580
|
||||
|
||||
* Tue Dec 09 2025 Zoltan Fridrich <zfridric@redhat.com> - 9.9p1-3
|
||||
- Enable support for DSA keys
|
||||
Resolves: RHEL-127624
|
||||
- CVE-2025-61984: Reject usernames with control characters
|
||||
Resolves: RHEL-133959
|
||||
- CVE-2025-61985: Reject URL-strings with NULL characters
|
||||
Resolves: RHEL-133960
|
||||
|
||||
* Mon Oct 27 2025 Zoltan Fridrich <zfridric@redhat.com> - 9.9p1-2
|
||||
- Fix implicit destination path selection when source path ends with ".."
|
||||
Resolves: RHEL-119515
|
||||
- Canonicalize username when matching a user
|
||||
Resolves: RHEL-118372
|
||||
|
||||
* Wed Sep 10 2025 Pavol Žáčik <pzacik@redhat.com> - 9.9p1-1
|
||||
- Rebase to version 9.9
|
||||
Resolves: RHEL-108912
|
||||
|
||||
* Mon Jul 21 2025 Zoltan Fridrich <zfridric@redhat.com> - 8.7p1-46
|
||||
- Move the redhat help message to debug1 log level
|
||||
Resolves: RHEL-104580
|
||||
|
||||
Loading…
Reference in New Issue
Block a user