diff --git a/CVE-2019-16905.patch b/CVE-2019-16905.patch deleted file mode 100644 index 5386344f22ed31cc2dff7702941cec73fb7e8809..0000000000000000000000000000000000000000 --- a/CVE-2019-16905.patch +++ /dev/null @@ -1,37 +0,0 @@ -From a546b17bbaeb12beac4c9aeed56f74a42b18a93a Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Wed, 9 Oct 2019 00:02:57 +0000 -Subject: [PATCH] upstream: fix integer overflow in XMSS private key parsing. - -Reported by Adam Zabrocki via SecuriTeam's SSH program. - -Note that this code is experimental and not compiled by default. - -ok markus@ - -OpenBSD-Commit-ID: cd0361896d15e8a1bac495ac583ff065ffca2be1 ---- - sshkey-xmss.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/sshkey-xmss.c b/sshkey-xmss.c -index a29e33f39..9e5f5e475 100644 ---- a/sshkey-xmss.c -+++ b/sshkey-xmss.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: sshkey-xmss.c,v 1.3 2018/07/09 21:59:10 markus Exp $ */ -+/* $OpenBSD: sshkey-xmss.c,v 1.6 2019/10/09 00:02:57 djm Exp $ */ - /* - * Copyright (c) 2017 Markus Friedl. All rights reserved. - * -@@ -977,7 +977,8 @@ sshkey_xmss_decrypt_state(const struct sshkey *k, struct sshbuf *encoded, - goto out; - } - /* check that an appropriate amount of auth data is present */ -- if (sshbuf_len(encoded) < encrypted_len + authlen) { -+ if (sshbuf_len(encoded) < authlen || -+ sshbuf_len(encoded) - authlen < encrypted_len) { - r = SSH_ERR_INVALID_FORMAT; - goto out; - } - diff --git a/CVE-2019-6109-1.patch b/CVE-2019-6109-1.patch deleted file mode 100644 index 1740739579bacb48cfc7e6eae804609ec604de87..0000000000000000000000000000000000000000 --- a/CVE-2019-6109-1.patch +++ /dev/null @@ -1,270 +0,0 @@ -From 8976f1c4b2721c26e878151f52bdf346dfe2d54c Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Wed, 23 Jan 2019 08:01:46 +0000 -Subject: [PATCH] upstream: Sanitize scp filenames via snmprintf. To do this we - move - -the progressmeter formatting outside of signal handler context and have the -atomicio callback called for EINTR too. bz#2434 with contributions from djm -and jjelen at redhat.com, ok djm@ - -OpenBSD-Commit-ID: 1af61c1f70e4f3bd8ab140b9f1fa699481db57d8 ---- - atomicio.c | 20 ++++++++++++++----- - progressmeter.c | 53 ++++++++++++++++++++++--------------------------- - progressmeter.h | 3 ++- - scp.c | 3 ++- - sftp-client.c | 18 +++++++++-------- - 5 files changed, 53 insertions(+), 44 deletions(-) - -diff --git a/atomicio.c b/atomicio.c -index cffa9fa7d..845b328ee 100644 ---- a/atomicio.c -+++ b/atomicio.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: atomicio.c,v 1.28 2016/07/27 23:18:12 djm Exp $ */ -+/* $OpenBSD: atomicio.c,v 1.29 2019/01/23 08:01:46 dtucker Exp $ */ - /* - * Copyright (c) 2006 Damien Miller. All rights reserved. - * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved. -@@ -67,9 +67,14 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n, - res = (f) (fd, s + pos, n - pos); - switch (res) { - case -1: -- if (errno == EINTR) -+ if (errno == EINTR) { -+ /* possible SIGALARM, update callback */ -+ if (cb != NULL && cb(cb_arg, 0) == -1) { -+ errno = EINTR; -+ return pos; -+ } - continue; -- if (errno == EAGAIN || errno == EWOULDBLOCK) { -+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) { - #ifndef BROKEN_READ_COMPARISON - (void)poll(&pfd, 1, -1); - #endif -@@ -124,9 +129,14 @@ atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd, - res = (f) (fd, iov, iovcnt); - switch (res) { - case -1: -- if (errno == EINTR) -+ if (errno == EINTR) { -+ /* possible SIGALARM, update callback */ -+ if (cb != NULL && cb(cb_arg, 0) == -1) { -+ errno = EINTR; -+ return pos; -+ } - continue; -- if (errno == EAGAIN || errno == EWOULDBLOCK) { -+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) { - #ifndef BROKEN_READV_COMPARISON - (void)poll(&pfd, 1, -1); - #endif -diff --git a/progressmeter.c b/progressmeter.c -index fe9bf52e4..add462dde 100644 ---- a/progressmeter.c -+++ b/progressmeter.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: progressmeter.c,v 1.45 2016/06/30 05:17:05 dtucker Exp $ */ -+/* $OpenBSD: progressmeter.c,v 1.46 2019/01/23 08:01:46 dtucker Exp $ */ - /* - * Copyright (c) 2003 Nils Nordman. All rights reserved. - * -@@ -31,6 +31,7 @@ - - #include - #include -+#include - #include - #include - #include -@@ -39,6 +40,7 @@ - #include "progressmeter.h" - #include "atomicio.h" - #include "misc.h" -+#include "utf8.h" - - #define DEFAULT_WINSIZE 80 - #define MAX_WINSIZE 512 -@@ -61,7 +63,7 @@ static void setscreensize(void); - void refresh_progress_meter(void); - - /* signal handler for updating the progress meter */ --static void update_progress_meter(int); -+static void sig_alarm(int); - - static double start; /* start progress */ - static double last_update; /* last progress update */ -@@ -74,6 +76,7 @@ static long stalled; /* how long we have been stalled */ - static int bytes_per_second; /* current speed in bytes per second */ - static int win_size; /* terminal window size */ - static volatile sig_atomic_t win_resized; /* for window resizing */ -+static volatile sig_atomic_t alarm_fired; - - /* units for format_size */ - static const char unit[] = " KMGT"; -@@ -126,9 +129,17 @@ refresh_progress_meter(void) - off_t bytes_left; - int cur_speed; - int hours, minutes, seconds; -- int i, len; - int file_len; - -+ if ((!alarm_fired && !win_resized) || !can_output()) -+ return; -+ alarm_fired = 0; -+ -+ if (win_resized) { -+ setscreensize(); -+ win_resized = 0; -+ } -+ - transferred = *counter - (cur_pos ? cur_pos : start_pos); - cur_pos = *counter; - now = monotime_double(); -@@ -158,16 +169,11 @@ refresh_progress_meter(void) - - /* filename */ - buf[0] = '\0'; -- file_len = win_size - 35; -+ file_len = win_size - 36; - if (file_len > 0) { -- len = snprintf(buf, file_len + 1, "\r%s", file); -- if (len < 0) -- len = 0; -- if (len >= file_len + 1) -- len = file_len; -- for (i = len; i < file_len; i++) -- buf[i] = ' '; -- buf[file_len] = '\0'; -+ buf[0] = '\r'; -+ snmprintf(buf+1, sizeof(buf)-1 , &file_len, "%*s", -+ file_len * -1, file); - } - - /* percent of transfer done */ -@@ -228,22 +234,11 @@ refresh_progress_meter(void) - - /*ARGSUSED*/ - static void --update_progress_meter(int ignore) -+sig_alarm(int ignore) - { -- int save_errno; -- -- save_errno = errno; -- -- if (win_resized) { -- setscreensize(); -- win_resized = 0; -- } -- if (can_output()) -- refresh_progress_meter(); -- -- signal(SIGALRM, update_progress_meter); -+ signal(SIGALRM, sig_alarm); -+ alarm_fired = 1; - alarm(UPDATE_INTERVAL); -- errno = save_errno; - } - - void -@@ -259,10 +254,9 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr) - bytes_per_second = 0; - - setscreensize(); -- if (can_output()) -- refresh_progress_meter(); -+ refresh_progress_meter(); - -- signal(SIGALRM, update_progress_meter); -+ signal(SIGALRM, sig_alarm); - signal(SIGWINCH, sig_winch); - alarm(UPDATE_INTERVAL); - } -@@ -286,6 +280,7 @@ stop_progress_meter(void) - static void - sig_winch(int sig) - { -+ signal(SIGWINCH, sig_winch); - win_resized = 1; - } - -diff --git a/progressmeter.h b/progressmeter.h -index bf179dca6..8f6678060 100644 ---- a/progressmeter.h -+++ b/progressmeter.h -@@ -1,4 +1,4 @@ --/* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */ -+/* $OpenBSD: progressmeter.h,v 1.4 2019/01/23 08:01:46 dtucker Exp $ */ - /* - * Copyright (c) 2002 Nils Nordman. All rights reserved. - * -@@ -24,4 +24,5 @@ - */ - - void start_progress_meter(const char *, off_t, off_t *); -+void refresh_progress_meter(void); - void stop_progress_meter(void); -diff --git a/scp.c b/scp.c -index ae51137ee..25595a299 100644 ---- a/scp.c -+++ b/scp.c -@@ -588,6 +588,7 @@ scpio(void *_cnt, size_t s) - off_t *cnt = (off_t *)_cnt; - - *cnt += s; -+ refresh_progress_meter(); - if (limit_kbps > 0) - bandwidth_limit(&bwlimit, s); - return 0; -diff --git a/sftp-client.c b/sftp-client.c -index d3f80e5a0..36c4b8a4a 100644 ---- a/sftp-client.c -+++ b/sftp-client.c -@@ -102,7 +102,9 @@ sftpio(void *_bwlimit, size_t amount) - { - struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; - -- bandwidth_limit(bwlimit, amount); -+ refresh_progress_meter(); -+ if (bwlimit != NULL) -+ bandwidth_limit(bwlimit, amount); - return 0; - } - -@@ -122,8 +124,8 @@ send_msg(struct sftp_conn *conn, struct sshbuf *m) - iov[1].iov_base = (u_char *)sshbuf_ptr(m); - iov[1].iov_len = sshbuf_len(m); - -- if (atomiciov6(writev, conn->fd_out, iov, 2, -- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) != -+ if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio, -+ conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) != - sshbuf_len(m) + sizeof(mlen)) - fatal("Couldn't send packet: %s", strerror(errno)); - -@@ -139,8 +141,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) - - if ((r = sshbuf_reserve(m, 4, &p)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -- if (atomicio6(read, conn->fd_in, p, 4, -- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) { -+ if (atomicio6(read, conn->fd_in, p, 4, sftpio, -+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) { - if (errno == EPIPE || errno == ECONNRESET) - fatal("Connection closed"); - else -@@ -158,8 +160,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial) - - if ((r = sshbuf_reserve(m, msg_len, &p)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -- if (atomicio6(read, conn->fd_in, p, msg_len, -- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) -+ if (atomicio6(read, conn->fd_in, p, msg_len, sftpio, -+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) - != msg_len) { - if (errno == EPIPE) - fatal("Connection closed"); - diff --git a/CVE-2019-6109-2.patch b/CVE-2019-6109-2.patch deleted file mode 100644 index d3fb333fec0b83fd4f135bf602dcf1f21bf0a894..0000000000000000000000000000000000000000 --- a/CVE-2019-6109-2.patch +++ /dev/null @@ -1,117 +0,0 @@ -From bdc6c63c80b55bcbaa66b5fde31c1cb1d09a41eb Mon Sep 17 00:00:00 2001 -From: "dtucker@openbsd.org" -Date: Thu, 24 Jan 2019 16:52:17 +0000 -Subject: [PATCH] upstream: Have progressmeter force an update at the beginning - and - -end of each transfer. Fixes the problem recently introduces where very quick -transfers do not display the progressmeter at all. Spotted by naddy@ - -OpenBSD-Commit-ID: 68dc46c259e8fdd4f5db3ec2a130f8e4590a7a9a ---- - progressmeter.c | 13 +++++-------- - progressmeter.h | 4 ++-- - scp.c | 4 ++-- - sftp-client.c | 4 ++-- - 4 files changed, 11 insertions(+), 14 deletions(-) - -diff --git a/progressmeter.c b/progressmeter.c -index add462dde..e385c1254 100644 ---- a/progressmeter.c -+++ b/progressmeter.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: progressmeter.c,v 1.46 2019/01/23 08:01:46 dtucker Exp $ */ -+/* $OpenBSD: progressmeter.c,v 1.47 2019/01/24 16:52:17 dtucker Exp $ */ - /* - * Copyright (c) 2003 Nils Nordman. All rights reserved. - * -@@ -59,9 +59,6 @@ static void format_rate(char *, int, off_t); - static void sig_winch(int); - static void setscreensize(void); - --/* updates the progressmeter to reflect the current state of the transfer */ --void refresh_progress_meter(void); -- - /* signal handler for updating the progress meter */ - static void sig_alarm(int); - -@@ -120,7 +117,7 @@ format_size(char *buf, int size, off_t bytes) - } - - void --refresh_progress_meter(void) -+refresh_progress_meter(int force_update) - { - char buf[MAX_WINSIZE + 1]; - off_t transferred; -@@ -131,7 +128,7 @@ refresh_progress_meter(void) - int hours, minutes, seconds; - int file_len; - -- if ((!alarm_fired && !win_resized) || !can_output()) -+ if ((!force_update && !alarm_fired && !win_resized) || !can_output()) - return; - alarm_fired = 0; - -@@ -254,7 +251,7 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr) - bytes_per_second = 0; - - setscreensize(); -- refresh_progress_meter(); -+ refresh_progress_meter(1); - - signal(SIGALRM, sig_alarm); - signal(SIGWINCH, sig_winch); -@@ -271,7 +268,7 @@ stop_progress_meter(void) - - /* Ensure we complete the progress */ - if (cur_pos != end_pos) -- refresh_progress_meter(); -+ refresh_progress_meter(1); - - atomicio(vwrite, STDOUT_FILENO, "\n", 1); - } -diff --git a/progressmeter.h b/progressmeter.h -index 8f6678060..1703ea75b 100644 ---- a/progressmeter.h -+++ b/progressmeter.h -@@ -1,4 +1,4 @@ --/* $OpenBSD: progressmeter.h,v 1.4 2019/01/23 08:01:46 dtucker Exp $ */ -+/* $OpenBSD: progressmeter.h,v 1.5 2019/01/24 16:52:17 dtucker Exp $ */ - /* - * Copyright (c) 2002 Nils Nordman. All rights reserved. - * -@@ -24,5 +24,5 @@ - */ - - void start_progress_meter(const char *, off_t, off_t *); --void refresh_progress_meter(void); -+void refresh_progress_meter(int); - void stop_progress_meter(void); -diff --git a/scp.c b/scp.c -index 25595a299..74dfe521a 100644 ---- a/scp.c -+++ b/scp.c -@@ -588,7 +588,7 @@ scpio(void *_cnt, size_t s) - off_t *cnt = (off_t *)_cnt; - - *cnt += s; -- refresh_progress_meter(); -+ refresh_progress_meter(0); - if (limit_kbps > 0) - bandwidth_limit(&bwlimit, s); - return 0; -diff --git a/sftp-client.c b/sftp-client.c -index 36c4b8a4a..73e3c2f53 100644 ---- a/sftp-client.c -+++ b/sftp-client.c -@@ -102,7 +102,7 @@ sftpio(void *_bwlimit, size_t amount) - { - struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit; - -- refresh_progress_meter(); -+ refresh_progress_meter(0); - if (bwlimit != NULL) - bandwidth_limit(bwlimit, amount); - return 0; - diff --git a/CVE-2019-6111-1.patch b/CVE-2019-6111-1.patch deleted file mode 100644 index e11fd5be176b4a68b97efd62acf3c802dd9fdda6..0000000000000000000000000000000000000000 --- a/CVE-2019-6111-1.patch +++ /dev/null @@ -1,181 +0,0 @@ -From 391ffc4b9d31fa1f4ad566499fef9176ff8a07dc Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Sat, 26 Jan 2019 22:41:28 +0000 -Subject: [PATCH] upstream: check in scp client that filenames sent during - -remote->local directory copies satisfy the wildcard specified by the user. - -This checking provides some protection against a malicious server -sending unexpected filenames, but it comes at a risk of rejecting wanted -files due to differences between client and server wildcard expansion rules. - -For this reason, this also adds a new -T flag to disable the check. - -reported by Harry Sintonen -fix approach suggested by markus@; -has been in snaps for ~1wk courtesy deraadt@ - -OpenBSD-Commit-ID: 00f44b50d2be8e321973f3c6d014260f8f7a8eda ---- - scp.1 | 16 +++++++++++++--- - scp.c | 39 ++++++++++++++++++++++++++++++--------- - 2 files changed, 43 insertions(+), 12 deletions(-) - -diff --git a/scp.1 b/scp.1 -index 8bb63edaa..a2833dab0 100644 ---- a/scp.1 -+++ b/scp.1 -@@ -18,7 +18,7 @@ - .Nd secure copy (remote file copy program) - .Sh SYNOPSIS - .Nm scp --.Op Fl 346BCpqrv -+.Op Fl 346BCpqrTv - .Op Fl c Ar cipher - .Op Fl F Ar ssh_config - .Op Fl i Ar identity_file -@@ -222,6 +222,16 @@ to use for the encrypted connection. - The program must understand - .Xr ssh 1 - options. -+.It Fl T -+Disable strict filename checking. -+By default when copying files from a remote host to a local directory -+.Nm -+checks that the received filenames match those requested on the command-line -+to prevent the remote end from sending unexpected or unwanted files. -+Because of differences in how various operating systems and shells interpret -+filename wildcards, these checks may cause wanted files to be rejected. -+This option disables these checks at the expense of fully trusting that -+the server will not send unexpected filenames. - .It Fl v - Verbose mode. - Causes -diff --git a/scp.c b/scp.c -index 74dfe521a..e669e815e 100644 ---- a/scp.c -+++ b/scp.c -@@ -94,6 +94,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -375,14 +376,14 @@ void verifydir(char *); - struct passwd *pwd; - uid_t userid; - int errs, remin, remout; --int pflag, iamremote, iamrecursive, targetshouldbedirectory; -+int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory; - - #define CMDNEEDS 64 - char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */ - - int response(void); - void rsource(char *, struct stat *); --void sink(int, char *[]); -+void sink(int, char *[], const char *); - void source(int, char *[]); - void tolocal(int, char *[]); - void toremote(int, char *[]); -@@ -423,8 +424,9 @@ main(int argc, char **argv) - addargs(&args, "-oRemoteCommand=none"); - addargs(&args, "-oRequestTTY=no"); - -- fflag = tflag = 0; -- while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1) -+ fflag = Tflag = tflag = 0; -+ while ((ch = getopt(argc, argv, -+ "dfl:prtTvBCc:i:P:q12346S:o:F:J:")) != -1) { - switch (ch) { - /* User-visible flags. */ - case '1': -@@ -504,9 +506,13 @@ main(int argc, char **argv) - setmode(0, O_BINARY); - #endif - break; -+ case 'T': -+ Tflag = 1; -+ break; - default: - usage(); - } -+ } - argc -= optind; - argv += optind; - -@@ -537,7 +543,7 @@ main(int argc, char **argv) - } - if (tflag) { - /* Receive data. */ -- sink(argc, argv); -+ sink(argc, argv, NULL); - exit(errs != 0); - } - if (argc < 2) -@@ -795,7 +801,7 @@ tolocal(int argc, char **argv) - continue; - } - free(bp); -- sink(1, argv + argc - 1); -+ sink(1, argv + argc - 1, src); - (void) close(remin); - remin = remout = -1; - } -@@ -971,7 +977,7 @@ rsource(char *name, struct stat *statp) - (sizeof(type) != 4 && sizeof(type) != 8)) - - void --sink(int argc, char **argv) -+sink(int argc, char **argv, const char *src) - { - static BUF buffer; - struct stat stb; -@@ -987,6 +993,7 @@ sink(int argc, char **argv) - unsigned long long ull; - int setimes, targisdir, wrerrno = 0; - char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; -+ char *src_copy = NULL, *restrict_pattern = NULL; - struct timeval tv[2]; - - #define atime tv[0] -@@ -1011,6 +1018,17 @@ sink(int argc, char **argv) - (void) atomicio(vwrite, remout, "", 1); - if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode)) - targisdir = 1; -+ if (src != NULL && !iamrecursive && !Tflag) { -+ /* -+ * Prepare to try to restrict incoming filenames to match -+ * the requested destination file glob. -+ */ -+ if ((src_copy = strdup(src)) == NULL) -+ fatal("strdup failed"); -+ if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) { -+ *restrict_pattern++ = '\0'; -+ } -+ } - for (first = 1;; first = 0) { - cp = buf; - if (atomicio(read, remin, cp, 1) != 1) -@@ -1115,6 +1133,9 @@ sink(int argc, char **argv) - run_err("error: unexpected filename: %s", cp); - exit(1); - } -+ if (restrict_pattern != NULL && -+ fnmatch(restrict_pattern, cp, 0) != 0) -+ SCREWUP("filename does not match request"); - if (targisdir) { - static char *namebuf; - static size_t cursize; -@@ -1152,7 +1173,7 @@ sink(int argc, char **argv) - goto bad; - } - vect[0] = xstrdup(np); -- sink(1, vect); -+ sink(1, vect, src); - if (setimes) { - setimes = 0; - if (utimes(vect[0], tv) < 0) - diff --git a/CVE-2019-6111-2.patch b/CVE-2019-6111-2.patch deleted file mode 100644 index 16b2b572bd849c0820f03480d289bffe6443133d..0000000000000000000000000000000000000000 --- a/CVE-2019-6111-2.patch +++ /dev/null @@ -1,348 +0,0 @@ -From 3d896c157c722bc47adca51a58dca859225b5874 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Sun, 10 Feb 2019 11:15:52 +0000 -Subject: [PATCH] upstream: when checking that filenames sent by the server - side - -match what the client requested, be prepared to handle shell-style brace -alternations, e.g. "{foo,bar}". - -"looks good to me" millert@ + in snaps for the last week courtesy -deraadt@ - -OpenBSD-Commit-ID: 3b1ce7639b0b25b2248e3a30f561a548f6815f3e ---- - scp.c | 282 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- - 1 file changed, 270 insertions(+), 12 deletions(-) - -diff --git a/scp.c b/scp.c -index 96fc246cd..80bc0e8b1 100644 ---- a/scp.c -+++ b/scp.c -@@ -630,6 +630,253 @@ parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp, - return r; - } - -+/* Appends a string to an array; returns 0 on success, -1 on alloc failure */ -+static int -+append(char *cp, char ***ap, size_t *np) -+{ -+ char **tmp; -+ -+ if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL) -+ return -1; -+ tmp[(*np)] = cp; -+ (*np)++; -+ *ap = tmp; -+ return 0; -+} -+ -+/* -+ * Finds the start and end of the first brace pair in the pattern. -+ * returns 0 on success or -1 for invalid patterns. -+ */ -+static int -+find_brace(const char *pattern, int *startp, int *endp) -+{ -+ int i; -+ int in_bracket, brace_level; -+ -+ *startp = *endp = -1; -+ in_bracket = brace_level = 0; -+ for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) { -+ switch (pattern[i]) { -+ case '\\': -+ /* skip next character */ -+ if (pattern[i + 1] != '\0') -+ i++; -+ break; -+ case '[': -+ in_bracket = 1; -+ break; -+ case ']': -+ in_bracket = 0; -+ break; -+ case '{': -+ if (in_bracket) -+ break; -+ if (pattern[i + 1] == '}') { -+ /* Protect a single {}, for find(1), like csh */ -+ i++; /* skip */ -+ break; -+ } -+ if (*startp == -1) -+ *startp = i; -+ brace_level++; -+ break; -+ case '}': -+ if (in_bracket) -+ break; -+ if (*startp < 0) { -+ /* Unbalanced brace */ -+ return -1; -+ } -+ if (--brace_level <= 0) -+ *endp = i; -+ break; -+ } -+ } -+ /* unbalanced brackets/braces */ -+ if (*endp < 0 && (*startp >= 0 || in_bracket)) -+ return -1; -+ return 0; -+} -+ -+/* -+ * Assembles and records a successfully-expanded pattern, returns -1 on -+ * alloc failure. -+ */ -+static int -+emit_expansion(const char *pattern, int brace_start, int brace_end, -+ int sel_start, int sel_end, char ***patternsp, size_t *npatternsp) -+{ -+ char *cp; -+ int o = 0, tail_len = strlen(pattern + brace_end + 1); -+ -+ if ((cp = malloc(brace_start + (sel_end - sel_start) + -+ tail_len + 1)) == NULL) -+ return -1; -+ -+ /* Pattern before initial brace */ -+ if (brace_start > 0) { -+ memcpy(cp, pattern, brace_start); -+ o = brace_start; -+ } -+ /* Current braced selection */ -+ if (sel_end - sel_start > 0) { -+ memcpy(cp + o, pattern + sel_start, -+ sel_end - sel_start); -+ o += sel_end - sel_start; -+ } -+ /* Remainder of pattern after closing brace */ -+ if (tail_len > 0) { -+ memcpy(cp + o, pattern + brace_end + 1, tail_len); -+ o += tail_len; -+ } -+ cp[o] = '\0'; -+ if (append(cp, patternsp, npatternsp) != 0) { -+ free(cp); -+ return -1; -+ } -+ return 0; -+} -+ -+/* -+ * Expand the first encountered brace in pattern, appending the expanded -+ * patterns it yielded to the *patternsp array. -+ * -+ * Returns 0 on success or -1 on allocation failure. -+ * -+ * Signals whether expansion was performed via *expanded and whether -+ * pattern was invalid via *invalid. -+ */ -+static int -+brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp, -+ int *expanded, int *invalid) -+{ -+ int i; -+ int in_bracket, brace_start, brace_end, brace_level; -+ int sel_start, sel_end; -+ -+ *invalid = *expanded = 0; -+ -+ if (find_brace(pattern, &brace_start, &brace_end) != 0) { -+ *invalid = 1; -+ return 0; -+ } else if (brace_start == -1) -+ return 0; -+ -+ in_bracket = brace_level = 0; -+ for (i = sel_start = brace_start + 1; i < brace_end; i++) { -+ switch (pattern[i]) { -+ case '{': -+ if (in_bracket) -+ break; -+ brace_level++; -+ break; -+ case '}': -+ if (in_bracket) -+ break; -+ brace_level--; -+ break; -+ case '[': -+ in_bracket = 1; -+ break; -+ case ']': -+ in_bracket = 0; -+ break; -+ case '\\': -+ if (i < brace_end - 1) -+ i++; /* skip */ -+ break; -+ } -+ if (pattern[i] == ',' || i == brace_end - 1) { -+ if (in_bracket || brace_level > 0) -+ continue; -+ /* End of a selection, emit an expanded pattern */ -+ -+ /* Adjust end index for last selection */ -+ sel_end = (i == brace_end - 1) ? brace_end : i; -+ if (emit_expansion(pattern, brace_start, brace_end, -+ sel_start, sel_end, patternsp, npatternsp) != 0) -+ return -1; -+ /* move on to the next selection */ -+ sel_start = i + 1; -+ continue; -+ } -+ } -+ if (in_bracket || brace_level > 0) { -+ *invalid = 1; -+ return 0; -+ } -+ /* success */ -+ *expanded = 1; -+ return 0; -+} -+ -+/* Expand braces from pattern. Returns 0 on success, -1 on failure */ -+static int -+brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp) -+{ -+ char *cp, *cp2, **active = NULL, **done = NULL; -+ size_t i, nactive = 0, ndone = 0; -+ int ret = -1, invalid = 0, expanded = 0; -+ -+ *patternsp = NULL; -+ *npatternsp = 0; -+ -+ /* Start the worklist with the original pattern */ -+ if ((cp = strdup(pattern)) == NULL) -+ return -1; -+ if (append(cp, &active, &nactive) != 0) { -+ free(cp); -+ return -1; -+ } -+ while (nactive > 0) { -+ cp = active[nactive - 1]; -+ nactive--; -+ if (brace_expand_one(cp, &active, &nactive, -+ &expanded, &invalid) == -1) { -+ free(cp); -+ goto fail; -+ } -+ if (invalid) -+ fatal("%s: invalid brace pattern \"%s\"", __func__, cp); -+ if (expanded) { -+ /* -+ * Current entry expanded to new entries on the -+ * active list; discard the progenitor pattern. -+ */ -+ free(cp); -+ continue; -+ } -+ /* -+ * Pattern did not expand; append the finename component to -+ * the completed list -+ */ -+ if ((cp2 = strrchr(cp, '/')) != NULL) -+ *cp2++ = '\0'; -+ else -+ cp2 = cp; -+ if (append(xstrdup(cp2), &done, &ndone) != 0) { -+ free(cp); -+ goto fail; -+ } -+ free(cp); -+ } -+ /* success */ -+ *patternsp = done; -+ *npatternsp = ndone; -+ done = NULL; -+ ndone = 0; -+ ret = 0; -+ fail: -+ for (i = 0; i < nactive; i++) -+ free(active[i]); -+ free(active); -+ for (i = 0; i < ndone; i++) -+ free(done[i]); -+ free(done); -+ return ret; -+} -+ - void - toremote(int argc, char **argv) - { -@@ -993,7 +1240,8 @@ sink(int argc, char **argv, const char *src) - unsigned long long ull; - int setimes, targisdir, wrerrno = 0; - char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048]; -- char *src_copy = NULL, *restrict_pattern = NULL; -+ char **patterns = NULL; -+ size_t n, npatterns = 0; - struct timeval tv[2]; - - #define atime tv[0] -@@ -1023,16 +1271,13 @@ sink(int argc, char **argv, const char *src) - * Prepare to try to restrict incoming filenames to match - * the requested destination file glob. - */ -- if ((src_copy = strdup(src)) == NULL) -- fatal("strdup failed"); -- if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) { -- *restrict_pattern++ = '\0'; -- } -+ if (brace_expand(src, &patterns, &npatterns) != 0) -+ fatal("%s: could not expand pattern", __func__); - } - for (first = 1;; first = 0) { - cp = buf; - if (atomicio(read, remin, cp, 1) != 1) -- return; -+ goto done; - if (*cp++ == '\n') - SCREWUP("unexpected "); - do { -@@ -1058,7 +1303,7 @@ sink(int argc, char **argv, const char *src) - } - if (buf[0] == 'E') { - (void) atomicio(vwrite, remout, "", 1); -- return; -+ goto done; - } - if (ch == '\n') - *--cp = 0; -@@ -1133,9 +1378,14 @@ sink(int argc, char **argv, const char *src) - run_err("error: unexpected filename: %s", cp); - exit(1); - } -- if (restrict_pattern != NULL && -- fnmatch(restrict_pattern, cp, 0) != 0) -- SCREWUP("filename does not match request"); -+ if (npatterns > 0) { -+ for (n = 0; n < npatterns; n++) { -+ if (fnmatch(patterns[n], cp, 0) == 0) -+ break; -+ } -+ if (n >= npatterns) -+ SCREWUP("filename does not match request"); -+ } - if (targisdir) { - static char *namebuf; - static size_t cursize; -@@ -1294,7 +1544,15 @@ bad: run_err("%s: %s", np, strerror(errno)); - break; - } - } -+done: -+ for (n = 0; n < npatterns; n++) -+ free(patterns[n]); -+ free(patterns); -+ return; - screwup: -+ for (n = 0; n < npatterns; n++) -+ free(patterns[n]); -+ free(patterns); - run_err("protocol error: %s", why); - exit(1); - } diff --git a/Cygwin-Change-service-name-to-cygsshd.patch b/Cygwin-Change-service-name-to-cygsshd.patch deleted file mode 100644 index ab884535d55df2542f9c020557d5945bd8674a64..0000000000000000000000000000000000000000 --- a/Cygwin-Change-service-name-to-cygsshd.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 89843de0c4c733501f6b4f988098e6e06963df37 Mon Sep 17 00:00:00 2001 -From: Corinna Vinschen -Date: Sat, 26 Jan 2019 23:03:12 +0100 -Subject: [PATCH 276/294] Cygwin: Change service name to cygsshd - -Microsoft hijacked the sshd service name without asking. ---- - contrib/cygwin/ssh-host-config | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/contrib/cygwin/ssh-host-config b/contrib/cygwin/ssh-host-config -index 2903125..52916d1 100644 ---- a/contrib/cygwin/ssh-host-config -+++ b/contrib/cygwin/ssh-host-config -@@ -61,7 +61,7 @@ LOCALSTATEDIR=/var - - sshd_config_configured=no - port_number=22 --service_name=sshd -+service_name=cygsshd - strictmodes=yes - cygwin_value="" - user_account= --- -1.8.3.1 - diff --git a/DJM-GPG-KEY.gpg b/DJM-GPG-KEY.gpg deleted file mode 100644 index 8e733eba655a32064e5e514b3a36ef43132d0ae4..0000000000000000000000000000000000000000 Binary files a/DJM-GPG-KEY.gpg and /dev/null differ diff --git a/Initial-len-for-the-fmt-NULL-case.patch b/Initial-len-for-the-fmt-NULL-case.patch deleted file mode 100644 index 6ff132d9f253297ce8dc202e46f1ce2ebb439a8f..0000000000000000000000000000000000000000 --- a/Initial-len-for-the-fmt-NULL-case.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 039bf2a81797b8f3af6058d34005a4896a363221 Mon Sep 17 00:00:00 2001 -From: Darren Tucker -Date: Fri, 7 Sep 2018 14:06:57 +1000 -Subject: [PATCH 003/294] Initial len for the fmt=NULL case. - -Patch from jjelen at redhat via bz#2687. (OpenSSH never calls -setproctitle with a null format so len is always initialized). ---- - openbsd-compat/setproctitle.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/openbsd-compat/setproctitle.c b/openbsd-compat/setproctitle.c -index 2b15c6e..dbd1a95 100644 ---- a/openbsd-compat/setproctitle.c -+++ b/openbsd-compat/setproctitle.c -@@ -125,7 +125,7 @@ setproctitle(const char *fmt, ...) - #if SPT_TYPE != SPT_NONE - va_list ap; - char buf[1024], ptitle[1024]; -- size_t len; -+ size_t len = 0; - int r; - extern char *__progname; - #if SPT_TYPE == SPT_PSTAT --- -1.8.3.1 - diff --git a/Move-RANDOM_SEED_SIZE-outside-ifdef.patch b/Move-RANDOM_SEED_SIZE-outside-ifdef.patch deleted file mode 100644 index 9f75f180d2ed82e52a98b35af54ec7848d03e4b7..0000000000000000000000000000000000000000 --- a/Move-RANDOM_SEED_SIZE-outside-ifdef.patch +++ /dev/null @@ -1,36 +0,0 @@ -From c721d5877509875c8515df0215fa1dab862013bc Mon Sep 17 00:00:00 2001 -From: Darren Tucker -Date: Fri, 23 Nov 2018 14:11:20 +1100 -Subject: [PATCH 127/294] Move RANDOM_SEED_SIZE outside ifdef. - -RANDOM_SEED_SIZE is used by both the OpenSSL and non-OpenSSL code -This fixes the build with configureed --without-openssl. ---- - entropy.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/entropy.c b/entropy.c -index 1e3f265..b04ef3f 100644 ---- a/entropy.c -+++ b/entropy.c -@@ -24,6 +24,8 @@ - - #include "includes.h" - -+#define RANDOM_SEED_SIZE 48 -+ - #ifdef WITH_OPENSSL - - #include -@@ -64,8 +66,6 @@ - */ - #ifndef OPENSSL_PRNG_ONLY - --#define RANDOM_SEED_SIZE 48 -- - /* - * Collect 'len' bytes of entropy into 'buf' from PRNGD/EGD daemon - * listening either on 'tcp_port', or via Unix domain socket at * --- -1.8.3.1 - diff --git a/bugfix-CVE-2018-15919.patch b/bugfix-CVE-2018-15919.patch deleted file mode 100644 index 13172f28c8f2371285e2adb23bc35b3d4229cb34..0000000000000000000000000000000000000000 --- a/bugfix-CVE-2018-15919.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 1a3f3190a287cc24fe2b7a47f420d03fba76b353 Mon Sep 17 00:00:00 2001 -From: majun -Date: Wed, 18 Mar 2020 19:23:15 +0800 -Subject: [PATCH] CVE-2018-15919 - ---- - auth.h | 1 + - auth2-gss.c | 1 + - auth2.c | 4 ++++ - 3 files changed, 6 insertions(+) - -diff --git a/auth.h b/auth.h -index 1d9cf66..51b27c7 100644 ---- a/auth.h -+++ b/auth.h -@@ -60,6 +60,7 @@ struct Authctxt { - int attempt; - int failures; - int server_caused_failure; -+ int server_caused_gssapi_failure; - int force_pwchange; - char *user; /* username sent by the client */ - char *service; -diff --git a/auth2-gss.c b/auth2-gss.c -index 764d509..9690f8a 100644 ---- a/auth2-gss.c -+++ b/auth2-gss.c -@@ -153,6 +153,7 @@ userauth_gssapi(struct ssh *ssh) - ssh_gssapi_delete_ctx(&ctxt); - free(doid); - authctxt->server_caused_failure = 1; -+ authctxt->server_caused_gssapi_failure = 1; - return (0); - } - -diff --git a/auth2.c b/auth2.c -index f0b61ce..14db54a 100644 ---- a/auth2.c -+++ b/auth2.c -@@ -336,6 +336,7 @@ if (options.check_user_splash) - auth2_authctxt_reset_info(authctxt); - authctxt->postponed = 0; - authctxt->server_caused_failure = 0; -+ authctxt->server_caused_gssapi_failure = 0; - - /* try to authenticate user */ - m = authmethod_lookup(authctxt, method); -@@ -427,6 +428,9 @@ userauth_finish(struct ssh *ssh, int authenticated, const char *method, - if (!partial && !authctxt->server_caused_failure && - (authctxt->attempt > 1 || strcmp(method, "none") != 0)) - authctxt->failures++; -+ if (!partial && authctxt->server_caused_gssapi_failure && -+ (authctxt->attempt > 1 || strcmp(method, "none") != 0)) -+ authctxt->failures++; - if (authctxt->failures >= options.max_authtries) { - #ifdef SSH_AUDIT_EVENTS - PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); --- -1.8.3.1 - diff --git a/bugfix-debug3-to-verbose-in-command.patch b/bugfix-debug3-to-verbose-in-command.patch new file mode 100644 index 0000000000000000000000000000000000000000..93403f537d20d9bc649fa835eb7f5255339e9dfb --- /dev/null +++ b/bugfix-debug3-to-verbose-in-command.patch @@ -0,0 +1,25 @@ +From ed070c21ae68170e1cead6f5be16482d4f73ae2b Mon Sep 17 00:00:00 2001 +From: m00525086 +Date: Thu, 5 Mar 2020 21:02:06 +0800 +Subject: [PATCH] d2v + +--- + monitor_wrap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/monitor_wrap.c b/monitor_wrap.c +index 7f5a8fa..6ebcda1 100644 +--- a/monitor_wrap.c ++++ b/monitor_wrap.c +@@ -928,7 +928,7 @@ mm_audit_run_command(const char *command) + int r; + int handle; + +- debug3("%s entering command %s", __func__, command); ++ verbose("%s entering command %s", __func__, command); + + if ((m = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); +-- +2.19.1 + diff --git a/bugfix-openssh-6.6p1-log-usepam-no.patch b/bugfix-openssh-6.6p1-log-usepam-no.patch index 4bc950906b089bdc986cf02d3b38acd21a0cdb63..4eeee2dc0cd663d8311c120d3adb41be021f5c11 100644 --- a/bugfix-openssh-6.6p1-log-usepam-no.patch +++ b/bugfix-openssh-6.6p1-log-usepam-no.patch @@ -1,6 +1,6 @@ -From 45b9c4762614db5bc14b855ccfc019951eebe42d Mon Sep 17 00:00:00 2001 +From 31883f21eff4265b68bb36f67b254adb524db6ae Mon Sep 17 00:00:00 2001 From: guoxiaoqi -Date: Mon, 10 Dec 2018 19:07:51 +0000 +Date: Thu, 16 Apr 2020 14:51:44 +0800 Subject: [PATCH] bugfix-openssh-6.6p1-log-usepam-no --- @@ -9,12 +9,12 @@ Subject: [PATCH] bugfix-openssh-6.6p1-log-usepam-no 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sshd.c b/sshd.c -index d6ac3e3..6f273b7 100644 +index c6c03ae..c291a5e 100644 --- a/sshd.c +++ b/sshd.c -@@ -1707,9 +1707,9 @@ main(int ac, char **av) +@@ -1812,9 +1812,9 @@ main(int ac, char **av) parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, - cfg, NULL); + cfg, &includes, NULL); - /* 'UsePAM no' is not supported in Fedora */ + /* 'UsePAM no' is not supported in openEuler */ @@ -22,21 +22,21 @@ index d6ac3e3..6f273b7 100644 - logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems."); + logit("WARNING: 'UsePAM no' is not supported in openEuler and may cause several problems."); - seed_rng(); - + /* Fill in default values for those options not explicitly set. */ + fill_default_server_options(&options); diff --git a/sshd_config b/sshd_config -index cc90a90..17b477c 100644 +index e125992..ebc28b3 100644 --- a/sshd_config +++ b/sshd_config -@@ -91,7 +91,7 @@ GSSAPICleanupCredentials no +@@ -87,7 +87,7 @@ AuthorizedKeysFile .ssh/authorized_keys # If you just want the PAM account and session checks to run without # PAM authentication, then enable this but set PasswordAuthentication # and ChallengeResponseAuthentication to 'no'. -# WARNING: 'UsePAM no' is not supported in Fedora and may cause several +# WARNING: 'UsePAM no' is not supported in openEuler and may cause several # problems. - UsePAM yes + #UsePAM no -- -1.8.3.1 +2.23.0 diff --git a/bugfix-openssh-add-option-check-username-splash.patch b/bugfix-openssh-add-option-check-username-splash.patch index 30f918b3261ed4e81824442cbb0b902b588b157a..c6c13290425499997aa99409da4ef4491cf8eb47 100644 --- a/bugfix-openssh-add-option-check-username-splash.patch +++ b/bugfix-openssh-add-option-check-username-splash.patch @@ -1,6 +1,6 @@ -From a28e7321bbb42cf6e8734a297c07dd9467662151 Mon Sep 17 00:00:00 2001 +From 74c1a37dfeab8e9cc39e5bc76891d1d9d66b7638 Mon Sep 17 00:00:00 2001 From: wangqiang -Date: Thu, 9 Aug 2018 14:27:55 +0800 +Date: Thu, 16 Apr 2020 15:58:30 +0800 Subject: [PATCH] openssh: add option check username splash add a check to inhibit username contains splash @@ -8,17 +8,17 @@ add an option 'CheckUserSplash' so that user can turn off this check --- - auth2.c | 3 +++ + auth2.c | 4 +++- servconf.c | 8 ++++++++ - servconf.h | 2 ++ + servconf.h | 1 + sshd_config | 2 ++ - 4 files changed, 15 insertions(+) + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/auth2.c b/auth2.c -index 6591a8b..be7f829 100644 +index 4adc502..956b9cf 100644 --- a/auth2.c +++ b/auth2.c -@@ -231,10 +231,13 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) +@@ -282,11 +282,13 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) debug("userauth-request for user %s service %s method %s", user, service, method); debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); @@ -28,15 +28,16 @@ index 6591a8b..be7f829 100644 if ((role = strchr(user, '/')) != NULL) *role++ = 0; #endif +- +} - if ((style = strchr(user, ':')) != NULL) *style++ = 0; + diff --git a/servconf.c b/servconf.c -index 08e5d70..85c9238 100644 +index 7001d56..76147f9 100644 --- a/servconf.c +++ b/servconf.c -@@ -185,6 +185,7 @@ +@@ -195,6 +195,7 @@ initialize_server_options(ServerOptions *options) options->ip_qos_interactive = -1; options->ip_qos_bulk = -1; options->version_addendum = NULL; @@ -44,64 +45,66 @@ index 08e5d70..85c9238 100644 options->fingerprint_hash = -1; options->disable_forwarding = -1; options->expose_userauth_info = -1; -@@ -425,6 +426,8 @@ +@@ -473,6 +474,8 @@ fill_default_server_options(ServerOptions *options) + options->ip_qos_bulk = IPTOS_DSCP_CS1; + if (options->version_addendum == NULL) options->version_addendum = xstrdup(""); - if (options->show_patchlevel == -1) - options->show_patchlevel = 0; + if (options->check_user_splash == -1) + options->check_user_splash = 1; if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) options->fwd_opts.streamlocal_bind_mask = 0177; if (options->fwd_opts.streamlocal_bind_unlink == -1) -@@ -522,6 +525,7 @@ +@@ -574,6 +577,7 @@ typedef enum { sStreamLocalBindMask, sStreamLocalBindUnlink, sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, - sExposeAuthInfo, sRDomain, + sExposeAuthInfo, sRDomain, sPubkeyAuthOptions, sSecurityKeyProvider, + sCheckUserSplash, sDeprecated, sIgnore, sUnsupported } ServerOpCodes; -@@ -684,6 +688,7 @@ +@@ -740,6 +744,7 @@ static struct { { "fingerprinthash", sFingerprintHash, SSHCFG_GLOBAL }, { "disableforwarding", sDisableForwarding, SSHCFG_ALL }, { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, + { "checkusersplash", sCheckUserSplash, SSHCFG_GLOBAL }, { "rdomain", sRDomain, SSHCFG_ALL }, - { NULL, sBadOption, 0 } - }; -@@ -1295,6 +1300,9 @@ + { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, + { "securitykeyprovider", sSecurityKeyProvider, SSHCFG_GLOBAL }, +@@ -1360,6 +1365,9 @@ process_server_config_line_depth(ServerOptions *options, char *line, case sUsePAM: intptr = &options->use_pam; goto parse_flag; + case sCheckUserSplash: -+ intptr = &options->check_user_splash; -+ goto parse_flag; ++ intptr = &options->check_user_splash; ++ goto parse_flag; /* Standard Options */ case sBadOption: diff --git a/servconf.h b/servconf.h -index 8318a74..be86374 100644 +index a3827e5..2c16b5a 100644 --- a/servconf.h +++ b/servconf.h -@@ -219,6 +219,8 @@ +@@ -226,6 +226,7 @@ typedef struct { int fingerprint_hash; int expose_userauth_info; u_int64_t timing_secret; -+ + int check_user_splash; /* check whether splash exists in username, if exist, disable login */ + char *sk_provider; } ServerOptions; - /* Information about the incoming connection as used by Match */ diff --git a/sshd_config b/sshd_config -index 6bbb86b..cc90a90 100644 +index ebc28b3..b121450 100644 --- a/sshd_config +++ b/sshd_config -@@ -137,3 +137,5 @@ Subsystem sftp /usr/libexec/sftp-server - # AllowTcpForwarding no +@@ -125,6 +125,8 @@ Subsystem sftp /usr/libexec/sftp-server # PermitTTY no # ForceCommand cvs server -+ + +#CheckUserSplash yes ++ + # To modify the system-wide ssh configuration, create a *.conf file under + # /etc/ssh/sshd_config.d/ which will be automatically included below + Include /etc/ssh/sshd_config.d/*.conf -- -1.8.3.1 +2.23.0 diff --git a/bugfix-supply-callback-to-PEM-read-bio-PrivateKey.patch b/bugfix-supply-callback-to-PEM-read-bio-PrivateKey.patch deleted file mode 100644 index cf46b2a16959a34c684c4c66148557a85442ded1..0000000000000000000000000000000000000000 --- a/bugfix-supply-callback-to-PEM-read-bio-PrivateKey.patch +++ /dev/null @@ -1,45 +0,0 @@ -OpenSSL 1.1.0i has changed the behaviour of their PEM APIs, -so that empty passphrases are interpreted differently. This -probabalistically breaks loading some keys, because the PEM format -is terrible and doesn't include a proper MAC. - -Avoid this by providing a basic callback to avoid passing empty -passphrases to OpenSSL in cases where one is required. ---- -diff --git a/sshkey.c b/sshkey.c -index 5807627..c973910 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -4063,6 +4063,20 @@ convert_libcrypto_error(void) - return translate_libcrypto_error(ERR_peek_last_error()); - } - -+static int -+pem_passphrase_cb(char *buf, int size, int rwflag, void *u) -+{ -+ char *p = (char *)u; -+ size_t len; -+ -+ if (p == NULL || (len = strlen(p)) == 0) -+ return -1; -+ if (size < 0 || len > (size_t)size) -+ return -1; -+ memcpy(buf, p, len); -+ return (int)len; -+} -+ - static int - sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, - const char *passphrase, struct sshkey **keyp) -@@ -4084,7 +4098,7 @@ sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type, - } - - clear_libcrypto_errors(); -- if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, -+ if ((pk = PEM_read_bio_PrivateKey(bio, NULL, pem_passphrase_cb, - (char *)passphrase)) == NULL) { - r = convert_libcrypto_error(); - goto out; - - - diff --git a/check-for-NULL-return-from-shadow_pw.patch b/check-for-NULL-return-from-shadow_pw.patch deleted file mode 100644 index 4389ecc8e3552fc6744e0d6f1bc6353f8aac836f..0000000000000000000000000000000000000000 --- a/check-for-NULL-return-from-shadow_pw.patch +++ /dev/null @@ -1,28 +0,0 @@ -From fe8e8f349a553ef4c567acd418aac769a82b7729 Mon Sep 17 00:00:00 2001 -From: Damien Miller -Date: Thu, 11 Oct 2018 11:03:15 +1100 -Subject: [PATCH 067/294] check for NULL return from shadow_pw() - -probably unreachable on this platform; pointed out by -coolbugcheckers AT gmail.com ---- - openbsd-compat/port-uw.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/openbsd-compat/port-uw.c b/openbsd-compat/port-uw.c -index 9edb1b4..1322131 100644 ---- a/openbsd-compat/port-uw.c -+++ b/openbsd-compat/port-uw.c -@@ -60,6 +60,9 @@ sys_auth_passwd(struct ssh *ssh, const char *password) - /* Just use the supplied fake password if authctxt is invalid */ - char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; - -+ if (pw_password == NULL) -+ return 0; -+ - /* Check for users with no password. */ - if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) - return (1); --- -1.8.3.1 - diff --git a/check-pw_passwd-NULL-here-too.patch b/check-pw_passwd-NULL-here-too.patch deleted file mode 100644 index 8833adac1acabc0ed7cb71658cd2a0fbb6876fc1..0000000000000000000000000000000000000000 --- a/check-pw_passwd-NULL-here-too.patch +++ /dev/null @@ -1,29 +0,0 @@ -From c29b111e7d87c2324ff71c80653dd8da168c13b9 Mon Sep 17 00:00:00 2001 -From: Damien Miller -Date: Thu, 11 Oct 2018 11:29:35 +1100 -Subject: [PATCH 068/294] check pw_passwd != NULL here too - -Again, for systems with broken NIS implementations. - -Prompted by coolbugcheckers AT gmail.com ---- - auth-passwd.c | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/auth-passwd.c b/auth-passwd.c -index 65f5251..24fcb67 100644 ---- a/auth-passwd.c -+++ b/auth-passwd.c -@@ -198,6 +198,9 @@ sys_auth_passwd(struct ssh *ssh, const char *password) - /* Just use the supplied fake password if authctxt is invalid */ - char *pw_password = authctxt->valid ? shadow_pw(pw) : pw->pw_passwd; - -+ if (pw_password == NULL) -+ return 0; -+ - /* Check for users with no password. */ - if (strcmp(pw_password, "") == 0 && strcmp(password, "") == 0) - return (1); --- -1.8.3.1 - diff --git a/delete-the-correct-thing-kexfuzz-binary.patch b/delete-the-correct-thing-kexfuzz-binary.patch deleted file mode 100644 index d06d754687b40d424acc30e350ca2714e7befc80..0000000000000000000000000000000000000000 --- a/delete-the-correct-thing-kexfuzz-binary.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 41c115a5ea1cb79a6a3182773c58a23f760e8076 Mon Sep 17 00:00:00 2001 -From: Damien Miller -Date: Wed, 12 Sep 2018 16:50:01 +1000 -Subject: [PATCH 016/294] delete the correct thing; kexfuzz binary - ---- - Makefile.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/Makefile.in b/Makefile.in -index d3cffc5..46562ad 100644 ---- a/Makefile.in -+++ b/Makefile.in -@@ -306,7 +306,7 @@ distclean: regressclean - rm -f regress/unittests/pkcs11/*.o - rm -f regress/unittests/pkcs11/test_pkcs11 - rm -f regress/misc/kexfuzz/*.o -- rm -f regress/misc/kexfuzz -+ rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) - (cd openbsd-compat && $(MAKE) distclean) - if test -d pkg ; then \ - rm -fr pkg ; \ --- -1.8.3.1 - diff --git a/feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch b/feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch index cbe4c8c6623ca6a0fcc807f41a73d802b8e5ec89..47e67b34d79947d1ee1158d9f4bbdf55d4fbace6 100644 --- a/feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch +++ b/feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch @@ -1,16 +1,16 @@ -From 5e7d567d7c7f61d4ee4f2cb2d56b33fadafd980c Mon Sep 17 00:00:00 2001 +From 6d98c61e18fe65a52e21df9cece74675f9c18125 Mon Sep 17 00:00:00 2001 From: s00467541 -Date: Tue, 12 Feb 2019 19:40:42 +0800 +Date: Thu, 16 Apr 2020 17:13:24 +0800 Subject: [PATCH] sync patch, add new judgement and delete default sftp-put-check.cfg Signed-off-by: s00467541 --- - sftp-server.c | 699 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 688 insertions(+), 11 deletions(-) + sftp-server.c | 702 +++++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 691 insertions(+), 11 deletions(-) diff --git a/sftp-server.c b/sftp-server.c -index 3fbc1f8..fd42be9 100644 +index 01d6f8f..682c19a 100644 --- a/sftp-server.c +++ b/sftp-server.c @@ -29,6 +29,12 @@ @@ -41,10 +41,10 @@ index 3fbc1f8..fd42be9 100644 +static int cflag = 0; +/*add for oom end*/ + - /* Our verbosity */ - static LogLevel log_level = SYSLOG_LEVEL_ERROR; + char *sftp_realpath(const char *, char *); /* sftp-realpath.c */ -@@ -87,6 +104,452 @@ struct Stat { + /* Our verbosity */ +@@ -89,6 +106,452 @@ struct Stat { Attrib attrib; }; @@ -497,7 +497,7 @@ index 3fbc1f8..fd42be9 100644 /* Packet handlers */ static void process_open(u_int32_t id); static void process_close(u_int32_t id); -@@ -689,6 +1148,15 @@ process_open(u_int32_t id) +@@ -695,6 +1158,15 @@ process_open(u_int32_t id) (r = sshbuf_get_u32(iqueue, &pflags)) != 0 || /* portable flags */ (r = decode_attrib(iqueue, &a)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -513,7 +513,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: open flags %d", id, pflags); flags = flags_from_portable(pflags); -@@ -722,6 +1190,8 @@ process_open(u_int32_t id) +@@ -728,6 +1200,8 @@ process_open(u_int32_t id) (void) umask(old_umask); /* restore umask to something sane */ if (status != SSH2_FX_OK) send_status(id, status); @@ -522,7 +522,7 @@ index 3fbc1f8..fd42be9 100644 free(name); } -@@ -753,6 +1223,17 @@ process_read(u_int32_t id) +@@ -759,6 +1233,17 @@ process_read(u_int32_t id) (r = sshbuf_get_u32(iqueue, &len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -540,7 +540,7 @@ index 3fbc1f8..fd42be9 100644 debug("request %u: read \"%s\" (handle %d) off %llu len %d", id, handle_to_name(handle), handle, (unsigned long long)off, len); if (len > sizeof buf) { -@@ -794,6 +1275,18 @@ process_write(u_int32_t id) +@@ -800,6 +1285,18 @@ process_write(u_int32_t id) (r = sshbuf_get_string(iqueue, &data, &len)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -559,12 +559,12 @@ index 3fbc1f8..fd42be9 100644 debug("request %u: write \"%s\" (handle %d) off %llu len %zu", id, handle_to_name(handle), handle, (unsigned long long)off, len); fd = handle_to_fd(handle); -@@ -807,16 +1299,30 @@ process_write(u_int32_t id) +@@ -813,16 +1310,30 @@ process_write(u_int32_t id) error("process_write: seek failed"); } else { /* XXX ATOMICIO ? */ - ret = write(fd, data, len); -- if (ret < 0) { +- if (ret == -1) { - error("process_write: write failed"); - status = errno_to_portable(errno); - } else if ((size_t)ret == len) { @@ -572,34 +572,34 @@ index 3fbc1f8..fd42be9 100644 - handle_update_write(handle, ret); - } else { - debug2("nothing at all written"); -+ /* add begin sftp oom fix */ -+ if (storage_flag == 1) -+ debug("cflag is %d",cflag); -+ if (!check_before_write(handle_to_name(handle), off)){ -+ error("check file size and free mem info before write failed"); -+ unlink(handle_to_name(handle)); ++ /* add begin sftp oom fix */ ++ if (storage_flag == 1) ++ debug("cflag is %d",cflag); ++ if (!check_before_write(handle_to_name(handle), off)){ ++ error("check file size and free mem info before write failed"); ++ unlink(handle_to_name(handle)); status = SSH2_FX_FAILURE; -+ send_status(id, status); -+ free(data); -+ sftp_server_cleanup_exit(1); -+ /* add end sftp oom fix */ -+ } else { -+ -+ ret = write(fd, data, len); -+ if (ret < 0) { -+ error("process_write: write failed"); -+ status = errno_to_portable(errno); -+ } else if ((size_t)ret == len) { -+ status = SSH2_FX_OK; -+ handle_update_write(handle, ret); -+ } else { -+ debug2("nothing at all written"); -+ status = SSH2_FX_FAILURE; -+ } ++ send_status(id, status); ++ free(data); ++ sftp_server_cleanup_exit(1); ++ /* add end sftp oom fix */ ++ } else { ++ ++ ret = write(fd, data, len); ++ if (ret < 0) { ++ error("process_write: write failed"); ++ status = errno_to_portable(errno); ++ } else if ((size_t)ret == len) { ++ status = SSH2_FX_OK; ++ handle_update_write(handle, ret); ++ } else { ++ debug2("nothing at all written"); ++ status = SSH2_FX_FAILURE; ++ } } } } -@@ -835,6 +1341,16 @@ process_do_stat(u_int32_t id, int do_lstat) +@@ -841,6 +1352,16 @@ process_do_stat(u_int32_t id, int do_lstat) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -616,7 +616,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: %sstat", id, do_lstat ? "l" : ""); verbose("%sstat name \"%s\"", do_lstat ? "l" : "", name); r = do_lstat ? lstat(name, &st) : stat(name, &st); -@@ -871,6 +1387,16 @@ process_fstat(u_int32_t id) +@@ -877,6 +1398,16 @@ process_fstat(u_int32_t id) if ((r = get_handle(iqueue, &handle)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -633,7 +633,7 @@ index 3fbc1f8..fd42be9 100644 debug("request %u: fstat \"%s\" (handle %u)", id, handle_to_name(handle), handle); fd = handle_to_fd(handle); -@@ -911,6 +1437,14 @@ process_setstat(u_int32_t id) +@@ -929,6 +1460,14 @@ process_setstat(u_int32_t id) (r = decode_attrib(iqueue, &a)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -648,7 +648,7 @@ index 3fbc1f8..fd42be9 100644 debug("request %u: setstat name \"%s\"", id, name); if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", -@@ -965,6 +1499,13 @@ process_fsetstat(u_int32_t id) +@@ -983,6 +1522,13 @@ process_fsetstat(u_int32_t id) else { char *name = handle_to_name(handle); @@ -662,7 +662,7 @@ index 3fbc1f8..fd42be9 100644 if (a.flags & SSH2_FILEXFER_ATTR_SIZE) { logit("set \"%s\" size %llu", name, (unsigned long long)a.size); -@@ -1022,6 +1563,14 @@ process_opendir(u_int32_t id) +@@ -1040,6 +1586,14 @@ process_opendir(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -677,20 +677,18 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: opendir", id); logit("opendir \"%s\"", path); dirp = opendir(path); -@@ -1076,6 +1625,12 @@ process_readdir(u_int32_t id) +@@ -1094,6 +1648,10 @@ process_readdir(u_int32_t id) strcmp(path, "/") ? "/" : "", dp->d_name); - if (lstat(pathname, &st) < 0) + if (lstat(pathname, &st) == -1) continue; -+ + if (RETURN_OK != path_permition_check(pathname,FLAG_PERMITOP)) -+ { -+ continue; -+ } -+ ++ { ++ continue; ++ } stat_to_attrib(&st, &(stats[count].attrib)); stats[count].name = xstrdup(dp->d_name); stats[count].long_name = ls_file(dp->d_name, &st, 0, 0); -@@ -1107,6 +1662,14 @@ process_remove(u_int32_t id) +@@ -1125,6 +1683,14 @@ process_remove(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -705,7 +703,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: remove", id); logit("remove name \"%s\"", name); r = unlink(name); -@@ -1126,6 +1689,14 @@ process_mkdir(u_int32_t id) +@@ -1144,6 +1710,14 @@ process_mkdir(u_int32_t id) (r = decode_attrib(iqueue, &a)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -720,7 +718,7 @@ index 3fbc1f8..fd42be9 100644 mode = (a.flags & SSH2_FILEXFER_ATTR_PERMISSIONS) ? a.perm & 07777 : 0777; debug3("request %u: mkdir", id); -@@ -1145,6 +1716,14 @@ process_rmdir(u_int32_t id) +@@ -1163,6 +1737,14 @@ process_rmdir(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -735,13 +733,13 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: rmdir", id); logit("rmdir name \"%s\"", name); r = rmdir(name); -@@ -1169,8 +1748,12 @@ process_realpath(u_int32_t id) +@@ -1187,8 +1769,12 @@ process_realpath(u_int32_t id) } debug3("request %u: realpath", id); verbose("realpath \"%s\"", path); -- if (realpath(path, resolvedname) == NULL) { +- if (sftp_realpath(path, resolvedname) == NULL) { - send_status(id, errno_to_portable(errno)); -+ if ((realpath(path, resolvedname) == NULL) ++ if ((sftp_realpath(path, resolvedname) == NULL) + || (RETURN_OK != path_permition_check(resolvedname,FLAG_PERMITOP))) { + if (storage_flag != 1) + send_status(id, errno_to_portable(errno)); @@ -750,7 +748,7 @@ index 3fbc1f8..fd42be9 100644 } else { Stat s; attrib_clear(&s.attrib); -@@ -1191,6 +1774,16 @@ process_rename(u_int32_t id) +@@ -1209,6 +1795,16 @@ process_rename(u_int32_t id) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -767,7 +765,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: rename", id); logit("rename old \"%s\" new \"%s\"", oldpath, newpath); status = SSH2_FX_FAILURE; -@@ -1250,6 +1843,14 @@ process_readlink(u_int32_t id) +@@ -1268,6 +1864,14 @@ process_readlink(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -782,7 +780,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: readlink", id); verbose("readlink \"%s\"", path); if ((len = readlink(path, buf, sizeof(buf) - 1)) == -1) -@@ -1275,6 +1876,16 @@ process_symlink(u_int32_t id) +@@ -1293,6 +1897,16 @@ process_symlink(u_int32_t id) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -799,7 +797,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: symlink", id); logit("symlink old \"%s\" new \"%s\"", oldpath, newpath); /* this will fail if 'newpath' exists */ -@@ -1295,6 +1906,16 @@ process_extended_posix_rename(u_int32_t id) +@@ -1313,6 +1927,16 @@ process_extended_posix_rename(u_int32_t id) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -816,7 +814,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: posix-rename", id); logit("posix-rename old \"%s\" new \"%s\"", oldpath, newpath); r = rename(oldpath, newpath); -@@ -1313,6 +1934,15 @@ process_extended_statvfs(u_int32_t id) +@@ -1331,6 +1955,15 @@ process_extended_statvfs(u_int32_t id) if ((r = sshbuf_get_cstring(iqueue, &path, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -832,7 +830,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: statvfs", id); logit("statvfs \"%s\"", path); -@@ -1331,6 +1961,17 @@ process_extended_fstatvfs(u_int32_t id) +@@ -1349,6 +1982,17 @@ process_extended_fstatvfs(u_int32_t id) if ((r = get_handle(iqueue, &handle)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -850,7 +848,7 @@ index 3fbc1f8..fd42be9 100644 debug("request %u: fstatvfs \"%s\" (handle %u)", id, handle_to_name(handle), handle); if ((fd = handle_to_fd(handle)) < 0) { -@@ -1353,6 +1994,15 @@ process_extended_hardlink(u_int32_t id) +@@ -1371,6 +2015,15 @@ process_extended_hardlink(u_int32_t id) (r = sshbuf_get_cstring(iqueue, &newpath, NULL)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -866,7 +864,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: hardlink", id); logit("hardlink old \"%s\" new \"%s\"", oldpath, newpath); r = link(oldpath, newpath); -@@ -1369,6 +2019,17 @@ process_extended_fsync(u_int32_t id) +@@ -1387,6 +2040,17 @@ process_extended_fsync(u_int32_t id) if ((r = get_handle(iqueue, &handle)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -884,7 +882,7 @@ index 3fbc1f8..fd42be9 100644 debug3("request %u: fsync (handle %u)", id, handle); verbose("fsync \"%s\"", handle_to_name(handle)); if ((fd = handle_to_fd(handle)) < 0) -@@ -1606,6 +2267,22 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle +@@ -1672,6 +2336,22 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw, int reset_handle log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler); @@ -908,4 +906,5 @@ index 3fbc1f8..fd42be9 100644 * On platforms where we can, avoid making /proc/self/{mem,maps} * available to the user so that sftp access doesn't automatically -- -1.8.3.1 +2.23.0 + diff --git a/in-pick_salt-avoid-dereference-of-NULL-passwords.patch b/in-pick_salt-avoid-dereference-of-NULL-passwords.patch deleted file mode 100644 index 829ad6cdbd056a0424d7a22203b2e05c6ac0070d..0000000000000000000000000000000000000000 --- a/in-pick_salt-avoid-dereference-of-NULL-passwords.patch +++ /dev/null @@ -1,30 +0,0 @@ -From d1d301a1dd5d6cc3a9ed93ab7ab09dda4cb456e0 Mon Sep 17 00:00:00 2001 -From: Damien Miller -Date: Wed, 10 Oct 2018 14:57:00 +1100 -Subject: [PATCH 064/294] in pick_salt() avoid dereference of NULL passwords - -Apparently some NIS implementations can leave pw->pw_passwd (or the -shadow equivalent) NULL. - -bz#2909; based on patch from Todd Eigenschink ---- - openbsd-compat/xcrypt.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/openbsd-compat/xcrypt.c b/openbsd-compat/xcrypt.c -index c9c6283..360b187 100644 ---- a/openbsd-compat/xcrypt.c -+++ b/openbsd-compat/xcrypt.c -@@ -82,7 +82,8 @@ pick_salt(void) - strlcpy(salt, "xx", sizeof(salt)); - setpwent(); - while ((pw = getpwent()) != NULL) { -- passwd = shadow_pw(pw); -+ if ((passwd = shadow_pw(pw)) == NULL) -+ continue; - if (passwd[0] == '$' && (p = strrchr(passwd+1, '$')) != NULL) { - typelen = p - passwd + 1; - strlcpy(salt, passwd, MIN(typelen, sizeof(salt))); --- -1.8.3.1 - diff --git a/openssh-5.1p1-askpass-progress.patch b/openssh-5.1p1-askpass-progress.patch index 6601fbf276f804d855f1f55e4cbed653f8f053f4..21f6502390f93801bdca3f1e21730de0d8b18282 100644 --- a/openssh-5.1p1-askpass-progress.patch +++ b/openssh-5.1p1-askpass-progress.patch @@ -9,7 +9,7 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr #include #include -@@ -81,13 +82,24 @@ ok_dialog(GtkWidget *entry, gpointer dia +@@ -81,14 +82,25 @@ ok_dialog(GtkWidget *entry, gpointer dia gtk_dialog_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); } @@ -25,57 +25,54 @@ diff -up openssh-7.4p1/contrib/gnome-ssh-askpass2.c.progress openssh-7.4p1/contr +} + static int - passphrase_dialog(char *message) + passphrase_dialog(char *message, int prompt_type) { const char *failed; char *passphrase, *local; int result, grab_tries, grab_server, grab_pointer; + int buttons, default_response; - GtkWidget *parent_window, *dialog, *entry; + GtkWidget *parent_window, *dialog, *entry, *progress, *hbox; GdkGrabStatus status; grab_server = (getenv("GNOME_SSH_ASKPASS_GRAB_SERVER") != NULL); -@@ -104,14 +116,32 @@ passphrase_dialog(char *message) - "%s", - message); +@@ -104,16 +116,37 @@ passphrase_dialog(char *message) + gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); -+ hbox = gtk_hbox_new(FALSE, 0); -+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, -+ FALSE, 0); -+ gtk_widget_show(hbox); + if (prompt_type == PROMPT_ENTRY) { ++ hbox = gtk_hbox_new(FALSE, 0); ++ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, ++ FALSE, 0); ++ gtk_widget_show(hbox); + - entry = gtk_entry_new(); - gtk_box_pack_start( -- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), entry, -- FALSE, FALSE, 0); -+ GTK_BOX(hbox), entry, -+ TRUE, FALSE, 0); -+ gtk_entry_set_width_chars(GTK_ENTRY(entry), 2); - gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); - gtk_widget_grab_focus(entry); - gtk_widget_show(entry); - -+ hbox = gtk_hbox_new(FALSE, 0); -+ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, + entry = gtk_entry_new(); + gtk_box_pack_start( +- GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), +- entry, FALSE, FALSE, 0); ++ GTK_BOX(hbox), entry, ++ TRUE, FALSE, 0); ++ gtk_entry_set_width_chars(GTK_ENTRY(entry), 2); + gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); + gtk_widget_grab_focus(entry); + gtk_widget_show(entry); + /* Make close dialog */ + g_signal_connect(G_OBJECT(entry), "activate", + G_CALLBACK(ok_dialog), dialog); ++ ++ hbox = gtk_hbox_new(FALSE, 0); ++ gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), hbox, FALSE, + FALSE, 8); -+ gtk_widget_show(hbox); ++ gtk_widget_show(hbox); + -+ progress = gtk_progress_bar_new(); -+ -+ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "Passphrase length hidden intentionally"); -+ gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE, -+ TRUE, 5); -+ gtk_widget_show(progress); ++ progress = gtk_progress_bar_new(); + - gtk_window_set_title(GTK_WINDOW(dialog), "OpenSSH"); - gtk_window_set_position (GTK_WINDOW(dialog), GTK_WIN_POS_CENTER); - gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); -@@ -120,6 +150,8 @@ passphrase_dialog(char *message) - gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - g_signal_connect(G_OBJECT(entry), "activate", - G_CALLBACK(ok_dialog), dialog); -+ g_signal_connect(G_OBJECT(entry), "changed", -+ G_CALLBACK(move_progress), progress); - - gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); ++ gtk_progress_bar_set_text(GTK_PROGRESS_BAR(progress), "Passphrase length hidden intentionally"); ++ gtk_box_pack_start(GTK_BOX(hbox), progress, TRUE, ++ TRUE, 5); ++ gtk_widget_show(progress); ++ g_signal_connect(G_OBJECT(entry), "changed", ++ G_CALLBACK(move_progress), progress); ++ + } + /* Grab focus */ diff --git a/openssh-5.9p1-wIm.patch b/openssh-5.9p1-wIm.patch deleted file mode 100644 index a00046a2f21245b50e68d254ce308669b1c76036..0000000000000000000000000000000000000000 --- a/openssh-5.9p1-wIm.patch +++ /dev/null @@ -1,78 +0,0 @@ -diff -up openssh-5.9p1/Makefile.in.wIm openssh-5.9p1/Makefile.in ---- openssh-5.9p1/Makefile.in.wIm 2011-08-05 22:15:18.000000000 +0200 -+++ openssh-5.9p1/Makefile.in 2011-09-12 16:24:18.643674014 +0200 -@@ -66,7 +66,7 @@ LIBSSH_OBJS=acss.o authfd.o authfile.o b - cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ - compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \ - log.o match.o md-sha256.o moduli.o nchan.o packet.o \ -- readpass.o rsa.o ttymodes.o xmalloc.o addrmatch.o \ -+ readpass.o rsa.o ttymodes.o whereIam.o xmalloc.o addrmatch.o \ - atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ - kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ -diff -up openssh-5.9p1/log.h.wIm openssh-5.9p1/log.h ---- openssh-5.9p1/log.h.wIm 2011-06-20 06:42:23.000000000 +0200 -+++ openssh-5.9p1/log.h 2011-09-12 16:34:52.984674326 +0200 -@@ -65,6 +65,8 @@ void verbose(const char *, ...) __at - void debug(const char *, ...) __attribute__((format(printf, 1, 2))); - void debug2(const char *, ...) __attribute__((format(printf, 1, 2))); - void debug3(const char *, ...) __attribute__((format(printf, 1, 2))); -+void _debug_wIm_body(const char *, int, const char *, const char *, int); -+#define debug_wIm(a,b) _debug_wIm_body(a,b,__func__,__FILE__,__LINE__) - - - void set_log_handler(log_handler_fn *, void *); -diff -up openssh-5.9p1/sshd.c.wIm openssh-5.9p1/sshd.c ---- openssh-5.9p1/sshd.c.wIm 2011-06-23 11:45:51.000000000 +0200 -+++ openssh-5.9p1/sshd.c 2011-09-12 16:38:35.787816490 +0200 -@@ -140,6 +140,9 @@ int deny_severity; - - extern char *__progname; - -+/* trace of fork processes */ -+extern int whereIam; -+ - /* Server configuration options. */ - ServerOptions options; - -@@ -666,6 +669,7 @@ privsep_preauth(Authctxt *authctxt) - return 1; - } else { - /* child */ -+ whereIam = 1; - close(pmonitor->m_sendfd); - close(pmonitor->m_log_recvfd); - -@@ -715,6 +719,7 @@ privsep_postauth(Authctxt *authctxt) - - /* child */ - -+ whereIam = 2; - close(pmonitor->m_sendfd); - pmonitor->m_sendfd = -1; - -@@ -1325,6 +1330,8 @@ main(int ac, char **av) - Key *key; - Authctxt *authctxt; - -+ whereIam = 0; -+ - #ifdef HAVE_SECUREWARE - (void)set_auth_parameters(ac, av); - #endif -diff -up openssh-5.9p1/whereIam.c.wIm openssh-5.9p1/whereIam.c ---- openssh-5.9p1/whereIam.c.wIm 2011-09-12 16:24:18.722674167 +0200 -+++ openssh-5.9p1/whereIam.c 2011-09-12 16:24:18.724674418 +0200 -@@ -0,0 +1,12 @@ -+ -+int whereIam = -1; -+ -+void _debug_wIm_body(const char *txt, int val, const char *func, const char *file, int line) -+{ -+ if (txt) -+ debug("%s=%d, %s(%s:%d) wIm = %d, uid=%d, euid=%d", txt, val, func, file, line, whereIam, getuid(), geteuid()); -+ else -+ debug("%s(%s:%d) wIm = %d, uid=%d, euid=%d", func, file, line, whereIam, getuid(), geteuid()); -+} -+ -+ diff --git a/openssh-6.1p1-gssapi-canohost.patch b/openssh-6.1p1-gssapi-canohost.patch deleted file mode 100644 index 3e6c9ccc8823acbec6adf1634a48ee00d878b0d3..0000000000000000000000000000000000000000 --- a/openssh-6.1p1-gssapi-canohost.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up openssh-6.1p1/sshconnect2.c.canohost openssh-6.1p1/sshconnect2.c ---- openssh-6.1p1/sshconnect2.c.canohost 2012-10-30 10:52:59.593301692 +0100 -+++ openssh-6.1p1/sshconnect2.c 2012-10-30 11:01:12.870301632 +0100 -@@ -699,12 +699,15 @@ userauth_gssapi(Authctxt *authctxt) - static u_int mech = 0; - OM_uint32 min; - int r, ok = 0; -- const char *gss_host; -+ const char *gss_host = NULL; - - if (options.gss_server_identity) - gss_host = options.gss_server_identity; -- else if (options.gss_trust_dns) -+ else if (options.gss_trust_dns) { - gss_host = get_canonical_hostname(active_state, 1); -+ if (strcmp(gss_host, "UNKNOWN") == 0) -+ gss_host = authctxt->host; -+ } - else - gss_host = authctxt->host; - diff --git a/openssh-6.2p1-vendor.patch b/openssh-6.2p1-vendor.patch deleted file mode 100644 index 1af5e9d3ff0d9697896c518d60acda03d26be903..0000000000000000000000000000000000000000 --- a/openssh-6.2p1-vendor.patch +++ /dev/null @@ -1,142 +0,0 @@ -diff -up openssh-7.4p1/configure.ac.vendor openssh-7.4p1/configure.ac ---- openssh-7.4p1/configure.ac.vendor 2016-12-23 13:34:51.681253844 +0100 -+++ openssh-7.4p1/configure.ac 2016-12-23 13:34:51.694253847 +0100 -@@ -4930,6 +4930,12 @@ AC_ARG_WITH([lastlog], - fi - ] - ) -+AC_ARG_ENABLE(vendor-patchlevel, -+ [ --enable-vendor-patchlevel=TAG specify a vendor patch level], -+ [AC_DEFINE_UNQUOTED(SSH_VENDOR_PATCHLEVEL,[SSH_RELEASE "-" "$enableval"],[Define to your vendor patch level, if it has been modified from the upstream source release.]) -+ SSH_VENDOR_PATCHLEVEL="$enableval"], -+ [AC_DEFINE(SSH_VENDOR_PATCHLEVEL,SSH_RELEASE,[Define to your vendor patch level, if it has been modified from the upstream source release.]) -+ SSH_VENDOR_PATCHLEVEL=none]) - - dnl lastlog, [uw]tmpx? detection - dnl NOTE: set the paths in the platform section to avoid the -@@ -5194,6 +5200,7 @@ echo " Translate v4 in v6 hack - echo " BSD Auth support: $BSD_AUTH_MSG" - echo " Random number source: $RAND_MSG" - echo " Privsep sandbox style: $SANDBOX_STYLE" -+echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL" - - echo "" - -diff -up openssh-7.4p1/servconf.c.vendor openssh-7.4p1/servconf.c ---- openssh-7.4p1/servconf.c.vendor 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/servconf.c 2016-12-23 13:36:07.555268628 +0100 -@@ -143,6 +143,7 @@ initialize_server_options(ServerOptions - options->max_authtries = -1; - options->max_sessions = -1; - options->banner = NULL; -+ options->show_patchlevel = -1; - options->use_dns = -1; - options->client_alive_interval = -1; - options->client_alive_count_max = -1; -@@ -325,6 +326,8 @@ fill_default_server_options(ServerOption - options->ip_qos_bulk = IPTOS_DSCP_CS1; - if (options->version_addendum == NULL) - options->version_addendum = xstrdup(""); -+ if (options->show_patchlevel == -1) -+ options->show_patchlevel = 0; - if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) - options->fwd_opts.streamlocal_bind_mask = 0177; - if (options->fwd_opts.streamlocal_bind_unlink == -1) -@@ -402,7 +405,7 @@ typedef enum { - sIgnoreUserKnownHosts, sCiphers, sMacs, sPidFile, - sGatewayPorts, sPubkeyAuthentication, sPubkeyAcceptedKeyTypes, - sXAuthLocation, sSubsystem, sMaxStartups, sMaxAuthTries, sMaxSessions, -- sBanner, sUseDNS, sHostbasedAuthentication, -+ sBanner, sShowPatchLevel, sUseDNS, sHostbasedAuthentication, - sHostbasedUsesNameFromPacketOnly, sHostbasedAcceptedKeyTypes, - sHostKeyAlgorithms, - sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, -@@ -528,6 +531,7 @@ static struct { - { "maxauthtries", sMaxAuthTries, SSHCFG_ALL }, - { "maxsessions", sMaxSessions, SSHCFG_ALL }, - { "banner", sBanner, SSHCFG_ALL }, -+ { "showpatchlevel", sShowPatchLevel, SSHCFG_GLOBAL }, - { "usedns", sUseDNS, SSHCFG_GLOBAL }, - { "verifyreversemapping", sDeprecated, SSHCFG_GLOBAL }, - { "reversemappingcheck", sDeprecated, SSHCFG_GLOBAL }, -@@ -1369,6 +1373,10 @@ process_server_config_line(ServerOptions - intptr = &options->disable_forwarding; - goto parse_flag; - -+ case sShowPatchLevel: -+ intptr = &options->show_patchlevel; -+ goto parse_flag; -+ - case sAllowUsers: - while ((arg = strdelim(&cp)) && *arg != '\0') { - if (match_user(NULL, NULL, NULL, arg) == -1) -@@ -2269,6 +2277,7 @@ dump_config(ServerOptions *o) - dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); - dump_cfg_fmtint(sCompression, o->compression); - dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports); -+ dump_cfg_fmtint(sShowPatchLevel, o->show_patchlevel); - dump_cfg_fmtint(sUseDNS, o->use_dns); - dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); - dump_cfg_fmtint(sAllowAgentForwarding, o->allow_agent_forwarding); -diff -up openssh-7.4p1/servconf.h.vendor openssh-7.4p1/servconf.h ---- openssh-7.4p1/servconf.h.vendor 2016-12-19 05:59:41.000000000 +0100 -+++ openssh-7.4p1/servconf.h 2016-12-23 13:34:51.694253847 +0100 -@@ -149,6 +149,7 @@ typedef struct { - int max_authtries; - int max_sessions; - char *banner; /* SSH-2 banner message */ -+ int show_patchlevel; /* Show vendor patch level to clients */ - int use_dns; - int client_alive_interval; /* - * poke the client this often to -diff -up openssh-7.4p1/sshd_config.5.vendor openssh-7.4p1/sshd_config.5 ---- openssh-7.4p1/sshd_config.5.vendor 2016-12-23 13:34:51.695253847 +0100 -+++ openssh-7.4p1/sshd_config.5 2016-12-23 13:37:17.482282253 +0100 -@@ -1334,6 +1334,13 @@ an OpenSSH Key Revocation List (KRL) as - .Cm AcceptEnv - or - .Cm PermitUserEnvironment . -+.It Cm ShowPatchLevel -+Specifies whether -+.Nm sshd -+will display the patch level of the binary in the identification string. -+The patch level is set at compile-time. -+The default is -+.Dq no . - .It Cm StreamLocalBindMask - Sets the octal file creation mode mask - .Pq umask -diff -up openssh-7.4p1/sshd_config.vendor openssh-7.4p1/sshd_config ---- openssh-7.4p1/sshd_config.vendor 2016-12-23 13:34:51.690253846 +0100 -+++ openssh-7.4p1/sshd_config 2016-12-23 13:34:51.695253847 +0100 -@@ -105,6 +105,7 @@ X11Forwarding yes - #Compression delayed - #ClientAliveInterval 0 - #ClientAliveCountMax 3 -+#ShowPatchLevel no - #UseDNS no - #PidFile /var/run/sshd.pid - #MaxStartups 10:30:100 -diff -up openssh-7.4p1/sshd.c.vendor openssh-7.4p1/sshd.c ---- openssh-7.4p1/sshd.c.vendor 2016-12-23 13:34:51.682253844 +0100 -+++ openssh-7.4p1/sshd.c 2016-12-23 13:38:32.434296856 +0100 -@@ -367,7 +367,8 @@ sshd_exchange_identification(struct ssh - char remote_version[256]; /* Must be at least as big as buf. */ - - xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n", -- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION, -+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, -+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION, - *options.version_addendum == '\0' ? "" : " ", - options.version_addendum); - -@@ -1650,7 +1651,8 @@ main(int ac, char **av) - exit(1); - } - -- debug("sshd version %s, %s", SSH_VERSION, -+ debug("sshd version %s, %s", -+ (options.show_patchlevel == 1) ? SSH_VENDOR_PATCHLEVEL : SSH_VERSION, - #ifdef WITH_OPENSSL - SSLeay_version(SSLEAY_VERSION) - #else diff --git a/openssh-6.6.1p1-log-in-chroot.patch b/openssh-6.6.1p1-log-in-chroot.patch index 7f822aba2566a7351b282245091d99c41aee05c5..12602424031b2991fe9ed3b1882af0dfa16cc628 100644 --- a/openssh-6.6.1p1-log-in-chroot.patch +++ b/openssh-6.6.1p1-log-in-chroot.patch @@ -46,7 +46,7 @@ diff -up openssh-7.4p1/monitor.c.log-in-chroot openssh-7.4p1/monitor.c + pmonitor->m_state = "preauth"; + - authctxt = _authctxt; + authctxt = (Authctxt *)ssh->authctxt; memset(authctxt, 0, sizeof(*authctxt)); ssh->authctxt = authctxt; @@ -405,6 +407,8 @@ monitor_child_postauth(struct monitor *p @@ -56,8 +56,8 @@ diff -up openssh-7.4p1/monitor.c.log-in-chroot openssh-7.4p1/monitor.c + pmonitor->m_state = "postauth"; + monitor_set_child_handler(pmonitor->m_pid); - signal(SIGHUP, &monitor_child_handler); - signal(SIGTERM, &monitor_child_handler); + ssh_signal(SIGHUP, &monitor_child_handler); + ssh_signal(SIGTERM, &monitor_child_handler); @@ -472,7 +476,7 @@ monitor_read_log(struct monitor *pmonito if (log_level_name(level) == NULL) fatal("%s: invalid log level %u (corrupted message?)", @@ -113,7 +113,7 @@ diff -up openssh-7.4p1/monitor.h.log-in-chroot openssh-7.4p1/monitor.h +void monitor_reinit(struct monitor *, const char *); struct Authctxt; - void monitor_child_preauth(struct Authctxt *, struct monitor *); + void monitor_child_preauth(struct ssh *, struct monitor *); diff -up openssh-7.4p1/session.c.log-in-chroot openssh-7.4p1/session.c --- openssh-7.4p1/session.c.log-in-chroot 2016-12-23 15:14:33.319168086 +0100 +++ openssh-7.4p1/session.c 2016-12-23 15:18:18.742211853 +0100 @@ -210,8 +210,8 @@ diff -up openssh-7.4p1/sftp-server.c.log-in-chroot openssh-7.4p1/sftp-server.c fd_set *rset, *wset; int i, r, in, out, max, ch, skipargs = 0, log_stderr = 0; @@ -1511,7 +1511,7 @@ sftp_server_main(int argc, char **argv, + extern char *__progname; - ssh_malloc_init(); /* must be called before any mallocs */ __progname = ssh_get_progname(argv[0]); - log_init(__progname, log_level, log_facility, log_stderr); + log_init_handler(__progname, log_level, log_facility, log_stderr, reset_handler); diff --git a/openssh-6.6.1p1-scp-non-existing-directory.patch b/openssh-6.6.1p1-scp-non-existing-directory.patch index 5412bc5d034c54507f0f95253fad4e11ebcfcced..bb55c0b4e57811aee80e11849105e25a2086121b 100644 --- a/openssh-6.6.1p1-scp-non-existing-directory.patch +++ b/openssh-6.6.1p1-scp-non-existing-directory.patch @@ -10,5 +10,5 @@ + } omode = mode; mode |= S_IWUSR; - if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) < 0) { + if ((ofd = open(np, O_WRONLY|O_CREAT, mode)) == -1) { -- diff --git a/openssh-6.6.1p1-selinux-contexts.patch b/openssh-6.6.1p1-selinux-contexts.patch index 8bf6c78d6242b5ea9c9bd8234fa792dcb4253f59..3a7193e817c05d6b82b1e10feb7f978346629e35 100644 --- a/openssh-6.6.1p1-selinux-contexts.patch +++ b/openssh-6.6.1p1-selinux-contexts.patch @@ -19,7 +19,7 @@ index 8f32464..18a2ca4 100644 if (!sshd_selinux_enabled()) return; -@@ -461,6 +462,58 @@ sshd_selinux_copy_context(void) +@@ -461,6 +462,72 @@ sshd_selinux_copy_context(void) } } @@ -30,46 +30,60 @@ index 8f32464..18a2ca4 100644 + char line[1024], *preauth_context = NULL, *cp, *arg; + const char *contexts_path; + FILE *contexts_file; ++ struct stat sb; + + contexts_path = selinux_openssh_contexts_path(); -+ if (contexts_path != NULL) { -+ if ((contexts_file = fopen(contexts_path, "r")) != NULL) { -+ struct stat sb; ++ if (contexts_path == NULL) { ++ debug3("%s: Failed to get the path to SELinux context", __func__); ++ return; ++ } ++ ++ if ((contexts_file = fopen(contexts_path, "r")) == NULL) { ++ debug("%s: Failed to open SELinux context file", __func__); ++ return; ++ } ++ ++ if (fstat(fileno(contexts_file), &sb) != 0 || ++ sb.st_uid != 0 || (sb.st_mode & 022) != 0) { ++ logit("%s: SELinux context file needs to be owned by root" ++ " and not writable by anyone else", __func__); ++ fclose(contexts_file); ++ return; ++ } + -+ if (fstat(fileno(contexts_file), &sb) == 0 && ((sb.st_uid == 0) && ((sb.st_mode & 022) == 0))) { -+ while (fgets(line, sizeof(line), contexts_file)) { -+ /* Strip trailing whitespace */ -+ for (len = strlen(line) - 1; len > 0; len--) { -+ if (strchr(" \t\r\n", line[len]) == NULL) -+ break; -+ line[len] = '\0'; -+ } ++ while (fgets(line, sizeof(line), contexts_file)) { ++ /* Strip trailing whitespace */ ++ for (len = strlen(line) - 1; len > 0; len--) { ++ if (strchr(" \t\r\n", line[len]) == NULL) ++ break; ++ line[len] = '\0'; ++ } + -+ if (line[0] == '\0') -+ continue; ++ if (line[0] == '\0') ++ continue; + -+ cp = line; -+ arg = strdelim(&cp); -+ if (arg && *arg == '\0') -+ arg = strdelim(&cp); ++ cp = line; ++ arg = strdelim(&cp); ++ if (arg && *arg == '\0') ++ arg = strdelim(&cp); + -+ if (arg && strcmp(arg, "privsep_preauth") == 0) { -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') { -+ debug("%s: privsep_preauth is empty", __func__); -+ fclose(contexts_file); -+ return; -+ } -+ preauth_context = xstrdup(arg); -+ } -+ } ++ if (arg && strcmp(arg, "privsep_preauth") == 0) { ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') { ++ debug("%s: privsep_preauth is empty", __func__); ++ fclose(contexts_file); ++ return; + } -+ fclose(contexts_file); ++ preauth_context = xstrdup(arg); + } + } ++ fclose(contexts_file); + -+ if (preauth_context == NULL) -+ preauth_context = xstrdup("sshd_net_t"); ++ if (preauth_context == NULL) { ++ debug("%s: Unable to find 'privsep_preauth' option in" ++ " SELinux context file", __func__); ++ return; ++ } + + ssh_selinux_change_context(preauth_context); + free(preauth_context); @@ -82,14 +96,6 @@ 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 -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - - #include "log.h" - #include "xmalloc.h" @@ -179,7 +179,7 @@ ssh_selinux_change_context(const char *newname) strlcpy(newctx + len, newname, newlen - len); if ((cx = index(cx + 1, ':'))) diff --git a/openssh-6.6p1-GSSAPIEnablek5users.patch b/openssh-6.6p1-GSSAPIEnablek5users.patch index 37e010d93a653257ac24d9fd4d0e66804d6a1944..01ea15612c219fd1dd67d4ebeb8553b5bde4d1cb 100644 --- a/openssh-6.6p1-GSSAPIEnablek5users.patch +++ b/openssh-6.6p1-GSSAPIEnablek5users.patch @@ -22,15 +22,15 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c --- openssh-7.4p1/servconf.c.GSSAPIEnablek5users 2016-12-23 15:18:40.615216100 +0100 +++ openssh-7.4p1/servconf.c 2016-12-23 15:35:36.354401156 +0100 @@ -168,6 +168,7 @@ initialize_server_options(ServerOptions - options->gss_strict_acceptor = -1; options->gss_store_rekey = -1; + options->gss_kex_algorithms = NULL; options->use_kuserok = -1; + options->enable_k5users = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; @@ -345,6 +346,8 @@ fill_default_server_options(ServerOption - options->gss_store_rekey = 0; + #endif if (options->use_kuserok == -1) options->use_kuserok = 1; + if (options->enable_k5users == -1) @@ -44,20 +44,22 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, - sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, + sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor, - sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel, + sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, + sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, -@@ -497,12 +500,14 @@ static struct { - { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, +@@ -497,14 +500,16 @@ static struct { { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, + { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, + { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, + { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, + { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL }, + { "gssapienablek5users", sUnsupported, SSHCFG_ALL }, #endif { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, @@ -83,7 +85,7 @@ diff -up openssh-7.4p1/servconf.c.GSSAPIEnablek5users openssh-7.4p1/servconf.c M_CP_INTOPT(log_level); @@ -2320,6 +2330,7 @@ dump_config(ServerOptions *o) # endif - dump_cfg_fmtint(sKerberosUniqueTicket, o->kerberos_unique_ticket); + dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache); dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); + dump_cfg_fmtint(sGssEnablek5users, o->enable_k5users); #endif @@ -93,7 +95,7 @@ diff -up openssh-7.4p1/servconf.h.GSSAPIEnablek5users openssh-7.4p1/servconf.h --- openssh-7.4p1/servconf.h.GSSAPIEnablek5users 2016-12-23 15:18:40.616216100 +0100 +++ openssh-7.4p1/servconf.h 2016-12-23 15:18:40.629216102 +0100 @@ -174,6 +174,7 @@ typedef struct { - int kerberos_unique_ticket; /* If true, the aquired ticket will + int kerberos_unique_ccache; /* If true, the acquired ticket will * be stored in per-session ccache */ int use_kuserok; + int enable_k5users; @@ -120,7 +122,7 @@ diff -up openssh-7.4p1/sshd_config.GSSAPIEnablek5users openssh-7.4p1/sshd_config --- openssh-7.4p1/sshd_config.GSSAPIEnablek5users 2016-12-23 15:18:40.616216100 +0100 +++ openssh-7.4p1/sshd_config 2016-12-23 15:18:40.631216103 +0100 @@ -80,6 +80,7 @@ GSSAPIAuthentication yes - GSSAPICleanupCredentials no + #GSSAPICleanupCredentials yes #GSSAPIStrictAcceptorCheck yes #GSSAPIKeyExchange no +#GSSAPIEnablek5users no diff --git a/openssh-6.6p1-ctr-cavstest.patch b/openssh-6.6p1-ctr-cavstest.patch index c56313d53ad4c9c5f7a990e7721b9fd545c51322..9454c502d0d6788f1b430700cfefcd91d30d4ca9 100644 --- a/openssh-6.6p1-ctr-cavstest.patch +++ b/openssh-6.6p1-ctr-cavstest.patch @@ -7,14 +7,14 @@ diff -up openssh-6.8p1/Makefile.in.ctr-cavs openssh-6.8p1/Makefile.in SSH_KEYCAT=$(libexecdir)/ssh-keycat +CTR_CAVSTEST=$(libexecdir)/ctr-cavstest SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ @@ -66,7 +67,7 @@ EXEEXT=@EXEEXT@ - MKDIR_P=@MKDIR_P@ - INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ --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-ldap-helper$(EXEEXT) ssh-keycat$(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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) + .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) ssh-ldap-helper$(EXEEXT) ssh-keycat$(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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) XMSS_OBJS=\ ssh-xmss.o \ @@ -25,8 +25,8 @@ diff -up openssh-6.8p1/Makefile.in.ctr-cavs openssh-6.8p1/Makefile.in +ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o + $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) + - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) @@ -326,6 +330,7 @@ install-files: $(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ @@ -187,7 +187,7 @@ diff -up openssh-6.8p1/ctr-cavstest.c.ctr-cavs openssh-6.8p1/ctr-cavstest.c + usage(); + } + -+ SSLeay_add_all_algorithms(); ++ OpenSSL_add_all_algorithms(); + + c = cipher_by_name(algo); + if (c == NULL) { diff --git a/openssh-6.6p1-force_krb.patch b/openssh-6.6p1-force_krb.patch index aeee77f34ee81ef4e06f2bd851c5e349fa39b823..90f8322f14191d57b9096069b5d26b2e5bfb3c22 100644 --- a/openssh-6.6p1-force_krb.patch +++ b/openssh-6.6p1-force_krb.patch @@ -235,9 +235,9 @@ index 28659ec..9c94d8e 100644 +#endif +#endif + + s->forced = 0; if (forced != NULL) { - if (IS_INTERNAL_SFTP(command)) { - s->is_subsystem = s->is_subsystem ? + s->forced = 1; diff --git a/ssh-gss.h b/ssh-gss.h index 0374c88..509109a 100644 --- a/ssh-gss.h diff --git a/openssh-6.6p1-keycat.patch b/openssh-6.6p1-keycat.patch index e22a5f365165a47f4bd1fc5b249c6cafcd8a25d6..5fc9b9ed4200db798631af792f74996c0ab7400f 100644 --- a/openssh-6.6p1-keycat.patch +++ b/openssh-6.6p1-keycat.patch @@ -41,22 +41,22 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper +SSH_KEYCAT=$(libexecdir)/ssh-keycat SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ @@ -52,6 +52,7 @@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ SSHLIBS=@SSHLIBS@ SSHDLIBS=@SSHDLIBS@ +KEYCATLIBS=@KEYCATLIBS@ LIBEDIT=@LIBEDIT@ + LIBFIDO2=@LIBFIDO2@ AR=@AR@ - AWK=@AWK@ @@ -65,7 +66,7 @@ EXEEXT=@EXEEXT@ - MKDIR_P=@MKDIR_P@ - INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ --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-ldap-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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) + .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) ssh-ldap-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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) XMSS_OBJS=\ ssh-xmss.o \ @@ -67,8 +67,8 @@ diff -up openssh/Makefile.in.keycat openssh/Makefile.in +ssh-keycat$(EXEEXT): $(LIBCOMPAT) $(SSHDOBJS) libssh.a ssh-keycat.o uidswap.o + $(LD) -o $@ ssh-keycat.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(KEYCATLIBS) $(LIBS) + - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) @@ -321,6 +325,7 @@ install-files: $(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \ diff --git a/openssh-6.6p1-keyperm.patch b/openssh-6.6p1-keyperm.patch index fbe33b0e12c0becb4b482d261c37ca03235f6a07..5e06940b64e6f61324f772f3aef1c2ad612064cf 100644 --- a/openssh-6.6p1-keyperm.patch +++ b/openssh-6.6p1-keyperm.patch @@ -1,8 +1,7 @@ -diff --git a/authfile.c b/authfile.c -index e93d867..4fc5b3d 100644 ---- a/authfile.c -+++ b/authfile.c -@@ -32,6 +32,7 @@ +diff -up openssh-8.2p1/authfile.c.keyperm openssh-8.2p1/authfile.c +--- openssh-8.2p1/authfile.c.keyperm 2020-02-14 01:40:54.000000000 +0100 ++++ openssh-8.2p1/authfile.c 2020-02-17 11:55:12.841729758 +0100 +@@ -31,6 +31,7 @@ #include #include @@ -10,17 +9,23 @@ index e93d867..4fc5b3d 100644 #include #include #include -@@ -207,6 +208,13 @@ sshkey_perm_ok(int fd, const char *filename) +@@ -101,7 +102,19 @@ sshkey_perm_ok(int fd, const char *filen #ifdef HAVE_CYGWIN if (check_ntsec(filename)) #endif -+ if (st.st_mode & 040) { -+ struct group *gr; -+ -+ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid)) -+ st.st_mode &= ~040; -+ } + if ((st.st_uid == getuid()) && (st.st_mode & 077) != 0) { ++ if (st.st_mode & 040) { ++ struct group *gr; ++ ++ if ((gr = getgrnam("ssh_keys")) && (st.st_gid == gr->gr_gid)) { ++ /* The only additional bit is read ++ * for ssh_keys group, which is fine */ ++ if ((st.st_mode & 077) == 040 ) { ++ return 0; ++ } ++ } ++ } error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); error("@ WARNING: UNPROTECTED PRIVATE KEY FILE! @"); + error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); diff --git a/openssh-6.6p1-kuserok.patch b/openssh-6.6p1-kuserok.patch index 81ec2a4b1625304ff3a8363f7fd87539f9168f0a..8428c1c8eca9b9b0b26fca2407e0c1991626a2c6 100644 --- a/openssh-6.6p1-kuserok.patch +++ b/openssh-6.6p1-kuserok.patch @@ -176,17 +176,17 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c --- openssh-7.4p1/servconf.c.kuserok 2016-12-23 14:36:07.630465944 +0100 +++ openssh-7.4p1/servconf.c 2016-12-23 15:11:52.278133344 +0100 @@ -116,6 +116,7 @@ initialize_server_options(ServerOptions - options->gss_cleanup_creds = -1; options->gss_strict_acceptor = -1; options->gss_store_rekey = -1; + options->gss_kex_algorithms = NULL; + options->use_kuserok = -1; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; @@ -278,6 +279,8 @@ fill_default_server_options(ServerOption - options->gss_strict_acceptor = 1; - if (options->gss_store_rekey == -1) - options->gss_store_rekey = 0; + if (options->gss_kex_algorithms == NULL) + options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX); + #endif + if (options->use_kuserok == -1) + options->use_kuserok = 1; if (options->password_authentication == -1) @@ -196,28 +196,28 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c sPermitRootLogin, sLogFacility, sLogLevel, sRhostsRSAAuthentication, sRSAAuthentication, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, -- sKerberosGetAFSToken, sKerberosUniqueTicket, -+ sKerberosGetAFSToken, sKerberosUniqueTicket, sKerberosUseKuserok, +- sKerberosGetAFSToken, sKerberosUniqueCCache, ++ sKerberosGetAFSToken, sKerberosUniqueCCache, sKerberosUseKuserok, sChallengeResponseAuthentication, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, @@ -478,12 +481,14 @@ static struct { { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif - { "kerberosuniqueticket", sKerberosUniqueTicket, SSHCFG_GLOBAL }, + { "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL }, + { "kerberosusekuserok", sKerberosUseKuserok, SSHCFG_ALL }, #else { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, - { "kerberosuniqueticket", sUnsupported, SSHCFG_GLOBAL }, + { "kerberosuniqueccache", sUnsupported, SSHCFG_GLOBAL }, + { "kerberosusekuserok", sUnsupported, SSHCFG_ALL }, #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, @@ -1644,6 +1649,10 @@ process_server_config_line(ServerOptions - *activep = value; + *activep = (inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; break; + case sKerberosUseKuserok: @@ -238,7 +238,7 @@ diff -up openssh-7.4p1/servconf.c.kuserok openssh-7.4p1/servconf.c @@ -2309,6 +2319,7 @@ dump_config(ServerOptions *o) dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif - dump_cfg_fmtint(sKerberosUniqueTicket, o->kerberos_unique_ticket); + dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache); + dump_cfg_fmtint(sKerberosUseKuserok, o->use_kuserok); #endif #ifdef GSSAPI @@ -248,7 +248,7 @@ diff -up openssh-7.4p1/servconf.h.kuserok openssh-7.4p1/servconf.h +++ openssh-7.4p1/servconf.h 2016-12-23 14:36:07.645465936 +0100 @@ -118,6 +118,7 @@ typedef struct { * authenticated with Kerberos. */ - int kerberos_unique_ticket; /* If true, the aquired ticket will + int kerberos_unique_ccache; /* If true, the acquired ticket will * be stored in per-session ccache */ + int use_kuserok; int gss_authentication; /* If true, permit GSSAPI authentication */ @@ -258,9 +258,9 @@ diff -up openssh-7.4p1/sshd_config.5.kuserok openssh-7.4p1/sshd_config.5 --- openssh-7.4p1/sshd_config.5.kuserok 2016-12-23 14:36:07.637465940 +0100 +++ openssh-7.4p1/sshd_config.5 2016-12-23 15:14:03.117162222 +0100 @@ -850,6 +850,10 @@ Specifies whether to automatically destr - tickets aquired in different sessions of the same user. - The default is - .Cm no . + .Cm no + can lead to overwriting previous tickets by subseqent connections to the same + user account. +.It Cm KerberosUseKuserok +Specifies whether to look at .k5login file for user's aliases. +The default is @@ -286,4 +286,4 @@ diff -up openssh-7.4p1/sshd_config.kuserok openssh-7.4p1/sshd_config +#KerberosUseKuserok yes # GSSAPI options - GSSAPIAuthentication yes + #GSSAPIAuthentication no diff --git a/openssh-6.6p1-privsep-selinux.patch b/openssh-6.6p1-privsep-selinux.patch index 1365506683894135299b678143b108db3bdcd707..3d4c2874ba6270e29b5b8e7d129c830516f192a7 100644 --- a/openssh-6.6p1-privsep-selinux.patch +++ b/openssh-6.6p1-privsep-selinux.patch @@ -25,15 +25,15 @@ diff -up openssh-7.4p1/openbsd-compat/port-linux-sshd.c.privsep-selinux openssh- + return; + + if (getexeccon((security_context_t *)&ctx) != 0) { -+ logit("%s: getcon failed with %s", __func__, strerror (errno)); ++ logit("%s: getexeccon failed with %s", __func__, strerror(errno)); + return; + } + if (ctx != NULL) { + /* unset exec context before we will lose this capabililty */ + if (setexeccon(NULL) != 0) -+ fatal("%s: setexeccon failed with %s", __func__, strerror (errno)); ++ fatal("%s: setexeccon failed with %s", __func__, strerror(errno)); + if (setcon(ctx) != 0) -+ fatal("%s: setcon failed with %s", __func__, strerror (errno)); ++ fatal("%s: setcon failed with %s", __func__, strerror(errno)); + freecon(ctx); + } +} diff --git a/openssh-6.7p1-coverity.patch b/openssh-6.7p1-coverity.patch index 0d238dd61c94c0b75add845df8edd9305c7ddd82..3f34464f51a09454c49053ce9e4eb769a6d1693b 100644 --- a/openssh-6.7p1-coverity.patch +++ b/openssh-6.7p1-coverity.patch @@ -20,7 +20,7 @@ diff -up openssh-7.4p1/monitor.c.coverity openssh-7.4p1/monitor.c --- openssh-7.4p1/monitor.c.coverity 2016-12-23 16:40:26.888788688 +0100 +++ openssh-7.4p1/monitor.c 2016-12-23 16:40:26.900788691 +0100 @@ -411,7 +411,7 @@ monitor_child_preauth(Authctxt *_authctx - mm_get_keystate(pmonitor); + mm_get_keystate(ssh, pmonitor); /* Drain any buffered messages from the child */ - while (pmonitor->m_log_recvfd != -1 && monitor_read_log(pmonitor) == 0) @@ -124,23 +124,23 @@ diff -up openssh-7.4p1/serverloop.c.coverity openssh-7.4p1/serverloop.c } @@ -518,7 +518,7 @@ server_request_tun(void) + debug("%s: invalid tun", __func__); + goto done; } - - tun = packet_get_int(); - if (auth_opts->force_tun_device != -1) { + if (auth_opts->force_tun_device >= 0) { - if (tun != SSH_TUNID_ANY && auth_opts->force_tun_device != tun) + if (tun != SSH_TUNID_ANY && + auth_opts->force_tun_device != (int)tun) goto done; - tun = auth_opts->force_tun_device; diff -up openssh-7.4p1/sftp.c.coverity openssh-7.4p1/sftp.c --- openssh-7.4p1/sftp.c.coverity 2016-12-19 05:59:41.000000000 +0100 +++ openssh-7.4p1/sftp.c 2016-12-23 16:40:26.903788691 +0100 @@ -224,7 +224,7 @@ killchild(int signo) - { - if (sshpid > 1) { - kill(sshpid, SIGTERM); -- waitpid(sshpid, NULL, 0); -+ (void) waitpid(sshpid, NULL, 0); + pid = sshpid; + if (pid > 1) { + kill(pid, SIGTERM); +- waitpid(pid, NULL, 0); ++ (void) waitpid(pid, NULL, 0); } _exit(1); @@ -163,7 +163,7 @@ diff -up openssh-7.4p1/sshd.c.coverity openssh-7.4p1/sshd.c +++ openssh-7.4p1/sshd.c 2016-12-23 16:40:26.904788692 +0100 @@ -691,8 +691,10 @@ privsep_preauth(Authctxt *authctxt) - privsep_preauth_child(); + privsep_preauth_child(ssh); setproctitle("%s", "[net]"); - if (box != NULL) + if (box != NULL) { @@ -174,8 +174,8 @@ 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 - if (num_listen_socks < 0) - break; + explicit_bzero(rnd, sizeof(rnd)); + } } + + if (fdset != NULL) diff --git a/openssh-6.7p1-kdf-cavs.patch b/openssh-6.7p1-kdf-cavs.patch index 181267cb4d166b79d3c55dbe2e68e6066b21e29c..971ac3d8db6bdf9d89e35c42fda9654e5839af9e 100644 --- a/openssh-6.7p1-kdf-cavs.patch +++ b/openssh-6.7p1-kdf-cavs.patch @@ -7,14 +7,14 @@ diff -up openssh-6.8p1/Makefile.in.kdf-cavs openssh-6.8p1/Makefile.in CTR_CAVSTEST=$(libexecdir)/ctr-cavstest +SSH_CAVS=$(libexecdir)/ssh-cavs SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ @@ -67,7 +68,7 @@ EXEEXT=@EXEEXT@ - MKDIR_P=@MKDIR_P@ - INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ --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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) ssh-cavs$(EXEEXT) + .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) ssh-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(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-ldap-helper$(EXEEXT) ssh-keycat$(EXEEXT) ctr-cavstest$(EXEEXT) ssh-cavs$(EXEEXT) XMSS_OBJS=\ ssh-xmss.o \ @@ -22,11 +22,11 @@ diff -up openssh-6.8p1/Makefile.in.kdf-cavs openssh-6.8p1/Makefile.in ctr-cavstest$(EXEEXT): $(LIBCOMPAT) libssh.a ctr-cavstest.o $(LD) -o $@ ctr-cavstest.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) -+ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-cavs.o -+ $(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) ++ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-cavs.o $(SKOBJS) ++ $(LD) -o $@ ssh-cavs.o $(SKOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) + - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) @@ -331,6 +335,8 @@ install-files: fi @@ -40,7 +40,7 @@ diff -up openssh-6.8p1/Makefile.in.kdf-cavs openssh-6.8p1/Makefile.in diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c --- openssh-6.8p1/ssh-cavs.c.kdf-cavs 2015-03-18 11:23:46.348049354 +0100 +++ openssh-6.8p1/ssh-cavs.c 2015-03-18 11:23:46.348049354 +0100 -@@ -0,0 +1,377 @@ +@@ -0,0 +1,387 @@ +/* + * Copyright (C) 2015, Stephan Mueller + * @@ -208,6 +208,7 @@ diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c +{ + int ret = 0; + struct kex kex; ++ struct sshbuf *Kb = NULL; + BIGNUM *Kbn = NULL; + int mode = 0; + struct newkeys *ctoskeys; @@ -222,10 +223,17 @@ diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c + Kbn = BN_new(); + BN_bin2bn(test->K, test->Klen, Kbn); + if (!Kbn) { -+ printf("cannot convert K into BIGNUM\n"); ++ printf("cannot convert K into bignum\n"); ++ ret = 1; ++ goto out; ++ } ++ Kb = sshbuf_new(); ++ if (!Kb) { ++ printf("cannot convert K into sshbuf\n"); + ret = 1; + goto out; + } ++ sshbuf_put_bignum2(Kb, Kbn); + + kex.session_id = test->session_id; + kex.session_id_len = test->session_id_len; @@ -285,7 +293,7 @@ diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c + goto out; + } + ssh->kex = &kex; -+ kex_derive_keys_bn(ssh, test->H, test->Hlen, Kbn); ++ kex_derive_keys(ssh, test->H, test->Hlen, Kb); + + ctoskeys = kex.newkeys[0]; + stockeys = kex.newkeys[1]; @@ -321,6 +329,8 @@ diff -up openssh-6.8p1/ssh-cavs.c.kdf-cavs openssh-6.8p1/ssh-cavs.c +out: + if (Kbn) + BN_free(Kbn); ++ if (Kb) ++ sshbuf_free(Kb); + if (ssh) + ssh_packet_close(ssh); + return ret; diff --git a/openssh-6.7p1-ldap.patch b/openssh-6.7p1-ldap.patch index ee44fdb6cf130a703194e59e9dc012e269b64566..aec47942166d2621f3d0c747a2c15ec6000c0db4 100644 --- a/openssh-6.7p1-ldap.patch +++ b/openssh-6.7p1-ldap.patch @@ -134,52 +134,54 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in +SSH_LDAP_HELPER=$(libexecdir)/ssh-ldap-helper +SSH_LDAP_WRAPPER=$(libexecdir)/ssh-ldap-wrapper SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper + SSH_SK_HELPER=$(libexecdir)/ssh-sk-helper PRIVSEP_PATH=@PRIVSEP_PATH@ - SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ @@ -50,6 +50,7 @@ - CFLAGS=@CFLAGS@ CPPFLAGS=-I. -I$(srcdir) @CPPFLAGS@ $(PATHS) @DEFS@ + PICFLAG=@PICFLAG@ LIBS=@LIBS@ +LDAPLIBS=@LDAPLIBS@ K5LIBS=@K5LIBS@ GSSLIBS=@GSSLIBS@ SSHLIBS=@SSHLIBS@ -@@ -61,8 +63,9 @@ XAUTH_PATH=@XAUTH_PATH@ +@@ -61,10 +63,11 @@ XAUTH_PATH=@XAUTH_PATH@ EXEEXT=@EXEEXT@ MANFMT=@MANFMT@ MKDIR_P=@MKDIR_P@ +INSTALL_SSH_LDAP_HELPER=@INSTALL_SSH_LDAP_HELPER@ --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) -+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-ldap-helper$(EXEEXT) + .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-ldap-helper$(EXEEXT) XMSS_OBJS=\ ssh-xmss.o \ @@ -112,8 +115,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw - sandbox-seccomp-filter.o sandbox-capsicum.o sandbox-pledge.o \ - sandbox-solaris.o uidswap.o --MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out --MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 -+MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap-helper.8.out ssh-ldap.conf.5.out -+MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 ssh-ldap-helper.8 ssh-ldap.conf.5 + SFTP_OBJS= sftp.o sftp-client.o sftp-common.o sftp-glob.o progressmeter.o + +-MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out +-MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5 ++MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out ssh-sk-helper.8.out sshd_config.5.out ssh_config.5.out ssh-ldap-helper.8.out ssh-ldap.conf.5.out ++MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 ssh-sk-helper.8 sshd_config.5 ssh_config.5 ssh-ldap-helper.8 ssh-ldap.conf.5 MANTYPE = @MANTYPE@ CONFIGFILES=sshd_config.out ssh_config.out moduli.out @@ -184,6 +187,9 @@ ssh-keysign$(EXEEXT): $(LIBCOMPAT) libss - ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o - $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) + ssh-sk-helper$(EXEEXT): $(LIBCOMPAT) libssh.a $(SKHELPER_OBJS) + $(LD) -o $@ $(SKHELPER_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) $(LIBFIDO2) +ssh-ldap-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o + $(LD) -o $@ ldapconf.o ldapbody.o ldapmisc.o ldap-helper.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat -lfipscheck $(LIBS) $(LDAPLIBS) + - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o - $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) + ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHKEYSCAN_OBJS) + $(LD) -o $@ $(SSHKEYSCAN_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) @@ -311,6 +317,10 @@ install-files: - $(INSTALL) -m 0755 $(STRIP_OPT) sshd$(EXEEXT) $(DESTDIR)$(sbindir)/sshd$(EXEEXT) $(INSTALL) -m 4711 $(STRIP_OPT) ssh-keysign$(EXEEXT) $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) $(INSTALL) -m 0755 $(STRIP_OPT) ssh-pkcs11-helper$(EXEEXT) $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) + $(INSTALL) -m 0755 $(STRIP_OPT) ssh-sk-helper$(EXEEXT) $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) + if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ + $(INSTALL) -m 0700 $(STRIP_OPT) ssh-ldap-helper $(DESTDIR)$(SSH_LDAP_HELPER) ; \ + $(INSTALL) -m 0700 ssh-ldap-wrapper $(DESTDIR)$(SSH_LDAP_WRAPPER) ; \ @@ -188,9 +190,9 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in $(INSTALL) -m 0755 $(STRIP_OPT) sftp-server$(EXEEXT) $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) $(INSTALL) -m 644 ssh.1.out $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 @@ -327,6 +337,10 @@ install-files: - $(INSTALL) -m 644 sftp-server.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 + $(INSTALL) -m 644 ssh-sk-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 + if test ! -z "$(INSTALL_SSH_LDAP_HELPER)" ; then \ + $(INSTALL) -m 644 ssh-ldap-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 ; \ + $(INSTALL) -m 644 ssh-ldap.conf.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh-ldap.conf.5 ; \ @@ -213,18 +215,18 @@ diff -up openssh-6.8p1/Makefile.in.ldap openssh-6.8p1/Makefile.in host-key: ssh-keygen$(EXEEXT) @if [ -z "$(DESTDIR)" ] ; then \ @@ -419,6 +440,8 @@ uninstall: - -rm -r $(DESTDIR)$(SFTP_SERVER)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_KEYSIGN)$(EXEEXT) -rm -f $(DESTDIR)$(SSH_PKCS11_HELPER)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_SK_HELPER)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_LDAP_HELPER)$(EXEEXT) + -rm -f $(DESTDIR)$(SSH_LDAP_WRAPPER)$(EXEEXT) -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/scp.1 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/ssh-add.1 @@ -430,6 +453,7 @@ uninstall: - -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/sftp-server.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-sk-helper.8 + -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-ldap-helper.8 regress-prep: @@ -233,8 +235,8 @@ diff -up openssh-6.8p1/configure.ac.ldap openssh-6.8p1/configure.ac --- openssh-6.8p1/configure.ac.ldap 2015-03-17 06:49:20.000000000 +0100 +++ openssh-6.8p1/configure.ac 2015-03-18 11:11:29.030801464 +0100 @@ -1605,6 +1605,110 @@ if test "x$use_pie" != "xno"; then - fi - fi + CFLAGS="$SAVED_CFLAGS" + AC_SUBST([PICFLAG]) +# Check whether user wants LDAP support +LDAP_MSG="no" @@ -331,7 +333,7 @@ diff -up openssh-6.8p1/configure.ac.ldap openssh-6.8p1/configure.ac + [ac_cv_ldap_set_rebind_proc=3], + [ac_cv_ldap_set_rebind_proc=2]) + AC_MSG_RESULT($ac_cv_ldap_set_rebind_proc) -+ AC_DEFINE(LDAP_SET_REBIND_PROC_ARGS, $ac_cv_ldap_set_rebind_proc, [number arguments of ldap_set_rebind_proc]) ++ AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $ac_cv_ldap_set_rebind_proc, [number arguments of ldap_set_rebind_proc]) + ) + LIBS="$saved_LIBS" + fi @@ -646,7 +648,7 @@ diff -up openssh-6.8p1/ldap.conf.ldap openssh-6.8p1/ldap.conf diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c --- openssh-6.8p1/ldapbody.c.ldap 2015-03-18 11:11:29.031801462 +0100 +++ openssh-6.8p1/ldapbody.c 2015-03-18 11:11:29.031801462 +0100 -@@ -0,0 +1,494 @@ +@@ -0,0 +1,499 @@ +/* $OpenBSD: ldapbody.c,v 1.1 2009/12/03 03:34:42 jfch Exp $ */ +/* + * Copyright (c) 2009 Jan F. Chadima. All rights reserved. @@ -708,7 +710,11 @@ diff -up openssh-6.8p1/ldapbody.c.ldap openssh-6.8p1/ldapbody.c + +#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000) +static int ++#if LDAP_API_VERSION > 3000 ++_rebind_proc (LDAP * ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *params) ++#else +_rebind_proc (LDAP * ld, LDAP_CONST char *url, int request, ber_int_t msgid) ++#endif +{ + struct timeval timeout; + int rc; diff --git a/openssh-6.8p1-sshdT-output.patch b/openssh-6.8p1-sshdT-output.patch index 7a843e79d25d0e1c4c9f2d0b2ab1f338ea6db96a..156e66d6d84ac3e7e68ead92315a338cafe60489 100644 --- a/openssh-6.8p1-sshdT-output.patch +++ b/openssh-6.8p1-sshdT-output.patch @@ -3,25 +3,10 @@ diff -up openssh/servconf.c.sshdt openssh/servconf.c +++ openssh/servconf.c 2015-06-24 11:44:39.734745802 +0200 @@ -2317,7 +2317,7 @@ dump_config(ServerOptions *o) dump_cfg_string(sXAuthLocation, o->xauth_location); - dump_cfg_string(sCiphers, o->ciphers ? o->ciphers : KEX_SERVER_ENCRYPT); - dump_cfg_string(sMacs, o->macs ? o->macs : KEX_SERVER_MAC); + dump_cfg_string(sCiphers, o->ciphers); + dump_cfg_string(sMacs, o->macs); - dump_cfg_string(sBanner, o->banner); + dump_cfg_string(sBanner, o->banner != NULL ? o->banner : "none"); dump_cfg_string(sForceCommand, o->adm_forced_command); dump_cfg_string(sChrootDirectory, o->chroot_directory); dump_cfg_string(sTrustedUserCAKeys, o->trusted_user_ca_keys); -diff -up openssh/ssh.1.sshdt openssh/ssh.1 ---- openssh/ssh.1.sshdt 2015-06-24 11:42:19.565102807 +0200 -+++ openssh/ssh.1 2015-06-24 11:42:29.042078701 +0200 -@@ -441,7 +441,11 @@ For full details of the options listed b - .It GatewayPorts - .It GlobalKnownHostsFile - .It GSSAPIAuthentication -+.It GSSAPIKeyExchange -+.It GSSAPIClientIdentity - .It GSSAPIDelegateCredentials -+.It GSSAPIRenewalForcesRekey -+.It GSSAPITrustDNS - .It HashKnownHosts - .It Host - .It HostbasedAuthentication diff --git a/openssh-6.9p1-permit-root-login.patch b/openssh-6.9p1-permit-root-login.patch deleted file mode 100644 index 6b4c4da1e9a15e9ada87a112d0b39dbdce36bc10..0000000000000000000000000000000000000000 --- a/openssh-6.9p1-permit-root-login.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up openssh-7.0p1/sshd_config.root-login openssh-7.0p1/sshd_config ---- openssh-7.0p1/sshd_config.root-login 2015-08-12 11:29:12.919269245 +0200 -+++ openssh-7.0p1/sshd_config 2015-08-12 11:31:03.653096466 +0200 -@@ -46,7 +46,7 @@ SyslogFacility AUTHPRIV - # Authentication: - - #LoginGraceTime 2m --#PermitRootLogin prohibit-password -+PermitRootLogin yes - #StrictModes yes - #MaxAuthTries 6 - #MaxSessions 10 diff --git a/openssh-7.0p1-gssKexAlgorithms.patch b/openssh-7.0p1-gssKexAlgorithms.patch deleted file mode 100644 index 2ba360ebbf154fbc3cbaa953cb5cfa38df2d8ac8..0000000000000000000000000000000000000000 --- a/openssh-7.0p1-gssKexAlgorithms.patch +++ /dev/null @@ -1,422 +0,0 @@ -diff -up openssh-7.0p1/gss-genr.c.gsskexalg openssh-7.0p1/gss-genr.c ---- openssh-7.0p1/gss-genr.c.gsskexalg 2015-08-19 12:28:38.024518959 +0200 -+++ openssh-7.0p1/gss-genr.c 2015-08-19 12:28:38.078518839 +0200 -@@ -78,7 +78,8 @@ ssh_gssapi_oid_table_ok() { - */ - - char * --ssh_gssapi_client_mechanisms(const char *host, const char *client) { -+ssh_gssapi_client_mechanisms(const char *host, const char *client, -+ const char *kex) { - gss_OID_set gss_supported; - OM_uint32 min_status; - -@@ -86,12 +87,12 @@ ssh_gssapi_client_mechanisms(const char - return NULL; - - return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, -- host, client)); -+ host, client, kex)); - } - - char * - ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, -- const char *host, const char *client) { -+ const char *host, const char *client, const char *kex) { - struct sshbuf *buf; - size_t i; - int oidpos, enclen, r; -@@ -100,6 +101,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup - char deroid[2]; - const EVP_MD *evp_md = EVP_md5(); - EVP_MD_CTX md; -+ char *s, *cp, *p; - - if (gss_enc2oid != NULL) { - for (i = 0; gss_enc2oid[i].encoded != NULL; i++) -@@ -113,6 +115,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup - fatal("%s: sshbuf_new failed", __func__); - - oidpos = 0; -+ s = cp = xstrdup(kex); - for (i = 0; i < gss_supported->count; i++) { - if (gss_supported->elements[i].length < 128 && - (*check)(NULL, &(gss_supported->elements[i]), host, client)) { -@@ -131,28 +134,25 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup - enclen = __b64_ntop(digest, EVP_MD_size(evp_md), - encoded, EVP_MD_size(evp_md) * 2); - -- if (oidpos != 0) -- if ((r = sshbuf_put_u8(buf, ',')) != 0) -- fatal("%s: buffer error: %s", __func__, ssh_err(r)); -- -- if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID, -- sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 || -- (r = sshbuf_put(buf, encoded, enclen)) != 0 || -- (r = sshbuf_put_u8(buf, ',')) != 0 || -- (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID, -- sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 || -- (r = sshbuf_put(buf, encoded, enclen)) != 0 || -- (r = sshbuf_put_u8(buf, ',')) != 0 || -- (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID, -- sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 || -- (r = sshbuf_put(buf, encoded, enclen)) != 0) -- fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ cp = strncpy(s, kex, strlen(kex)); -+ for ((p = strsep(&cp, ",")); p && *p != '\0'; -+ (p = strsep(&cp, ","))) { -+ if (sshbuf_len(buf) != 0) -+ if ((r = sshbuf_put_u8(buf, ',')) != 0) -+ fatal("%s: buffer error: %s", -+ __func__, ssh_err(r)); -+ if ((r = sshbuf_put(buf, p, strlen(p))) != 0 || -+ (r = sshbuf_put(buf, encoded, enclen)) != 0) -+ fatal("%s: buffer error: %s", -+ __func__, ssh_err(r)); -+ } - - gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); - gss_enc2oid[oidpos].encoded = encoded; - oidpos++; - } - } -+ free(s); - gss_enc2oid[oidpos].oid = NULL; - gss_enc2oid[oidpos].encoded = NULL; - -diff -up openssh-7.0p1/gss-serv.c.gsskexalg openssh-7.0p1/gss-serv.c ---- openssh-7.0p1/gss-serv.c.gsskexalg 2015-08-19 12:28:38.024518959 +0200 -+++ openssh-7.0p1/gss-serv.c 2015-08-19 12:28:38.078518839 +0200 -@@ -149,7 +149,8 @@ ssh_gssapi_server_mechanisms() { - if (supported_oids == NULL) - ssh_gssapi_prepare_supported_oids(); - return (ssh_gssapi_kex_mechs(supported_oids, -- &ssh_gssapi_server_check_mech, NULL, NULL)); -+ &ssh_gssapi_server_check_mech, NULL, NULL, -+ options.gss_kex_algorithms)); - } - - /* Unprivileged */ -diff -up openssh-7.0p1/kex.c.gsskexalg openssh-7.0p1/kex.c ---- openssh-7.0p1/kex.c.gsskexalg 2015-08-19 12:28:38.078518839 +0200 -+++ openssh-7.0p1/kex.c 2015-08-19 12:30:13.249306371 +0200 -@@ -50,6 +50,7 @@ - #include "misc.h" - #include "dispatch.h" - #include "monitor.h" -+#include "xmalloc.h" - - #include "ssherr.h" - #include "sshbuf.h" -@@ -232,6 +232,29 @@ kex_assemble_names(const char *def, char - return r; - } - -+/* Validate GSS KEX method name list */ -+int -+gss_kex_names_valid(const char *names) -+{ -+ char *s, *cp, *p; -+ -+ if (names == NULL || *names == '\0') -+ return 0; -+ s = cp = xstrdup(names); -+ for ((p = strsep(&cp, ",")); p && *p != '\0'; -+ (p = strsep(&cp, ","))) { -+ if (strncmp(p, "gss-", 4) != 0 -+ || kex_alg_by_name(p) == NULL) { -+ error("Unsupported KEX algorithm \"%.100s\"", p); -+ free(s); -+ return 0; -+ } -+ } -+ debug3("gss kex names ok: [%s]", names); -+ free(s); -+ return 1; -+} -+ - /* put algorithm proposal into buffer */ - int - kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) -diff -up openssh-7.0p1/kex.h.gsskexalg openssh-7.0p1/kex.h ---- openssh-7.0p1/kex.h.gsskexalg 2015-08-19 12:28:38.078518839 +0200 -+++ openssh-7.0p1/kex.h 2015-08-19 12:30:52.404218958 +0200 -@@ -173,6 +173,7 @@ int kex_names_valid(const char *); - char *kex_alg_list(char); - char *kex_names_cat(const char *, const char *); - int kex_assemble_names(char **, const char *, const char *); -+int gss_kex_names_valid(const char *); - - int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **); - int kex_setup(struct ssh *, char *[PROPOSAL_MAX]); -diff -up openssh-7.0p1/readconf.c.gsskexalg openssh-7.0p1/readconf.c ---- openssh-7.0p1/readconf.c.gsskexalg 2015-08-19 12:28:38.026518955 +0200 -+++ openssh-7.0p1/readconf.c 2015-08-19 12:31:28.333138747 +0200 -@@ -61,6 +61,7 @@ - #include "uidswap.h" - #include "myproposal.h" - #include "digest.h" -+#include "ssh-gss.h" - - /* Format of the configuration file: - -@@ -148,7 +149,7 @@ typedef enum { - oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, - oAddressFamily, oGssAuthentication, oGssDelegateCreds, - oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, -- oGssServerIdentity, -+ oGssServerIdentity, oGssKexAlgorithms, - oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, - oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, - oHashKnownHosts, -@@ -200,6 +201,7 @@ static struct { - { "gssapiclientidentity", oGssClientIdentity }, - { "gssapiserveridentity", oGssServerIdentity }, - { "gssapirenewalforcesrekey", oGssRenewalRekey }, -+ { "gssapikexalgorithms", oGssKexAlgorithms }, - # else - { "gssapiauthentication", oUnsupported }, - { "gssapikeyexchange", oUnsupported }, -@@ -207,6 +209,7 @@ static struct { - { "gssapitrustdns", oUnsupported }, - { "gssapiclientidentity", oUnsupported }, - { "gssapirenewalforcesrekey", oUnsupported }, -+ { "gssapikexalgorithms", oUnsupported }, - #endif - #ifdef ENABLE_PKCS11 - { "smartcarddevice", oPKCS11Provider }, -@@ -929,6 +932,18 @@ parse_time: - intptr = &options->gss_renewal_rekey; - goto parse_flag; - -+ case oGssKexAlgorithms: -+ arg = strdelim(&s); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing argument.", -+ filename, linenum); -+ if (!gss_kex_names_valid(arg)) -+ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.", -+ filename, linenum, arg ? arg : ""); -+ if (*activep && options->gss_kex_algorithms == NULL) -+ options->gss_kex_algorithms = xstrdup(arg); -+ break; -+ - case oBatchMode: - intptr = &options->batch_mode; - goto parse_flag; -@@ -1638,6 +1653,7 @@ initialize_options(Options * options) - options->gss_renewal_rekey = -1; - options->gss_client_identity = NULL; - options->gss_server_identity = NULL; -+ options->gss_kex_algorithms = NULL; - options->password_authentication = -1; - options->kbd_interactive_authentication = -1; - options->kbd_interactive_devices = NULL; -@@ -1773,6 +1789,10 @@ fill_default_options(Options * options) - options->gss_trust_dns = 0; - if (options->gss_renewal_rekey == -1) - options->gss_renewal_rekey = 0; -+#ifdef GSSAPI -+ if (options->gss_kex_algorithms == NULL) -+ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX); -+#endif - if (options->password_authentication == -1) - options->password_authentication = 1; - if (options->kbd_interactive_authentication == -1) -diff -up openssh-7.0p1/readconf.h.gsskexalg openssh-7.0p1/readconf.h ---- openssh-7.0p1/readconf.h.gsskexalg 2015-08-19 12:28:38.026518955 +0200 -+++ openssh-7.0p1/readconf.h 2015-08-19 12:28:38.079518836 +0200 -@@ -51,6 +51,7 @@ typedef struct { - int gss_renewal_rekey; /* Credential renewal forces rekey */ - char *gss_client_identity; /* Principal to initiate GSSAPI with */ - char *gss_server_identity; /* GSSAPI target principal */ -+ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */ - int password_authentication; /* Try password - * authentication. */ - int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff -up openssh-7.0p1/servconf.c.gsskexalg openssh-7.0p1/servconf.c ---- openssh-7.0p1/servconf.c.gsskexalg 2015-08-19 12:28:38.074518847 +0200 -+++ openssh-7.0p1/servconf.c 2015-08-19 12:33:13.599902732 +0200 -@@ -57,6 +57,7 @@ - #include "auth.h" - #include "myproposal.h" - #include "digest.h" -+#include "ssh-gss.h" - - static void add_listen_addr(ServerOptions *, const char *, - const char *, int); -@@ -121,6 +122,7 @@ initialize_server_options(ServerOptions - options->gss_cleanup_creds = -1; - options->gss_strict_acceptor = -1; - options->gss_store_rekey = -1; -+ options->gss_kex_algorithms = NULL; - options->use_kuserok = -1; - options->enable_k5users = -1; - options->password_authentication = -1; -@@ -288,6 +290,10 @@ fill_default_server_options(ServerOption - options->gss_strict_acceptor = 1; - if (options->gss_store_rekey == -1) - options->gss_store_rekey = 0; -+#ifdef GSSAPI -+ if (options->gss_kex_algorithms == NULL) -+ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX); -+#endif - if (options->use_kuserok == -1) - options->use_kuserok = 1; - if (options->enable_k5users == -1) -@@ -427,7 +431,7 @@ typedef enum { - sHostKeyAlgorithms, - sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, - sGssAuthentication, sGssCleanupCreds, sGssEnablek5users, sGssStrictAcceptor, -- sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel, -+ sGssKeyEx, sGssStoreRekey, sGssKexAlgorithms, sAcceptEnv, sSetEnv, sPermitTunnel, - sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, - sUsePrivilegeSeparation, sAllowAgentForwarding, - sHostCertificate, -@@ -506,6 +510,7 @@ static struct { - { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, - { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, - { "gssapienablek5users", sGssEnablek5users, SSHCFG_ALL }, -+ { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, - #else - { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, - { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, -@@ -513,6 +518,7 @@ static struct { - { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, - { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, - { "gssapienablek5users", sUnsupported, SSHCFG_ALL }, -+ { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL }, - #endif - { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, - { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, -@@ -1273,6 +1279,18 @@ process_server_config_line(ServerOptions - intptr = &options->gss_store_rekey; - goto parse_flag; - -+ case sGssKexAlgorithms: -+ arg = strdelim(&cp); -+ if (!arg || *arg == '\0') -+ fatal("%.200s line %d: Missing argument.", -+ filename, linenum); -+ if (!gss_kex_names_valid(arg)) -+ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.", -+ filename, linenum, arg ? arg : ""); -+ if (*activep && options->gss_kex_algorithms == NULL) -+ options->gss_kex_algorithms = xstrdup(arg); -+ break; -+ - case sPasswordAuthentication: - intptr = &options->password_authentication; - goto parse_flag; -@@ -2304,6 +2322,7 @@ dump_config(ServerOptions *o) - dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); - dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); - dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); -+ dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms); - #endif - dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); - dump_cfg_fmtint(sKbdInteractiveAuthentication, -diff -up openssh-7.0p1/servconf.h.gsskexalg openssh-7.0p1/servconf.h ---- openssh-7.0p1/servconf.h.gsskexalg 2015-08-19 12:28:38.080518834 +0200 -+++ openssh-7.0p1/servconf.h 2015-08-19 12:34:46.328693944 +0200 -@@ -122,6 +122,7 @@ typedef struct { - int gss_cleanup_creds; /* If true, destroy cred cache on logout */ - int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ - int gss_store_rekey; -+ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */ - int password_authentication; /* If true, permit password - * authentication. */ - int kbd_interactive_authentication; /* If true, permit */ -diff -up openssh-7.0p1/ssh.1.gsskexalg openssh-7.0p1/ssh.1 ---- openssh-7.0p1/ssh.1.gsskexalg 2015-08-19 12:28:38.081518832 +0200 -+++ openssh-7.0p1/ssh.1 2015-08-19 12:35:31.741591692 +0200 -@@ -496,6 +496,7 @@ For full details of the options listed b - .It GSSAPIDelegateCredentials - .It GSSAPIRenewalForcesRekey - .It GSSAPITrustDNS -+.It GSSAPIKexAlgorithms - .It HashKnownHosts - .It Host - .It HostbasedAuthentication -diff -up openssh-7.0p1/ssh_config.5.gsskexalg openssh-7.0p1/ssh_config.5 ---- openssh-7.0p1/ssh_config.5.gsskexalg 2015-08-19 12:28:38.028518950 +0200 -+++ openssh-7.0p1/ssh_config.5 2015-08-19 12:28:38.082518830 +0200 -@@ -786,6 +786,18 @@ command line will be passed untouched to - command line will be passed untouched to the GSSAPI library. - The default is - .Dq no . -+.It Cm GSSAPIKexAlgorithms -+The list of key exchange algorithms that are offered for GSSAPI -+key exchange. Possible values are -+.Bd -literal -offset 3n -+gss-gex-sha1-, -+gss-group1-sha1-, -+gss-group14-sha1- -+.Ed -+.Pp -+The default is -+.Dq gss-gex-sha1-,gss-group14-sha1- . -+This option only applies to protocol version 2 connections using GSSAPI. - .It Cm HashKnownHosts - Indicates that - .Xr ssh 1 -diff -up openssh-7.0p1/sshconnect2.c.gsskexalg openssh-7.0p1/sshconnect2.c ---- openssh-7.0p1/sshconnect2.c.gsskexalg 2015-08-19 12:28:38.045518912 +0200 -+++ openssh-7.0p1/sshconnect2.c 2015-08-19 12:28:38.081518832 +0200 -@@ -179,7 +179,8 @@ ssh_kex2(char *host, struct sockaddr *ho - else - gss_host = host; - -- gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); -+ gss = ssh_gssapi_client_mechanisms(gss_host, -+ options.gss_client_identity, options.gss_kex_algorithms); - if (gss) { - debug("Offering GSSAPI proposal: %s", gss); - xasprintf(&options.kex_algorithms, ---- openssh-7.1p1/sshd_config.5.gsskexalg 2015-12-10 15:32:48.105418092 +0100 -+++ openssh-7.1p1/sshd_config.5 2015-12-10 15:33:47.771279548 +0100 -@@ -663,6 +663,18 @@ or updated credentials from a compatible - For this to work - .Cm GSSAPIKeyExchange - needs to be enabled in the server and also used by the client. -+.It Cm GSSAPIKexAlgorithms -+The list of key exchange algorithms that are accepted by GSSAPI -+key exchange. Possible values are -+.Bd -literal -offset 3n -+gss-gex-sha1-, -+gss-group1-sha1-, -+gss-group14-sha1- -+.Ed -+.Pp -+The default is -+.Dq gss-gex-sha1-,gss-group14-sha1- . -+This option only applies to protocol version 2 connections using GSSAPI. - .It Cm HostbasedAcceptedKeyTypes - Specifies the key types that will be accepted for hostbased authentication - as a list of comma-separated patterns. -diff -up openssh-7.0p1/ssh-gss.h.gsskexalg openssh-7.0p1/ssh-gss.h ---- openssh-7.0p1/ssh-gss.h.gsskexalg 2015-08-19 12:28:38.031518944 +0200 -+++ openssh-7.0p1/ssh-gss.h 2015-08-19 12:28:38.081518832 +0200 -@@ -76,6 +76,10 @@ extern char **k5users_allowed_cmds; - #define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" - #define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" - -+#define GSS_KEX_DEFAULT_KEX \ -+ KEX_GSS_GEX_SHA1_ID "," \ -+ KEX_GSS_GRP14_SHA1_ID -+ - typedef struct { - char *envvar; - char *envval; -@@ -147,9 +151,9 @@ int ssh_gssapi_credentials_updated(Gssct - /* In the server */ - typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, - const char *); --char *ssh_gssapi_client_mechanisms(const char *, const char *); -+char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *); - char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, -- const char *); -+ const char *, const char *); - gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); - int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, - const char *); diff --git a/openssh-7.1p1-gssapi-documentation.patch b/openssh-7.1p1-gssapi-documentation.patch deleted file mode 100644 index db689d434e79bb4c0e0df3e4e4c71c18965abf04..0000000000000000000000000000000000000000 --- a/openssh-7.1p1-gssapi-documentation.patch +++ /dev/null @@ -1,52 +0,0 @@ -diff -up openssh-7.4p1/ssh_config.5.gss-docs openssh-7.4p1/ssh_config.5 ---- openssh-7.4p1/ssh_config.5.gss-docs 2016-12-23 14:28:34.051714486 +0100 -+++ openssh-7.4p1/ssh_config.5 2016-12-23 14:34:24.568522417 +0100 -@@ -765,10 +765,19 @@ The default is - If set to - .Dq yes - then renewal of the client's GSSAPI credentials will force the rekeying of the --ssh connection. With a compatible server, this can delegate the renewed -+ssh connection. With a compatible server, this will delegate the renewed - credentials to a session on the server. -+.Pp -+Checks are made to ensure that credentials are only propagated when the new -+credentials match the old ones on the originating client and where the -+receiving server still has the old set in its cache. -+.Pp - The default is - .Dq no . -+.Pp -+For this to work -+.Cm GSSAPIKeyExchange -+needs to be enabled in the server and also used by the client. - .It Cm GSSAPIServerIdentity - If set, specifies the GSSAPI server identity that ssh should expect when - connecting to the server. The default is unset, which means that the -@@ -776,9 +785,11 @@ expected GSSAPI server identity will be - hostname. - .It Cm GSSAPITrustDns - Set to --.Dq yes to indicate that the DNS is trusted to securely canonicalize -+.Dq yes -+to indicate that the DNS is trusted to securely canonicalize - the name of the host being connected to. If --.Dq no, the hostname entered on the -+.Dq no , -+the hostname entered on the - command line will be passed untouched to the GSSAPI library. - The default is - .Dq no . -diff -up openssh-7.4p1/sshd_config.5.gss-docs openssh-7.4p1/sshd_config.5 ---- openssh-7.4p1/sshd_config.5.gss-docs 2016-12-23 14:28:34.043714490 +0100 -+++ openssh-7.4p1/sshd_config.5 2016-12-23 14:28:34.051714486 +0100 -@@ -652,6 +652,10 @@ Controls whether the user's GSSAPI crede - successful connection rekeying. This option can be used to accepted renewed - or updated credentials from a compatible client. The default is - .Dq no . -+.Pp -+For this to work -+.Cm GSSAPIKeyExchange -+needs to be enabled in the server and also used by the client. - .It Cm HostbasedAcceptedKeyTypes - Specifies the key types that will be accepted for hostbased authentication - as a list of comma-separated patterns. diff --git a/openssh-7.1p2-audit-race-condition.patch b/openssh-7.1p2-audit-race-condition.patch index 9a0d9173c5ba54435e27e723143ef0c72d302f1b..9c9a6804735d4f6d762d1ec28de4a1b25c8f9e71 100644 --- a/openssh-7.1p2-audit-race-condition.patch +++ b/openssh-7.1p2-audit-race-condition.patch @@ -56,9 +56,9 @@ diff -up openssh-7.4p1/monitor_wrap.h.audit-race openssh-7.4p1/monitor_wrap.h --- openssh-7.4p1/monitor_wrap.h.audit-race 2016-12-23 16:35:52.694685771 +0100 +++ openssh-7.4p1/monitor_wrap.h 2016-12-23 16:35:52.698685772 +0100 @@ -83,6 +83,8 @@ void mm_audit_unsupported_body(int); - void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t); - void mm_audit_session_key_free_body(int, pid_t, uid_t); - void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t); + void mm_audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t); + void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t); + void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); +int mm_forward_audit_messages(int); +void mm_set_monitor_pipe(int); #endif @@ -82,7 +82,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c return 1; } -+void child_destory_sensitive_data(); ++void child_destory_sensitive_data(struct ssh *ssh); + #define USE_PIPES 1 /* @@ -91,7 +91,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c close(err[0]); #endif -+ child_destory_sensitive_data(); ++ child_destory_sensitive_data(ssh); + /* Do processing for the child (exec command etc). */ do_child(ssh, s, command); @@ -101,7 +101,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c close(ttyfd); + /* Do this early, so we will not block large MOTDs */ -+ child_destory_sensitive_data(); ++ child_destory_sensitive_data(ssh); + /* record login, etc. similar to login(1) */ #ifndef HAVE_OSF_SIA @@ -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(s->command)); + s->command_handle = PRIVSEP(audit_run_command(ssh, s->command)); + if (pipe(paudit) < 0) + fatal("pipe: %s", strerror(errno)); #endif @@ -141,7 +141,7 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c } +void -+child_destory_sensitive_data() ++child_destory_sensitive_data(struct ssh *ssh) +{ +#ifdef SSH_AUDIT_EVENTS + int pparent = paudit[1]; @@ -152,15 +152,15 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c +#endif + + /* remove hostkey from the child's memory */ -+ destroy_sensitive_data(use_privsep); ++ destroy_sensitive_data(ssh, use_privsep); + /* + * We can audit this, because we hacked the pipe to direct the + * messages over postauth child. But this message requires answer + * which we can't do using one-way pipe. + */ -+ packet_destroy_all(0, 1); ++ packet_destroy_all(ssh, 0, 1); + /* XXX this will clean the rest but should not audit anymore */ -+ /* packet_clear_keys(); */ ++ /* packet_clear_keys(ssh); */ + +#ifdef SSH_AUDIT_EVENTS + /* Notify parent that we are done */ @@ -172,15 +172,15 @@ diff -up openssh-7.4p1/session.c.audit-race openssh-7.4p1/session.c * Performs common processing for the child, such as setting up the * environment, closing extra file descriptors, setting the user and group @@ -1554,13 +1608,6 @@ do_child(Session *s, const char *command - struct passwd *pw = s->pw; - int r = 0; + + sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); - /* remove hostkey from the child's memory */ -- destroy_sensitive_data(1); -- packet_clear_keys(); +- destroy_sensitive_data(ssh, 1); +- 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. */ -- packet_destroy_all(0, 1); +- packet_destroy_all(ssh, 0, 1); - /* Force a password change */ if (s->authctxt->force_pwchange) { diff --git a/openssh-7.2p2-k5login_directory.patch b/openssh-7.2p2-k5login_directory.patch index 09369aa122d8060391309543b134cd90548b6d4c..242294a2cdb82184f344ce395bbe93e95394316c 100644 --- a/openssh-7.2p2-k5login_directory.patch +++ b/openssh-7.2p2-k5login_directory.patch @@ -2,10 +2,11 @@ diff --git a/auth-krb5.c b/auth-krb5.c index 2b02a04..19b9364 100644 --- a/auth-krb5.c +++ b/auth-krb5.c -@@ -375,6 +375,22 @@ cleanup: - return -1; +@@ -375,5 +375,21 @@ cleanup: + return (krb5_cc_resolve(ctx, ccname, ccache)); + } } - ++ +/* + * Reads k5login_directory option from the krb5.conf + */ @@ -21,22 +22,21 @@ index 2b02a04..19b9364 100644 + return profile_get_string(p, "libdefaults", "k5login_directory", NULL, NULL, + k5login_directory); +} -+ - krb5_error_code - ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) { - profile_t p; + #endif /* !HEIMDAL */ + #endif /* KRB5 */ diff --git a/auth.h b/auth.h index f9d191c..c432d2f 100644 --- a/auth.h +++ b/auth.h -@@ -222,5 +222,7 @@ int sys_auth_passwd(Authctxt *, const char *); +@@ -222,6 +222,8 @@ int sys_auth_passwd(Authctxt *, const char *); + #if defined(KRB5) && !defined(HEIMDAL) - #include krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *); +krb5_error_code ssh_krb5_get_k5login_directory(krb5_context ctx, + char **k5login_directory); #endif - #endif + + #endif /* AUTH_H */ diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c index a7c0c5f..df8cc9a 100644 --- a/gss-serv-krb5.c diff --git a/openssh-7.2p2-s390-closefrom.patch b/openssh-7.2p2-s390-closefrom.patch index 301a5236fc2bf07864fe1ae91628835180d5f330..363538ca937b04d160a013a45821dc86e5fd1d9e 100644 --- a/openssh-7.2p2-s390-closefrom.patch +++ b/openssh-7.2p2-s390-closefrom.patch @@ -48,5 +48,5 @@ Author: Harald Freudenberger +#endif } (void) closedir(dirp); - } else + return; diff --git a/openssh-7.2p2-x11.patch b/openssh-7.2p2-x11.patch index 48ce840d30eb6bbd1f16595a28083c0abdd4f52f..0a19ecb2948796fe98a0dbdbbd516b0ebf69dd8b 100644 --- a/openssh-7.2p2-x11.patch +++ b/openssh-7.2p2-x11.patch @@ -14,7 +14,7 @@ diff -up openssh-7.2p2/channels.c.x11 openssh-7.2p2/channels.c + if (len <= 0) + return -1; sock = socket(AF_UNIX, SOCK_STREAM, 0); - if (sock < 0) + if (sock == -1) error("socket: %.100s", strerror(errno)); memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; diff --git a/openssh-7.3p1-openssl-1.1.0.patch b/openssh-7.3p1-openssl-1.1.0.patch deleted file mode 100644 index 42ede48494e0000263f57e08b4ce0d0b8e744e39..0000000000000000000000000000000000000000 --- a/openssh-7.3p1-openssl-1.1.0.patch +++ /dev/null @@ -1,2688 +0,0 @@ -diff -up openssh/auth-pam.c.openssl openssh/auth-pam.c ---- openssh/auth-pam.c.openssl 2017-09-26 13:19:31.662248869 +0200 -+++ openssh/auth-pam.c 2017-09-26 13:19:31.793249672 +0200 -@@ -128,6 +128,10 @@ extern u_int utmp_len; - typedef pthread_t sp_pthread_t; - #else - typedef pid_t sp_pthread_t; -+# define pthread_create(a, b, c, d) _ssh_compat_pthread_create(a, b, c, d) -+# define pthread_exit(a) _ssh_compat_pthread_exit(a) -+# define pthread_cancel(a) _ssh_compat_pthread_cancel(a) -+# define pthread_join(a, b) _ssh_compat_pthread_join(a, b) - #endif - - struct pam_ctxt { -diff -up openssh/cipher.c.openssl openssh/cipher.c ---- openssh/cipher.c.openssl 2017-09-26 13:19:31.782249605 +0200 -+++ openssh/cipher.c 2017-09-26 13:27:37.424040367 +0200 -@@ -283,7 +283,7 @@ cipher_init(struct sshcipher_ctx **ccp, - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if (EVP_CipherInit(cc->evp, type, NULL, (u_char *)iv, -+ if (EVP_CipherInit(cc->evp, type, (u_char *)key, (u_char *)iv, - (do_encrypt == CIPHER_ENCRYPT)) == 0) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; -@@ -301,10 +301,6 @@ cipher_init(struct sshcipher_ctx **ccp, - goto out; - } - } -- if (EVP_CipherInit(cc->evp, NULL, (u_char *)key, NULL, -1) == 0) { -- ret = SSH_ERR_LIBCRYPTO_ERROR; -- goto out; -- } - ret = 0; - #endif /* WITH_OPENSSL */ - out: -@@ -490,7 +486,7 @@ cipher_get_keyiv(struct sshcipher_ctx *c - len, iv)) - return SSH_ERR_LIBCRYPTO_ERROR; - } else -- memcpy(iv, cc->evp->iv, len); -+ memcpy(iv, EVP_CIPHER_CTX_iv(cc->evp), len); - #endif - return 0; - } -@@ -524,14 +520,14 @@ cipher_set_keyiv(struct sshcipher_ctx *c - EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv)) - return SSH_ERR_LIBCRYPTO_ERROR; - } else -- memcpy(cc->evp->iv, iv, evplen); -+ memcpy(EVP_CIPHER_CTX_iv_noconst(cc->evp), iv, evplen); - #endif - return 0; - } - - #ifdef WITH_OPENSSL --#define EVP_X_STATE(evp) (evp)->cipher_data --#define EVP_X_STATE_LEN(evp) (evp)->cipher->ctx_size -+#define EVP_X_STATE(evp) EVP_CIPHER_CTX_get_cipher_data(evp) -+#define EVP_X_STATE_LEN(evp) EVP_CIPHER_impl_ctx_size(EVP_CIPHER_CTX_cipher(evp)) - #endif - - int -diff -up openssh/ctr-cavstest.c.openssl openssh/ctr-cavstest.c ---- openssh/ctr-cavstest.c.openssl 2017-09-26 13:19:31.707249145 +0200 -+++ openssh/ctr-cavstest.c 2017-09-26 13:19:31.794249679 +0200 -@@ -144,7 +144,7 @@ int main (int argc, char *argv[]) - usage(); - } - -- SSLeay_add_all_algorithms(); -+ OpenSSL_add_all_algorithms(); - - c = cipher_by_name(algo); - if (c == NULL) { -diff -up openssh/dh.c.openssl openssh/dh.c ---- openssh/dh.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/dh.c 2017-09-26 13:19:31.794249679 +0200 -@@ -212,14 +212,15 @@ choose_dh(int min, int wantbits, int max - /* diffie-hellman-groupN-sha1 */ - - int --dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) -+dh_pub_is_valid(const DH *dh, const BIGNUM *dh_pub) - { - int i; - int n = BN_num_bits(dh_pub); - int bits_set = 0; - BIGNUM *tmp; -+ const BIGNUM *p; - -- if (dh_pub->neg) { -+ if (BN_is_negative(dh_pub)) { - logit("invalid public DH value: negative"); - return 0; - } -@@ -232,7 +233,8 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) - error("%s: BN_new failed", __func__); - return 0; - } -- if (!BN_sub(tmp, dh->p, BN_value_one()) || -+ DH_get0_pqg(dh, &p, NULL, NULL); -+ if (!BN_sub(tmp, p, BN_value_one()) || - BN_cmp(dh_pub, tmp) != -1) { /* pub_exp > p-2 */ - BN_clear_free(tmp); - logit("invalid public DH value: >= p-1"); -@@ -243,14 +245,14 @@ dh_pub_is_valid(DH *dh, BIGNUM *dh_pub) - for (i = 0; i <= n; i++) - if (BN_is_bit_set(dh_pub, i)) - bits_set++; -- debug2("bits set: %d/%d", bits_set, BN_num_bits(dh->p)); -+ debug2("bits set: %d/%d", bits_set, BN_num_bits(p)); - - /* - * if g==2 and bits_set==1 then computing log_g(dh_pub) is trivial - */ - if (bits_set < 4) { - logit("invalid public DH value (%d/%d)", -- bits_set, BN_num_bits(dh->p)); -+ bits_set, BN_num_bits(p)); - return 0; - } - return 1; -@@ -260,9 +262,11 @@ int - dh_gen_key(DH *dh, int need) - { - int pbits; -+ const BIGNUM *p, *pub_key; - -- if (need < 0 || dh->p == NULL || -- (pbits = BN_num_bits(dh->p)) <= 0 || -+ DH_get0_pqg(dh, &p, NULL, NULL); -+ if (need < 0 || p == NULL || -+ (pbits = BN_num_bits(p)) <= 0 || - need > INT_MAX / 2 || 2 * need > pbits) - return SSH_ERR_INVALID_ARGUMENT; - if (need < 256) -@@ -271,11 +275,11 @@ dh_gen_key(DH *dh, int need) - * Pollard Rho, Big step/Little Step attacks are O(sqrt(n)), - * so double requested need here. - */ -- dh->length = MINIMUM(need * 2, pbits - 1); -- if (DH_generate_key(dh) == 0 || -- !dh_pub_is_valid(dh, dh->pub_key)) { -- BN_clear_free(dh->priv_key); -- dh->priv_key = NULL; -+ DH_set_length(dh, MINIMUM(need * 2, pbits - 1)); -+ 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_LIBCRYPTO_ERROR; - } - return 0; -@@ -284,15 +289,22 @@ DH * - dh_new_group_asc(const char *gen, const char *modulus) - { - DH *dh; -+ BIGNUM *p = NULL, *g = NULL; - -- if ((dh = DH_new()) == NULL) -- return NULL; -- if (BN_hex2bn(&dh->p, modulus) == 0 || -- BN_hex2bn(&dh->g, gen) == 0) { -- DH_free(dh); -- return NULL; -- } -+ if ((dh = DH_new()) == NULL || -+ (p = BN_new()) == NULL || -+ (g = BN_new()) == NULL) -+ goto err; -+ if (BN_hex2bn(&p, modulus) == 0 || -+ BN_hex2bn(&g, gen) == 0 || -+ DH_set0_pqg(dh, p, NULL, g) == 0) -+ goto err; - return (dh); -+err: -+ DH_free(dh); -+ BN_free(p); -+ BN_free(g); -+ return NULL; - } - - /* -@@ -307,8 +319,7 @@ dh_new_group(BIGNUM *gen, BIGNUM *modulu - - if ((dh = DH_new()) == NULL) - return NULL; -- dh->p = modulus; -- dh->g = gen; -+ DH_set0_pqg(dh, modulus, NULL, gen); - - return (dh); - } -diff -up openssh/dh.h.openssl openssh/dh.h ---- openssh/dh.h.openssl 2017-09-26 13:19:31.783249611 +0200 -+++ openssh/dh.h 2017-09-26 13:19:31.794249679 +0200 -@@ -42,7 +42,7 @@ DH *dh_new_group18(void); - DH *dh_new_group_fallback(int); - - int dh_gen_key(DH *, int); --int dh_pub_is_valid(DH *, BIGNUM *); -+int dh_pub_is_valid(const DH *, const BIGNUM *); - - u_int dh_estimate(int); - -diff -up openssh/digest-openssl.c.openssl openssh/digest-openssl.c ---- openssh/digest-openssl.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/digest-openssl.c 2017-09-26 13:19:31.795249685 +0200 -@@ -43,7 +43,7 @@ - - struct ssh_digest_ctx { - int alg; -- EVP_MD_CTX mdctx; -+ EVP_MD_CTX *mdctx; - }; - - struct ssh_digest { -@@ -106,7 +106,7 @@ ssh_digest_bytes(int alg) - size_t - ssh_digest_blocksize(struct ssh_digest_ctx *ctx) - { -- return EVP_MD_CTX_block_size(&ctx->mdctx); -+ return EVP_MD_CTX_block_size(ctx->mdctx); - } - - struct ssh_digest_ctx * -@@ -118,8 +118,10 @@ ssh_digest_start(int alg) - if (digest == NULL || ((ret = calloc(1, sizeof(*ret))) == NULL)) - return NULL; - ret->alg = alg; -- EVP_MD_CTX_init(&ret->mdctx); -- if (EVP_DigestInit_ex(&ret->mdctx, digest->mdfunc(), NULL) != 1) { -+ ret->mdctx = EVP_MD_CTX_new(); -+ if (ret->mdctx == NULL || -+ EVP_DigestInit_ex(ret->mdctx, digest->mdfunc(), NULL) != 1) { -+ EVP_MD_CTX_free(ret->mdctx); - free(ret); - return NULL; - } -@@ -132,7 +133,7 @@ ssh_digest_copy_state(struct ssh_digest_ - if (from->alg != to->alg) - return SSH_ERR_INVALID_ARGUMENT; - /* we have bcopy-style order while openssl has memcpy-style */ -- if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx)) -+ if (!EVP_MD_CTX_copy_ex(to->mdctx, from->mdctx)) - return SSH_ERR_LIBCRYPTO_ERROR; - return 0; - } -@@ -140,7 +141,7 @@ ssh_digest_copy_state(struct ssh_digest_ - int - ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) - { -- if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) -+ if (EVP_DigestUpdate(ctx->mdctx, m, mlen) != 1) - return SSH_ERR_LIBCRYPTO_ERROR; - return 0; - } -@@ -161,7 +162,7 @@ ssh_digest_final(struct ssh_digest_ctx * - return SSH_ERR_INVALID_ARGUMENT; - if (dlen < digest->digest_len) /* No truncation allowed */ - return SSH_ERR_INVALID_ARGUMENT; -- if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1) -+ if (EVP_DigestFinal_ex(ctx->mdctx, d, &l) != 1) - return SSH_ERR_LIBCRYPTO_ERROR; - if (l != digest->digest_len) /* sanity */ - return SSH_ERR_INTERNAL_ERROR; -@@ -172,7 +173,7 @@ void - ssh_digest_free(struct ssh_digest_ctx *ctx) - { - if (ctx != NULL) { -- EVP_MD_CTX_cleanup(&ctx->mdctx); -+ EVP_MD_CTX_free(ctx->mdctx); - explicit_bzero(ctx, sizeof(*ctx)); - free(ctx); - } -diff -up openssh/entropy.c.openssl openssh/entropy.c ---- openssh/entropy.c.openssl 2017-09-26 13:19:31.783249611 +0200 -+++ openssh/entropy.c 2017-09-26 13:19:31.795249685 +0200 -@@ -218,7 +218,9 @@ seed_rng(void) - "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); - - /* clean the PRNG status when exiting the program */ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L - atexit(RAND_cleanup); -+#endif - - #ifndef OPENSSL_PRNG_ONLY - if (RAND_status() == 1) { -diff -up openssh/gss-genr.c.openssl openssh/gss-genr.c ---- openssh/gss-genr.c.openssl 2017-09-26 13:19:31.773249550 +0200 -+++ openssh/gss-genr.c 2017-09-26 13:19:31.796249691 +0200 -@@ -99,7 +99,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup - u_char digest[EVP_MAX_MD_SIZE]; - char deroid[2]; - const EVP_MD *evp_md = EVP_md5(); -- EVP_MD_CTX md; -+ EVP_MD_CTX *md; - char *s, *cp, *p; - - if (gss_enc2oid != NULL) { -@@ -113,6 +113,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup - if ((buf = sshbuf_new()) == NULL) - fatal("%s: sshbuf_new failed", __func__); - -+ md = EVP_MD_CTX_new(); - oidpos = 0; - s = cp = xstrdup(kex); - for (i = 0; i < gss_supported->count; i++) { -@@ -122,12 +123,13 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup - deroid[0] = SSH_GSS_OIDTYPE; - deroid[1] = gss_supported->elements[i].length; - -- EVP_DigestInit(&md, evp_md); -- EVP_DigestUpdate(&md, deroid, 2); -- EVP_DigestUpdate(&md, -+ EVP_MD_CTX_reset(md); -+ EVP_DigestInit(md, evp_md); -+ EVP_DigestUpdate(md, deroid, 2); -+ EVP_DigestUpdate(md, - gss_supported->elements[i].elements, - gss_supported->elements[i].length); -- EVP_DigestFinal(&md, digest, NULL); -+ EVP_DigestFinal(md, digest, NULL); - - encoded = xmalloc(EVP_MD_size(evp_md) * 2); - enclen = __b64_ntop(digest, EVP_MD_size(evp_md), -@@ -149,6 +151,7 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_sup - } - } - free(s); -+ EVP_MD_CTX_free(md); - gss_enc2oid[oidpos].oid = NULL; - gss_enc2oid[oidpos].encoded = NULL; - -diff -up openssh/includes.h.openssl openssh/includes.h ---- openssh/includes.h.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/includes.h 2017-09-26 13:19:31.796249691 +0200 -@@ -166,6 +166,7 @@ - - #ifdef WITH_OPENSSL - #include /* For OPENSSL_VERSION_NUMBER */ -+#include "libcrypto-compat.h" - #endif - - #include "defines.h" -diff -up openssh/kexdhc.c.openssl openssh/kexdhc.c ---- openssh/kexdhc.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/kexdhc.c 2017-09-26 13:19:31.797249697 +0200 -@@ -56,6 +56,7 @@ kexdh_client(struct ssh *ssh) - { - struct kex *kex = ssh->kex; - int r; -+ const BIGNUM *pub_key; - - /* generate and send 'e', client DH public key */ - switch (kex->kex_type) { -@@ -81,21 +82,27 @@ kexdh_client(struct ssh *ssh) - goto out; - } - debug("sending SSH2_MSG_KEXDH_INIT"); -- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || -- (r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || -- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || -+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) -+ goto out; -+ DH_get0_key(kex->dh, &pub_key, NULL); -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_INIT)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - #ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "pub= "); -- BN_print_fp(stderr, kex->dh->pub_key); -+ BN_print_fp(stderr, pub_key); - fprintf(stderr, "\n"); - #endif - debug("expecting SSH2_MSG_KEXDH_REPLY"); - ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_REPLY, &input_kex_dh); - r = 0; - out: -+ if (r != 0) { -+ DH_free(kex->dh); -+ kex->dh = NULL; -+ } - return r; - } - -@@ -109,6 +116,7 @@ input_kex_dh(int type, u_int32_t seq, st - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t klen = 0, slen, sbloblen, hashlen; - int kout, r; -+ const BIGNUM *pub_key; - - if (kex->verify_host_key == NULL) { - r = SSH_ERR_INVALID_ARGUMENT; -@@ -168,6 +176,7 @@ input_kex_dh(int type, u_int32_t seq, st - #endif - - /* calc and verify H */ -+ DH_get0_key(kex->dh, &pub_key, NULL); - hashlen = sizeof(hash); - if ((r = kex_dh_hash( - kex->hash_alg, -@@ -176,7 +185,7 @@ input_kex_dh(int type, u_int32_t seq, st - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - server_host_key_blob, sbloblen, -- kex->dh->pub_key, -+ pub_key, - dh_server_pub, - shared_secret, - hash, &hashlen)) != 0) -diff -up openssh/kexdhs.c.openssl openssh/kexdhs.c ---- openssh/kexdhs.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/kexdhs.c 2017-09-26 13:19:31.797249697 +0200 -@@ -87,6 +87,10 @@ kexdh_server(struct ssh *ssh) - ssh_dispatch_set(ssh, SSH2_MSG_KEXDH_INIT, &input_kex_dh_init); - r = 0; - out: -+ if (r != 0) { -+ DH_free(kex->dh); -+ kex->dh = NULL; -+ } - return r; - } - -@@ -101,6 +105,7 @@ input_kex_dh_init(int type, u_int32_t se - size_t sbloblen, slen; - size_t klen = 0, hashlen; - int kout, r; -+ const BIGNUM *pub_key; - - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) { -@@ -163,6 +168,7 @@ input_kex_dh_init(int type, u_int32_t se - goto out; - /* calc H */ - hashlen = sizeof(hash); -+ DH_get0_key(kex->dh, &pub_key, NULL); - if ((r = kex_dh_hash( - kex->hash_alg, - kex->client_version_string, -@@ -171,7 +177,7 @@ input_kex_dh_init(int type, u_int32_t se - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - server_host_key_blob, sbloblen, - dh_client_pub, -- kex->dh->pub_key, -+ pub_key, - shared_secret, - hash, &hashlen)) != 0) - goto out; -@@ -197,7 +203,7 @@ input_kex_dh_init(int type, u_int32_t se - /* send server hostkey, DH pubkey 'f' and signed H */ - if ((r = sshpkt_start(ssh, SSH2_MSG_KEXDH_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || -- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ -+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */ - (r = sshpkt_put_string(ssh, signature, slen)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; -diff -up openssh/kexgexc.c.openssl openssh/kexgexc.c ---- openssh/kexgexc.c.openssl 2017-09-26 13:19:31.783249611 +0200 -+++ openssh/kexgexc.c 2017-09-26 13:19:31.797249697 +0200 -@@ -95,6 +95,7 @@ input_kex_dh_gex_group(int type, u_int32 - struct kex *kex = ssh->kex; - BIGNUM *p = NULL, *g = NULL; - int r, bits; -+ const BIGNUM *pub_key; - - debug("got SSH2_MSG_KEX_DH_GEX_GROUP"); - -@@ -119,24 +120,30 @@ input_kex_dh_gex_group(int type, u_int32 - p = g = NULL; /* belong to kex->dh now */ - - /* generate and send 'e', client DH public key */ -- if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0 || -- (r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || -- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || -+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) -+ goto out; -+ DH_get0_key(kex->dh, &pub_key, NULL); -+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_INIT)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - debug("SSH2_MSG_KEX_DH_GEX_INIT sent"); - #ifdef DEBUG_KEXDH - DHparams_print_fp(stderr, kex->dh); - fprintf(stderr, "pub= "); -- BN_print_fp(stderr, kex->dh->pub_key); -+ BN_print_fp(stderr, pub_key); - fprintf(stderr, "\n"); - #endif - ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_GROUP, NULL); - ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_REPLY, &input_kex_dh_gex_reply); - r = 0; - out: - BN_clear_free(p); - BN_clear_free(g); -+ if (r != 0) { -+ DH_free(kex->dh); -+ kex->dh = NULL; -+ } - return r; - } - -@@ -152,6 +157,7 @@ input_kex_dh_gex_reply(int type, u_int32 - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t klen = 0, slen, sbloblen, hashlen; - int kout, r; -+ const BIGNUM *p, *g, *pub_key; - - debug("got SSH2_MSG_KEX_DH_GEX_REPLY"); - if (kex->verify_host_key == NULL) { -@@ -214,6 +220,8 @@ input_kex_dh_gex_reply(int type, u_int32 - kex->min = kex->max = -1; - - /* calc and verify H */ -+ DH_get0_pqg(kex->dh, &p, NULL, &g); -+ DH_get0_key(kex->dh, &pub_key, NULL); - hashlen = sizeof(hash); - if ((r = kexgex_hash( - kex->hash_alg, -@@ -223,8 +231,8 @@ input_kex_dh_gex_reply(int type, u_int32 - sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), - server_host_key_blob, sbloblen, - kex->min, kex->nbits, kex->max, -- kex->dh->p, kex->dh->g, -- kex->dh->pub_key, -+ p, g, -+ pub_key, - dh_server_pub, - shared_secret, - hash, &hashlen)) != 0) -diff -up openssh/kexgexs.c.openssl openssh/kexgexs.c ---- openssh/kexgexs.c.openssl 2017-09-26 13:19:31.783249611 +0200 -+++ openssh/kexgexs.c 2017-09-26 13:19:31.797249697 +0200 -@@ -72,6 +72,7 @@ input_kex_dh_gex_request(int type, u_int - struct kex *kex = ssh->kex; - int r; - u_int min = 0, max = 0, nbits = 0; -+ const BIGNUM *p, *g; - - debug("SSH2_MSG_KEX_DH_GEX_REQUEST received"); - if ((r = sshpkt_get_u32(ssh, &min)) != 0 || -@@ -101,9 +102,10 @@ input_kex_dh_gex_request(int type, u_int - goto out; - } - debug("SSH2_MSG_KEX_DH_GEX_GROUP sent"); -+ DH_get0_pqg(kex->dh, &p, NULL, &g); - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_GROUP)) != 0 || -- (r = sshpkt_put_bignum2(ssh, kex->dh->p)) != 0 || -- (r = sshpkt_put_bignum2(ssh, kex->dh->g)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, p)) != 0 || -+ (r = sshpkt_put_bignum2(ssh, g)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; - -@@ -115,6 +117,10 @@ input_kex_dh_gex_request(int type, u_int - ssh_dispatch_set(ssh, SSH2_MSG_KEX_DH_GEX_INIT, &input_kex_dh_gex_init); - r = 0; - out: -+ if (r != 0) { -+ DH_free(kex->dh); -+ kex->dh = NULL; -+ } - return r; - } - -@@ -129,6 +135,7 @@ input_kex_dh_gex_init(int type, u_int32_ - size_t sbloblen, slen; - size_t klen = 0, hashlen; - int kout, r; -+ const BIGNUM *p, *g, *pub_key; - - if (kex->load_host_public_key == NULL || - kex->load_host_private_key == NULL) { -@@ -191,6 +198,8 @@ input_kex_dh_gex_init(int type, u_int32_ - goto out; - /* calc H */ - hashlen = sizeof(hash); -+ DH_get0_pqg(kex->dh, &p, NULL, &g); -+ DH_get0_key(kex->dh, &pub_key, NULL); - if ((r = kexgex_hash( - kex->hash_alg, - kex->client_version_string, -@@ -199,9 +208,9 @@ input_kex_dh_gex_init(int type, u_int32_ - sshbuf_ptr(kex->my), sshbuf_len(kex->my), - server_host_key_blob, sbloblen, - kex->min, kex->nbits, kex->max, -- kex->dh->p, kex->dh->g, -+ p, g, - dh_client_pub, -- kex->dh->pub_key, -+ pub_key, - shared_secret, - hash, &hashlen)) != 0) - goto out; -@@ -227,7 +236,7 @@ input_kex_dh_gex_init(int type, u_int32_ - /* send server hostkey, DH pubkey 'f' and signed H */ - if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_DH_GEX_REPLY)) != 0 || - (r = sshpkt_put_string(ssh, server_host_key_blob, sbloblen)) != 0 || -- (r = sshpkt_put_bignum2(ssh, kex->dh->pub_key)) != 0 || /* f */ -+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || /* f */ - (r = sshpkt_put_string(ssh, signature, slen)) != 0 || - (r = sshpkt_send(ssh)) != 0) - goto out; -diff -up openssh/kexgssc.c.openssl openssh/kexgssc.c ---- openssh/kexgssc.c.openssl 2017-09-26 13:19:31.771249537 +0200 -+++ openssh/kexgssc.c 2017-09-26 13:19:31.797249697 +0200 -@@ -59,6 +59,7 @@ kexgss_client(struct ssh *ssh) { - BIGNUM *shared_secret = NULL; - BIGNUM *p = NULL; - BIGNUM *g = NULL; -+ const BIGNUM *pub_key, *p1, *g1; - u_char *kbuf; - u_char *serverhostkey = NULL; - u_char *empty = ""; -@@ -126,6 +127,7 @@ kexgss_client(struct ssh *ssh) { - - /* Step 1 - e is dh->pub_key */ - dh_gen_key(dh, ssh->kex->we_need * 8); -+ DH_get0_key(dh, &pub_key, NULL); - - /* This is f, we initialise it now to make life easier */ - dh_server_pub = BN_new(); -@@ -173,7 +175,7 @@ kexgss_client(struct ssh *ssh) { - packet_start(SSH2_MSG_KEXGSS_INIT); - packet_put_string(send_tok.value, - send_tok.length); -- packet_put_bignum2(dh->pub_key); -+ packet_put_bignum2((BIGNUM *)pub_key); - first = 0; - } else { - packet_start(SSH2_MSG_KEXGSS_CONTINUE); -@@ -282,13 +284,14 @@ kexgss_client(struct ssh *ssh) { - sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), - sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), - (serverhostkey ? serverhostkey : empty), slen, -- dh->pub_key, /* e */ -+ pub_key, /* e */ - dh_server_pub, /* f */ - shared_secret, /* K */ - hash, &hashlen - ); - break; - case KEX_GSS_GEX_SHA1: -+ DH_get0_pqg(dh, &p1, NULL, &g1); - kexgex_hash( - ssh->kex->hash_alg, - ssh->kex->client_version_string, -@@ -297,8 +300,8 @@ kexgss_client(struct ssh *ssh) { - sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), - (serverhostkey ? serverhostkey : empty), slen, - min, nbits, max, -- dh->p, dh->g, -- dh->pub_key, -+ p1, g1, -+ pub_key, - dh_server_pub, - shared_secret, - hash, &hashlen -diff -up openssh/kexgsss.c.openssl openssh/kexgsss.c ---- openssh/kexgsss.c.openssl 2017-09-26 13:19:31.771249537 +0200 -+++ openssh/kexgsss.c 2017-09-26 13:19:31.798249703 +0200 -@@ -78,6 +78,7 @@ kexgss_server(struct ssh *ssh) - char *mechs; - u_char hash[SSH_DIGEST_MAX_LENGTH]; - size_t hashlen; -+ const BIGNUM *p, *g, *pub_key; - - /* Initialise GSSAPI */ - -@@ -127,9 +128,10 @@ kexgss_server(struct ssh *ssh) - if (dh == NULL) - packet_disconnect("Protocol error: no matching group found"); - -+ DH_get0_pqg(dh, &p, NULL, &g); - packet_start(SSH2_MSG_KEXGSS_GROUP); -- packet_put_bignum2(dh->p); -- packet_put_bignum2(dh->g); -+ packet_put_bignum2((BIGNUM *)p); -+ packet_put_bignum2((BIGNUM *)g); - packet_send(); - - packet_write_wait(); -@@ -221,6 +223,7 @@ kexgss_server(struct ssh *ssh) - memset(kbuf, 0, klen); - free(kbuf); - -+ DH_get0_key(dh, &pub_key, NULL); - hashlen = sizeof(hash); - switch (ssh->kex->kex_type) { - case KEX_GSS_GRP1_SHA1: -@@ -232,7 +235,7 @@ kexgss_server(struct ssh *ssh) - sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), - sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), - NULL, 0, /* Change this if we start sending host keys */ -- dh_client_pub, dh->pub_key, shared_secret, -+ dh_client_pub, pub_key, shared_secret, - hash, &hashlen - ); - break; -@@ -244,9 +247,9 @@ kexgss_server(struct ssh *ssh) - sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), - NULL, 0, - cmin, nbits, cmax, -- dh->p, dh->g, -+ p, g, - dh_client_pub, -- dh->pub_key, -+ pub_key, - shared_secret, - hash, &hashlen - ); -@@ -270,7 +273,7 @@ kexgss_server(struct ssh *ssh) - fatal("Couldn't get MIC"); - - packet_start(SSH2_MSG_KEXGSS_COMPLETE); -- packet_put_bignum2(dh->pub_key); -+ packet_put_bignum2((BIGNUM *)pub_key); - packet_put_string(msg_tok.value,msg_tok.length); - - if (send_tok.length != 0) { -diff -up openssh/libcrypto-compat.c.openssl openssh/libcrypto-compat.c ---- openssh/libcrypto-compat.c.openssl 2017-09-26 13:19:31.798249703 +0200 -+++ openssh/libcrypto-compat.c 2017-09-26 13:19:31.798249703 +0200 -@@ -0,0 +1,428 @@ -+/* -+ * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. -+ * -+ * Licensed under the OpenSSL license (the "License"). You may not use -+ * this file except in compliance with the License. You can obtain a copy -+ * in the file LICENSE in the source distribution or at -+ * https://www.openssl.org/source/license.html -+ */ -+ -+#include "includes.h" -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ -+#include -+#include -+ -+static void *OPENSSL_zalloc(size_t num) -+{ -+ void *ret = OPENSSL_malloc(num); -+ -+ if (ret != NULL) -+ memset(ret, 0, num); -+ return ret; -+} -+ -+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) -+{ -+ /* If the fields n and e in r are NULL, the corresponding input -+ * parameters MUST be non-NULL for n and e. d may be -+ * left NULL (in case only the public key is used). -+ */ -+ if ((r->n == NULL && n == NULL) -+ || (r->e == NULL && e == NULL)) -+ return 0; -+ -+ if (n != NULL) { -+ BN_free(r->n); -+ r->n = n; -+ } -+ if (e != NULL) { -+ BN_free(r->e); -+ r->e = e; -+ } -+ if (d != NULL) { -+ BN_free(r->d); -+ r->d = d; -+ } -+ -+ return 1; -+} -+ -+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q) -+{ -+ /* If the fields p and q in r are NULL, the corresponding input -+ * parameters MUST be non-NULL. -+ */ -+ if ((r->p == NULL && p == NULL) -+ || (r->q == NULL && q == NULL)) -+ return 0; -+ -+ if (p != NULL) { -+ BN_free(r->p); -+ r->p = p; -+ } -+ if (q != NULL) { -+ BN_free(r->q); -+ r->q = q; -+ } -+ -+ return 1; -+} -+ -+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp) -+{ -+ /* If the fields dmp1, dmq1 and iqmp in r are NULL, the corresponding input -+ * parameters MUST be non-NULL. -+ */ -+ if ((r->dmp1 == NULL && dmp1 == NULL) -+ || (r->dmq1 == NULL && dmq1 == NULL) -+ || (r->iqmp == NULL && iqmp == NULL)) -+ return 0; -+ -+ if (dmp1 != NULL) { -+ BN_free(r->dmp1); -+ r->dmp1 = dmp1; -+ } -+ if (dmq1 != NULL) { -+ BN_free(r->dmq1); -+ r->dmq1 = dmq1; -+ } -+ if (iqmp != NULL) { -+ BN_free(r->iqmp); -+ r->iqmp = iqmp; -+ } -+ -+ return 1; -+} -+ -+void RSA_get0_key(const RSA *r, -+ const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) -+{ -+ if (n != NULL) -+ *n = r->n; -+ if (e != NULL) -+ *e = r->e; -+ if (d != NULL) -+ *d = r->d; -+} -+ -+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) -+{ -+ if (p != NULL) -+ *p = r->p; -+ if (q != NULL) -+ *q = r->q; -+} -+ -+void RSA_get0_crt_params(const RSA *r, -+ const BIGNUM **dmp1, const BIGNUM **dmq1, -+ const BIGNUM **iqmp) -+{ -+ if (dmp1 != NULL) -+ *dmp1 = r->dmp1; -+ if (dmq1 != NULL) -+ *dmq1 = r->dmq1; -+ if (iqmp != NULL) -+ *iqmp = r->iqmp; -+} -+ -+void DSA_get0_pqg(const DSA *d, -+ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) -+{ -+ if (p != NULL) -+ *p = d->p; -+ if (q != NULL) -+ *q = d->q; -+ if (g != NULL) -+ *g = d->g; -+} -+ -+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g) -+{ -+ /* If the fields p, q and g in d are NULL, the corresponding input -+ * parameters MUST be non-NULL. -+ */ -+ if ((d->p == NULL && p == NULL) -+ || (d->q == NULL && q == NULL) -+ || (d->g == NULL && g == NULL)) -+ return 0; -+ -+ if (p != NULL) { -+ BN_free(d->p); -+ d->p = p; -+ } -+ if (q != NULL) { -+ BN_free(d->q); -+ d->q = q; -+ } -+ if (g != NULL) { -+ BN_free(d->g); -+ d->g = g; -+ } -+ -+ return 1; -+} -+ -+void DSA_get0_key(const DSA *d, -+ const BIGNUM **pub_key, const BIGNUM **priv_key) -+{ -+ if (pub_key != NULL) -+ *pub_key = d->pub_key; -+ if (priv_key != NULL) -+ *priv_key = d->priv_key; -+} -+ -+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key) -+{ -+ /* If the field pub_key in d is NULL, the corresponding input -+ * parameters MUST be non-NULL. The priv_key field may -+ * be left NULL. -+ */ -+ if (d->pub_key == NULL && pub_key == NULL) -+ return 0; -+ -+ if (pub_key != NULL) { -+ BN_free(d->pub_key); -+ d->pub_key = pub_key; -+ } -+ if (priv_key != NULL) { -+ BN_free(d->priv_key); -+ d->priv_key = priv_key; -+ } -+ -+ return 1; -+} -+ -+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) -+{ -+ if (pr != NULL) -+ *pr = sig->r; -+ if (ps != NULL) -+ *ps = sig->s; -+} -+ -+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s) -+{ -+ if (r == NULL || s == NULL) -+ return 0; -+ BN_clear_free(sig->r); -+ BN_clear_free(sig->s); -+ sig->r = r; -+ sig->s = s; -+ return 1; -+} -+ -+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) -+{ -+ if (pr != NULL) -+ *pr = sig->r; -+ if (ps != NULL) -+ *ps = sig->s; -+} -+ -+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) -+{ -+ if (r == NULL || s == NULL) -+ return 0; -+ BN_clear_free(sig->r); -+ BN_clear_free(sig->s); -+ sig->r = r; -+ sig->s = s; -+ return 1; -+} -+ -+void DH_get0_pqg(const DH *dh, -+ const BIGNUM **p, const BIGNUM **q, const BIGNUM **g) -+{ -+ if (p != NULL) -+ *p = dh->p; -+ if (q != NULL) -+ *q = dh->q; -+ if (g != NULL) -+ *g = dh->g; -+} -+ -+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) -+{ -+ /* If the fields p and g in d are NULL, the corresponding input -+ * parameters MUST be non-NULL. q may remain NULL. -+ */ -+ if ((dh->p == NULL && p == NULL) -+ || (dh->g == NULL && g == NULL)) -+ return 0; -+ -+ if (p != NULL) { -+ BN_free(dh->p); -+ dh->p = p; -+ } -+ if (q != NULL) { -+ BN_free(dh->q); -+ dh->q = q; -+ } -+ if (g != NULL) { -+ BN_free(dh->g); -+ dh->g = g; -+ } -+ -+ if (q != NULL) { -+ dh->length = BN_num_bits(q); -+ } -+ -+ return 1; -+} -+ -+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key) -+{ -+ if (pub_key != NULL) -+ *pub_key = dh->pub_key; -+ if (priv_key != NULL) -+ *priv_key = dh->priv_key; -+} -+ -+int DH_set_length(DH *dh, long length) -+{ -+ dh->length = length; -+ return 1; -+} -+ -+const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx) -+{ -+ return ctx->iv; -+} -+ -+unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx) -+{ -+ return ctx->iv; -+} -+ -+EVP_MD_CTX *EVP_MD_CTX_new(void) -+{ -+ return OPENSSL_zalloc(sizeof(EVP_MD_CTX)); -+} -+ -+static void OPENSSL_clear_free(void *str, size_t num) -+{ -+ if (str == NULL) -+ return; -+ if (num) -+ OPENSSL_cleanse(str, num); -+ OPENSSL_free(str); -+} -+ -+/* This call frees resources associated with the context */ -+int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) -+{ -+ if (ctx == NULL) -+ return 1; -+ -+ /* -+ * Don't assume ctx->md_data was cleaned in EVP_Digest_Final, because -+ * sometimes only copies of the context are ever finalised. -+ */ -+ if (ctx->digest && ctx->digest->cleanup -+ && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_CLEANED)) -+ ctx->digest->cleanup(ctx); -+ if (ctx->digest && ctx->digest->ctx_size && ctx->md_data -+ && !EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_REUSE)) { -+ OPENSSL_clear_free(ctx->md_data, ctx->digest->ctx_size); -+ } -+ EVP_PKEY_CTX_free(ctx->pctx); -+#ifndef OPENSSL_NO_ENGINE -+ ENGINE_finish(ctx->engine); -+#endif -+ OPENSSL_cleanse(ctx, sizeof(*ctx)); -+ -+ return 1; -+} -+ -+void EVP_MD_CTX_free(EVP_MD_CTX *ctx) -+{ -+ EVP_MD_CTX_reset(ctx); -+ OPENSSL_free(ctx); -+} -+ -+RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth) -+{ -+ RSA_METHOD *ret; -+ -+ ret = OPENSSL_malloc(sizeof(RSA_METHOD)); -+ -+ if (ret != NULL) { -+ memcpy(ret, meth, sizeof(*meth)); -+ ret->name = OPENSSL_strdup(meth->name); -+ if (ret->name == NULL) { -+ OPENSSL_free(ret); -+ return NULL; -+ } -+ } -+ -+ return ret; -+} -+ -+int RSA_meth_set1_name(RSA_METHOD *meth, const char *name) -+{ -+ char *tmpname; -+ -+ tmpname = OPENSSL_strdup(name); -+ if (tmpname == NULL) { -+ return 0; -+ } -+ -+ OPENSSL_free((char *)meth->name); -+ meth->name = tmpname; -+ -+ return 1; -+} -+ -+int RSA_meth_set_priv_enc(RSA_METHOD *meth, -+ int (*priv_enc) (int flen, const unsigned char *from, -+ unsigned char *to, RSA *rsa, -+ int padding)) -+{ -+ meth->rsa_priv_enc = priv_enc; -+ return 1; -+} -+ -+int RSA_meth_set_priv_dec(RSA_METHOD *meth, -+ int (*priv_dec) (int flen, const unsigned char *from, -+ unsigned char *to, RSA *rsa, -+ int padding)) -+{ -+ meth->rsa_priv_dec = priv_dec; -+ return 1; -+} -+ -+int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa)) -+{ -+ meth->finish = finish; -+ return 1; -+} -+ -+void RSA_meth_free(RSA_METHOD *meth) -+{ -+ if (meth != NULL) { -+ OPENSSL_free((char *)meth->name); -+ OPENSSL_free(meth); -+ } -+} -+ -+int RSA_bits(const RSA *r) -+{ -+ return (BN_num_bits(r->n)); -+} -+ -+int DSA_bits(const DSA *dsa) -+{ -+ return BN_num_bits(dsa->p); -+} -+ -+RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey) -+{ -+ if (pkey->type != EVP_PKEY_RSA) { -+ return NULL; -+ } -+ return pkey->pkey.rsa; -+} -+ -+#endif /* OPENSSL_VERSION_NUMBER */ -diff -up openssh/libcrypto-compat.h.openssl openssh/libcrypto-compat.h ---- openssh/libcrypto-compat.h.openssl 2017-09-26 13:19:31.798249703 +0200 -+++ openssh/libcrypto-compat.h 2017-09-26 13:19:31.798249703 +0200 -@@ -0,0 +1,59 @@ -+#ifndef LIBCRYPTO_COMPAT_H -+#define LIBCRYPTO_COMPAT_H -+ -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ -+#include -+#include -+#include -+#include -+#include -+ -+int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); -+int RSA_set0_factors(RSA *r, BIGNUM *p, BIGNUM *q); -+int RSA_set0_crt_params(RSA *r, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqmp); -+void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); -+void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); -+void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp); -+ -+void DSA_get0_pqg(const DSA *d, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); -+int DSA_set0_pqg(DSA *d, BIGNUM *p, BIGNUM *q, BIGNUM *g); -+void DSA_get0_key(const DSA *d, const BIGNUM **pub_key, const BIGNUM **priv_key); -+int DSA_set0_key(DSA *d, BIGNUM *pub_key, BIGNUM *priv_key); -+ -+void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); -+int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s); -+ -+void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); -+int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); -+ -+void DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); -+int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g); -+void DH_get0_key(const DH *dh, const BIGNUM **pub_key, const BIGNUM **priv_key); -+int DH_set_length(DH *dh, long length); -+ -+const unsigned char *EVP_CIPHER_CTX_iv(const EVP_CIPHER_CTX *ctx); -+unsigned char *EVP_CIPHER_CTX_iv_noconst(EVP_CIPHER_CTX *ctx); -+int EVP_MD_CTX_reset(EVP_MD_CTX *ctx); -+EVP_MD_CTX *EVP_MD_CTX_new(void); -+void EVP_MD_CTX_free(EVP_MD_CTX *ctx); -+#define EVP_CIPHER_impl_ctx_size(e) e->ctx_size -+#define EVP_CIPHER_CTX_get_cipher_data(ctx) ctx->cipher_data -+ -+RSA_METHOD *RSA_meth_dup(const RSA_METHOD *meth); -+int RSA_meth_set1_name(RSA_METHOD *meth, const char *name); -+#define RSA_meth_get_finish(meth) meth->finish -+int RSA_meth_set_priv_enc(RSA_METHOD *meth, int (*priv_enc) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)); -+int RSA_meth_set_priv_dec(RSA_METHOD *meth, int (*priv_dec) (int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding)); -+int RSA_meth_set_finish(RSA_METHOD *meth, int (*finish) (RSA *rsa)); -+void RSA_meth_free(RSA_METHOD *meth); -+ -+int RSA_bits(const RSA *r); -+int DSA_bits(const DSA *d); -+ -+RSA *EVP_PKEY_get0_RSA(EVP_PKEY *pkey); -+ -+#endif /* OPENSSL_VERSION_NUMBER */ -+ -+#endif /* LIBCRYPTO_COMPAT_H */ -+ -diff -up openssh/Makefile.in.openssl openssh/Makefile.in ---- openssh/Makefile.in.openssl 2017-09-26 13:19:31.784249617 +0200 -+++ openssh/Makefile.in 2017-09-26 13:19:31.798249703 +0200 -@@ -101,7 +101,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ - kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ - platform-pledge.o platform-tracing.o platform-misc.o \ -- auditstub.o -+ auditstub.o libcrypto-compat.o - - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect2.o mux.o -diff -up openssh/monitor.c.openssl openssh/monitor.c ---- openssh/monitor.c.openssl 2017-09-26 13:19:31.789249648 +0200 -+++ openssh/monitor.c 2017-09-26 13:19:31.799249709 +0200 -@@ -631,9 +631,12 @@ mm_answer_moduli(int sock, Buffer *m) - return (0); - } else { - /* Send first bignum */ -+ const BIGNUM *p, *g; -+ -+ DH_get0_pqg(dh, &p, NULL, &g); - if ((r = sshbuf_put_u8(m, 1)) != 0 || -- (r = sshbuf_put_bignum2(m, dh->p)) != 0 || -- (r = sshbuf_put_bignum2(m, dh->g)) != 0) -+ (r = sshbuf_put_bignum2(m, p)) != 0 || -+ (r = sshbuf_put_bignum2(m, g)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); - - DH_free(dh); -diff -up openssh/openbsd-compat/openssl-compat.c.openssl openssh/openbsd-compat/openssl-compat.c ---- openssh/openbsd-compat/openssl-compat.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/openbsd-compat/openssl-compat.c 2017-09-26 13:19:31.799249709 +0200 -@@ -70,12 +70,19 @@ ssh_compatible_openssl(long headerver, l - void - ssh_OpenSSL_add_all_algorithms(void) - { -+#if OPENSSL_VERSION_NUMBER < 0x10100000L - OpenSSL_add_all_algorithms(); - - /* Enable use of crypto hardware */ - ENGINE_load_builtin_engines(); -+#if OPENSSL_VERSION_NUMBER < 0x10001000L - ENGINE_register_all_complete(); -+#endif - OPENSSL_config(NULL); -+#else -+ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_DIGESTS | -+ OPENSSL_INIT_ADD_ALL_DIGESTS | OPENSSL_INIT_LOAD_CONFIG, NULL); -+#endif - } - #endif - -diff -up openssh/pam_ssh_agent_auth-0.10.3/configure.ac.openssl openssh/pam_ssh_agent_auth-0.10.3/configure.ac ---- openssh/pam_ssh_agent_auth-0.10.3/configure.ac.openssl 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/configure.ac 2017-09-26 13:19:31.799249709 +0200 -@@ -1829,6 +1829,7 @@ AC_RUN_IFELSE( - [AC_LANG_SOURCE([[ - #include - #include -+#include - int main(void) { exit(SSLeay() == OPENSSL_VERSION_NUMBER ? 0 : 1); } - ]])], - [ -diff -up openssh/regress/unittests/sshkey/test_file.c.openssl openssh/regress/unittests/sshkey/test_file.c ---- openssh/regress/unittests/sshkey/test_file.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/regress/unittests/sshkey/test_file.c 2017-09-26 13:19:31.799249709 +0200 -@@ -46,6 +46,7 @@ sshkey_file_tests(void) - struct sshbuf *buf, *pw; - BIGNUM *a, *b, *c; - char *cp; -+ const BIGNUM *n, *p, *q, *g, *pub_key, *priv_key; - - TEST_START("load passphrase"); - pw = load_text_file("pw"); -@@ -60,9 +61,11 @@ sshkey_file_tests(void) - a = load_bignum("rsa_1.param.n"); - b = load_bignum("rsa_1.param.p"); - c = load_bignum("rsa_1.param.q"); -- ASSERT_BIGNUM_EQ(k1->rsa->n, a); -- ASSERT_BIGNUM_EQ(k1->rsa->p, b); -- ASSERT_BIGNUM_EQ(k1->rsa->q, c); -+ RSA_get0_key(k1->rsa, &n, NULL, NULL); -+ RSA_get0_factors(k1->rsa, &p, &q); -+ ASSERT_BIGNUM_EQ(n, a); -+ ASSERT_BIGNUM_EQ(p, b); -+ ASSERT_BIGNUM_EQ(q, c); - BN_free(a); - BN_free(b); - BN_free(c); -@@ -151,9 +154,11 @@ sshkey_file_tests(void) - a = load_bignum("dsa_1.param.g"); - b = load_bignum("dsa_1.param.priv"); - c = load_bignum("dsa_1.param.pub"); -- ASSERT_BIGNUM_EQ(k1->dsa->g, a); -- ASSERT_BIGNUM_EQ(k1->dsa->priv_key, b); -- ASSERT_BIGNUM_EQ(k1->dsa->pub_key, c); -+ DSA_get0_pqg(k1->dsa, NULL, NULL, &g); -+ DSA_get0_key(k1->dsa, &pub_key, &priv_key); -+ ASSERT_BIGNUM_EQ(g, a); -+ ASSERT_BIGNUM_EQ(priv_key, b); -+ ASSERT_BIGNUM_EQ(pub_key, c); - BN_free(a); - BN_free(b); - BN_free(c); -diff -up openssh/regress/unittests/sshkey/test_sshkey.c.openssl openssh/regress/unittests/sshkey/test_sshkey.c ---- openssh/regress/unittests/sshkey/test_sshkey.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/regress/unittests/sshkey/test_sshkey.c 2017-09-26 13:19:31.800249715 +0200 -@@ -197,9 +197,6 @@ sshkey_tests(void) - k1 = sshkey_new(KEY_RSA); - ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->rsa, NULL); -- ASSERT_PTR_NE(k1->rsa->n, NULL); -- ASSERT_PTR_NE(k1->rsa->e, NULL); -- ASSERT_PTR_EQ(k1->rsa->p, NULL); - sshkey_free(k1); - TEST_DONE(); - -@@ -207,8 +204,6 @@ sshkey_tests(void) - k1 = sshkey_new(KEY_DSA); - ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->dsa, NULL); -- ASSERT_PTR_NE(k1->dsa->g, NULL); -- ASSERT_PTR_EQ(k1->dsa->priv_key, NULL); - sshkey_free(k1); - TEST_DONE(); - -@@ -234,9 +229,6 @@ sshkey_tests(void) - k1 = sshkey_new_private(KEY_RSA); - ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->rsa, NULL); -- ASSERT_PTR_NE(k1->rsa->n, NULL); -- ASSERT_PTR_NE(k1->rsa->e, NULL); -- ASSERT_PTR_NE(k1->rsa->p, NULL); - ASSERT_INT_EQ(sshkey_add_private(k1), 0); - sshkey_free(k1); - TEST_DONE(); -@@ -245,8 +237,6 @@ sshkey_tests(void) - k1 = sshkey_new_private(KEY_DSA); - ASSERT_PTR_NE(k1, NULL); - ASSERT_PTR_NE(k1->dsa, NULL); -- ASSERT_PTR_NE(k1->dsa->g, NULL); -- ASSERT_PTR_NE(k1->dsa->priv_key, NULL); - ASSERT_INT_EQ(sshkey_add_private(k1), 0); - sshkey_free(k1); - TEST_DONE(); -@@ -285,18 +275,13 @@ sshkey_tests(void) - ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1024, &kr), 0); - ASSERT_PTR_NE(kr, NULL); - ASSERT_PTR_NE(kr->rsa, NULL); -- ASSERT_PTR_NE(kr->rsa->n, NULL); -- ASSERT_PTR_NE(kr->rsa->e, NULL); -- ASSERT_PTR_NE(kr->rsa->p, NULL); -- ASSERT_INT_EQ(BN_num_bits(kr->rsa->n), 1024); -+ ASSERT_INT_EQ(RSA_bits(kr->rsa), 1024); - TEST_DONE(); - - TEST_START("generate KEY_DSA"); - ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0); - ASSERT_PTR_NE(kd, NULL); - ASSERT_PTR_NE(kd->dsa, NULL); -- ASSERT_PTR_NE(kd->dsa->g, NULL); -- ASSERT_PTR_NE(kd->dsa->priv_key, NULL); - TEST_DONE(); - - #ifdef OPENSSL_HAS_ECC -@@ -323,9 +308,6 @@ sshkey_tests(void) - ASSERT_PTR_NE(kr, k1); - ASSERT_INT_EQ(k1->type, KEY_RSA); - ASSERT_PTR_NE(k1->rsa, NULL); -- ASSERT_PTR_NE(k1->rsa->n, NULL); -- ASSERT_PTR_NE(k1->rsa->e, NULL); -- ASSERT_PTR_EQ(k1->rsa->p, NULL); - TEST_DONE(); - - TEST_START("equal KEY_RSA/demoted KEY_RSA"); -@@ -339,8 +321,6 @@ sshkey_tests(void) - ASSERT_PTR_NE(kd, k1); - ASSERT_INT_EQ(k1->type, KEY_DSA); - ASSERT_PTR_NE(k1->dsa, NULL); -- ASSERT_PTR_NE(k1->dsa->g, NULL); -- ASSERT_PTR_EQ(k1->dsa->priv_key, NULL); - TEST_DONE(); - - TEST_START("equal KEY_DSA/demoted KEY_DSA"); -diff -up openssh/ssh.c.openssl openssh/ssh.c ---- openssh/ssh.c.openssl 2017-09-26 13:19:31.786249629 +0200 -+++ openssh/ssh.c 2017-09-26 13:19:31.800249715 +0200 -@@ -530,7 +530,9 @@ main(int ac, char **av) - sanitise_stdfd(); - - __progname = ssh_get_progname(av[0]); -+#if OPENSSL_VERSION_NUMBER < 0x10100000L - SSLeay_add_all_algorithms(); -+#endif - if (access("/etc/system-fips", F_OK) == 0) - if (! FIPSCHECK_verify(NULL, NULL)){ - if (FIPS_mode()) -diff -up openssh/sshd.c.openssl openssh/sshd.c ---- openssh/sshd.c.openssl 2017-09-26 13:19:31.792249666 +0200 -+++ openssh/sshd.c 2017-09-26 13:19:31.801249721 +0200 -@@ -1485,7 +1485,7 @@ main(int ac, char **av) - #endif - __progname = ssh_get_progname(av[0]); - -- SSLeay_add_all_algorithms(); -+ OpenSSL_add_all_algorithms(); - if (access("/etc/system-fips", F_OK) == 0) - if (! FIPSCHECK_verify(NULL, NULL)) { - openlog(__progname, LOG_PID, LOG_AUTHPRIV); -diff -up openssh/ssh-dss.c.openssl openssh/ssh-dss.c ---- openssh/ssh-dss.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/ssh-dss.c 2017-09-26 13:19:31.801249721 +0200 -@@ -55,6 +55,7 @@ ssh_dss_sign(const struct sshkey *key, u - size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); - struct sshbuf *b = NULL; - int ret = SSH_ERR_INVALID_ARGUMENT; -+ const BIGNUM *r, *s; - - if (lenp != NULL) - *lenp = 0; -@@ -76,15 +77,16 @@ ssh_dss_sign(const struct sshkey *key, u - goto out; - } - -- rlen = BN_num_bytes(sig->r); -- slen = BN_num_bytes(sig->s); -+ DSA_SIG_get0(sig, &r, &s); -+ rlen = BN_num_bytes(r); -+ slen = BN_num_bytes(s); - if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { - ret = SSH_ERR_INTERNAL_ERROR; - goto out; - } - explicit_bzero(sigblob, SIGBLOB_LEN); -- BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); -- BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen); -+ BN_bn2bin(r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen); -+ BN_bn2bin(s, sigblob + SIGBLOB_LEN - slen); - - if ((b = sshbuf_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; -@@ -137,6 +139,7 @@ ssh_dss_verify(const struct sshkey *key, - int ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL; - char *ktype = NULL; -+ BIGNUM *r = NULL, *s = NULL; - - if (key == NULL || key->dsa == NULL || - sshkey_type_plain(key->type) != KEY_DSA || -@@ -177,16 +180,19 @@ ssh_dss_verify(const struct sshkey *key, - - /* parse signature */ - if ((sig = DSA_SIG_new()) == NULL || -- (sig->r = BN_new()) == NULL || -- (sig->s = BN_new()) == NULL) { -+ (r = BN_new()) == NULL || -+ (s = BN_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || -- (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) { -+ if ((BN_bin2bn(sigblob, INTBLOB_LEN, r) == NULL) || -+ (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, s) == NULL) || -+ (DSA_SIG_set0(sig, r, s) == 0)) { - ret = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -+ r = NULL; -+ s = NULL; - - /* sha1 the data */ - if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, -@@ -207,7 +213,9 @@ ssh_dss_verify(const struct sshkey *key, - - out: - explicit_bzero(digest, sizeof(digest)); -+ BN_free(r); -+ BN_free(s); - DSA_SIG_free(sig); - sshbuf_free(b); - free(ktype); - if (sigblob != NULL) { -diff -up openssh/ssh-ecdsa.c.openssl openssh/ssh-ecdsa.c ---- openssh/ssh-ecdsa.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/ssh-ecdsa.c 2017-09-26 13:19:31.801249721 +0200 -@@ -54,6 +54,7 @@ ssh_ecdsa_sign(const struct sshkey *key, - size_t len, dlen; - struct sshbuf *b = NULL, *bb = NULL; - int ret = SSH_ERR_INTERNAL_ERROR; -+ const BIGNUM *r, *s; - - if (lenp != NULL) - *lenp = 0; -@@ -80,8 +81,9 @@ ssh_ecdsa_sign(const struct sshkey *key, - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 || -- (ret = sshbuf_put_bignum2(bb, sig->s)) != 0) -+ ECDSA_SIG_get0(sig, &r, &s); -+ if ((ret = sshbuf_put_bignum2(bb, r)) != 0 || -+ (ret = sshbuf_put_bignum2(bb, s)) != 0) - goto out; - if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 || - (ret = sshbuf_put_stringb(b, bb)) != 0) -@@ -119,6 +121,7 @@ ssh_ecdsa_verify(const struct sshkey *ke - int ret = SSH_ERR_INTERNAL_ERROR; - struct sshbuf *b = NULL, *sigbuf = NULL; - char *ktype = NULL; -+ BIGNUM *r = NULL, *s = NULL; - - if (key == NULL || key->ecdsa == NULL || - sshkey_type_plain(key->type) != KEY_ECDSA || -@@ -147,15 +150,23 @@ ssh_ecdsa_verify(const struct sshkey *ke - } - - /* parse signature */ -- if ((sig = ECDSA_SIG_new()) == NULL) { -+ if ((sig = ECDSA_SIG_new()) == NULL || -+ (r = BN_new()) == NULL || -+ (s = BN_new()) == NULL) { - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 || -- sshbuf_get_bignum2(sigbuf, sig->s) != 0) { -+ if (sshbuf_get_bignum2(sigbuf, r) != 0 || -+ sshbuf_get_bignum2(sigbuf, s) != 0) { - ret = SSH_ERR_INVALID_FORMAT; - goto out; - } -+ if (ECDSA_SIG_set0(sig, r, s) == 0) { -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ r = NULL; -+ s = NULL; - if (sshbuf_len(sigbuf) != 0) { - ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; - goto out; -@@ -180,7 +191,9 @@ ssh_ecdsa_verify(const struct sshkey *ke - explicit_bzero(digest, sizeof(digest)); - sshbuf_free(sigbuf); - sshbuf_free(b); -+ BN_free(r); -+ BN_free(s); - ECDSA_SIG_free(sig); - free(ktype); - return ret; - } -diff -up openssh/sshkey.c.openssl openssh/sshkey.c ---- openssh/sshkey.c.openssl 2017-09-26 13:19:31.786249629 +0200 -+++ openssh/sshkey.c 2017-09-26 13:19:31.802249728 +0200 -@@ -267,10 +267,10 @@ sshkey_size(const struct sshkey *k) - #ifdef WITH_OPENSSL - case KEY_RSA: - case KEY_RSA_CERT: -- return BN_num_bits(k->rsa->n); -+ return RSA_bits(k->rsa); - case KEY_DSA: - case KEY_DSA_CERT: -- return BN_num_bits(k->dsa->p); -+ return DSA_bits(k->dsa); - case KEY_ECDSA: - case KEY_ECDSA_CERT: - return sshkey_curve_nid_to_bits(k->ecdsa_nid); -@@ -302,11 +302,17 @@ sshkey_is_private(const struct sshkey *k - switch (k->type) { - #ifdef WITH_OPENSSL - case KEY_RSA_CERT: -- case KEY_RSA: -- return k->rsa->d != NULL; -+ case KEY_RSA: { -+ const BIGNUM *d; -+ RSA_get0_key(k->rsa, NULL, NULL, &d); -+ return d != NULL; -+ } - case KEY_DSA_CERT: -- case KEY_DSA: -- return k->dsa->priv_key != NULL; -+ 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: -@@ -496,10 +501,7 @@ sshkey_new(int type) - #ifdef WITH_OPENSSL - case KEY_RSA: - case KEY_RSA_CERT: -- if ((rsa = RSA_new()) == NULL || -- (rsa->n = BN_new()) == NULL || -- (rsa->e = BN_new()) == NULL) { -- RSA_free(rsa); -+ if ((rsa = RSA_new()) == NULL) { - free(k); - return NULL; - } -@@ -508,12 +509,7 @@ sshkey_new(int type) - break; - case KEY_DSA: - case KEY_DSA_CERT: -- if ((dsa = DSA_new()) == NULL || -- (dsa->p = BN_new()) == NULL || -- (dsa->q = BN_new()) == NULL || -- (dsa->g = BN_new()) == NULL || -- (dsa->pub_key = BN_new()) == NULL) { -- DSA_free(dsa); -+ if ((dsa = DSA_new()) == NULL) { - free(k); - return NULL; - } -@@ -553,21 +548,10 @@ sshkey_add_private(struct sshkey *k) - #ifdef WITH_OPENSSL - case KEY_RSA: - case KEY_RSA_CERT: --#define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL) -- if (bn_maybe_alloc_failed(k->rsa->d) || -- bn_maybe_alloc_failed(k->rsa->iqmp) || -- bn_maybe_alloc_failed(k->rsa->q) || -- bn_maybe_alloc_failed(k->rsa->p) || -- bn_maybe_alloc_failed(k->rsa->dmq1) || -- bn_maybe_alloc_failed(k->rsa->dmp1)) -- return SSH_ERR_ALLOC_FAIL; - break; - case KEY_DSA: - case KEY_DSA_CERT: -- if (bn_maybe_alloc_failed(k->dsa->priv_key)) -- return SSH_ERR_ALLOC_FAIL; - break; --#undef bn_maybe_alloc_failed - case KEY_ECDSA: - case KEY_ECDSA_CERT: - /* Cannot do anything until we know the group */ -@@ -684,17 +668,31 @@ sshkey_equal_public(const struct sshkey - switch (a->type) { - #ifdef WITH_OPENSSL - case KEY_RSA_CERT: -- case KEY_RSA: -- return a->rsa != NULL && b->rsa != NULL && -- BN_cmp(a->rsa->e, b->rsa->e) == 0 && -- BN_cmp(a->rsa->n, b->rsa->n) == 0; -+ case KEY_RSA: { -+ const BIGNUM *a_e, *a_n, *b_e, *b_n; -+ -+ if (a->rsa == NULL || b->rsa == NULL) -+ return 0; -+ RSA_get0_key(a->rsa, &a_n, &a_e, NULL); -+ RSA_get0_key(b->rsa, &b_n, &b_e, NULL); -+ return BN_cmp(a_e, b_e) == 0 && BN_cmp(a_n, b_n) == 0; -+ } - case KEY_DSA_CERT: -- case KEY_DSA: -- return a->dsa != NULL && b->dsa != NULL && -- BN_cmp(a->dsa->p, b->dsa->p) == 0 && -- BN_cmp(a->dsa->q, b->dsa->q) == 0 && -- BN_cmp(a->dsa->g, b->dsa->g) == 0 && -- BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0; -+ case KEY_DSA: { -+ const BIGNUM *a_p, *a_q, *a_g, *a_pub_key; -+ const BIGNUM *b_p, *b_q, *b_g, *b_pub_key; -+ -+ if (a->dsa == NULL || b->dsa == NULL) -+ return 0; -+ DSA_get0_pqg(a->dsa, &a_p, &a_q, &a_g); -+ DSA_get0_key(a->dsa, &a_pub_key, NULL); -+ DSA_get0_pqg(b->dsa, &b_p, &b_q, &b_g); -+ DSA_get0_key(b->dsa, &b_pub_key, NULL); -+ return BN_cmp(a_p, b_p) == 0 && -+ BN_cmp(a_q, b_q) == 0 && -+ BN_cmp(a_g, b_g) == 0 && -+ BN_cmp(a_pub_key, b_pub_key) == 0; -+ } - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: - case KEY_ECDSA: -@@ -769,15 +767,21 @@ to_blob_buf(const struct sshkey *key, st - return ret; - break; - #ifdef WITH_OPENSSL -- case KEY_DSA: -- if (key->dsa == NULL) -- return SSH_ERR_INVALID_ARGUMENT; -- if ((ret = sshbuf_put_cstring(b, typename)) != 0 || -- (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || -- (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || -- (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || -- (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0) -- return ret; -+ case KEY_DSA: { -+ const BIGNUM *p, *q, *g, *pub_key; -+ -+ if (key->dsa == NULL) -+ return SSH_ERR_INVALID_ARGUMENT; -+ -+ DSA_get0_pqg(key->dsa, &p, &q, &g); -+ DSA_get0_key(key->dsa, &pub_key, NULL); -+ if ((ret = sshbuf_put_cstring(b, typename)) != 0 || -+ (ret = sshbuf_put_bignum2(b, p)) != 0 || -+ (ret = sshbuf_put_bignum2(b, q)) != 0 || -+ (ret = sshbuf_put_bignum2(b, g)) != 0 || -+ (ret = sshbuf_put_bignum2(b, pub_key)) != 0) -+ return ret; -+ } - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: -@@ -790,13 +794,18 @@ to_blob_buf(const struct sshkey *key, st - return ret; - break; - # endif -- case KEY_RSA: -- if (key->rsa == NULL) -- return SSH_ERR_INVALID_ARGUMENT; -- if ((ret = sshbuf_put_cstring(b, typename)) != 0 || -- (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || -- (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0) -- return ret; -+ case KEY_RSA: { -+ const BIGNUM *e, *n; -+ -+ if (key->rsa == NULL) -+ return SSH_ERR_INVALID_ARGUMENT; -+ -+ RSA_get0_key(key->rsa, &n, &e, NULL); -+ if ((ret = sshbuf_put_cstring(b, typename)) != 0 || -+ (ret = sshbuf_put_bignum2(b, e)) != 0 || -+ (ret = sshbuf_put_bignum2(b, n)) != 0) -+ return ret; -+ } - break; - #endif /* WITH_OPENSSL */ - case KEY_ED25519: -@@ -1672,15 +1681,32 @@ sshkey_from_private(const struct sshkey - switch (k->type) { - #ifdef WITH_OPENSSL - case KEY_DSA: -- case KEY_DSA_CERT: -- if ((n = sshkey_new(k->type)) == NULL) -- return SSH_ERR_ALLOC_FAIL; -- if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) || -- (BN_copy(n->dsa->q, k->dsa->q) == NULL) || -- (BN_copy(n->dsa->g, k->dsa->g) == NULL) || -- (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) { -- sshkey_free(n); -- return SSH_ERR_ALLOC_FAIL; -+ case KEY_DSA_CERT: { -+ const BIGNUM *k_p, *k_q, *k_g, *k_pub_key; -+ BIGNUM *n_p = NULL, *n_q = NULL, *n_g = NULL, *n_pub_key = NULL; -+ -+ if ((n = sshkey_new(k->type)) == NULL) -+ return SSH_ERR_ALLOC_FAIL; -+ -+ DSA_get0_pqg(k->dsa, &k_p, &k_q, &k_g); -+ DSA_get0_key(k->dsa, &k_pub_key, NULL); -+ -+ if (((n_p = BN_dup(k_p)) == NULL) || -+ ((n_q = BN_dup(k_q)) == NULL) || -+ ((n_g = BN_dup(k_g)) == NULL) || -+ (DSA_set0_pqg(n->dsa, n_p, n_q, n_g) == 0)) { -+ sshkey_free(n); -+ BN_free(n_p); -+ BN_free(n_q); -+ BN_free(n_g); -+ return SSH_ERR_ALLOC_FAIL; -+ } -+ if (((n_pub_key = BN_dup(k_pub_key)) == NULL) || -+ (DSA_set0_key(n->dsa, n_pub_key, NULL) == 0)) { -+ sshkey_free(n); -+ BN_free(n_pub_key); -+ return SSH_ERR_ALLOC_FAIL; -+ } - } - break; - # ifdef OPENSSL_HAS_ECC -@@ -1702,13 +1728,22 @@ sshkey_from_private(const struct sshkey - break; - # endif /* OPENSSL_HAS_ECC */ - case KEY_RSA: -- case KEY_RSA_CERT: -- if ((n = sshkey_new(k->type)) == NULL) -- return SSH_ERR_ALLOC_FAIL; -- if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) || -- (BN_copy(n->rsa->e, k->rsa->e) == NULL)) { -- sshkey_free(n); -- return SSH_ERR_ALLOC_FAIL; -+ case KEY_RSA_CERT: { -+ const BIGNUM *k_n, *k_e; -+ BIGNUM *n_n = NULL, *n_e = NULL; -+ -+ if ((n = sshkey_new(k->type)) == NULL) -+ return SSH_ERR_ALLOC_FAIL; -+ -+ RSA_get0_key(k->rsa, &k_n, &k_e, NULL); -+ if (((n_n = BN_dup(k_n)) == NULL) || -+ ((n_e = BN_dup(k_e)) == NULL) || -+ RSA_set0_key(n->rsa, n_n, n_e, NULL) == 0) { -+ sshkey_free(n); -+ BN_free(n_n); -+ BN_free(n_e); -+ return SSH_ERR_ALLOC_FAIL; -+ } - } - break; - #endif /* WITH_OPENSSL */ -@@ -1907,12 +1942,22 @@ sshkey_from_blob_internal(struct sshbuf - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if (sshbuf_get_bignum2(b, key->rsa->e) != 0 || -- sshbuf_get_bignum2(b, key->rsa->n) != 0) { -- ret = SSH_ERR_INVALID_FORMAT; -- goto out; -+ { -+ BIGNUM *e, *n; -+ -+ e = BN_new(); -+ n = BN_new(); -+ if (e == NULL || n == NULL || -+ sshbuf_get_bignum2(b, e) != 0 || -+ sshbuf_get_bignum2(b, n) != 0 || -+ RSA_set0_key(key->rsa, n, e, NULL) == 0) { -+ BN_free(e); -+ BN_free(n); -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } - } -- if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { -+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - ret = SSH_ERR_KEY_LENGTH; - goto out; - } -@@ -1932,12 +1977,34 @@ sshkey_from_blob_internal(struct sshbuf - ret = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if (sshbuf_get_bignum2(b, key->dsa->p) != 0 || -- sshbuf_get_bignum2(b, key->dsa->q) != 0 || -- sshbuf_get_bignum2(b, key->dsa->g) != 0 || -- sshbuf_get_bignum2(b, key->dsa->pub_key) != 0) { -- ret = SSH_ERR_INVALID_FORMAT; -- goto out; -+ { -+ BIGNUM *p, *q, *g, *pub_key; -+ -+ p = BN_new(); -+ q = BN_new(); -+ g = BN_new(); -+ pub_key = BN_new(); -+ -+ if (p == NULL || q == NULL || g == NULL || -+ pub_key == NULL || -+ sshbuf_get_bignum2(b, p) != 0 || -+ sshbuf_get_bignum2(b, q) != 0 || -+ sshbuf_get_bignum2(b, g) != 0 || -+ sshbuf_get_bignum2(b, pub_key) != 0 || -+ DSA_set0_pqg(key->dsa, p, q, g) == 0) { -+ BN_free(p); -+ BN_free(q); -+ BN_free(g); -+ BN_free(pub_key); -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if (DSA_set0_key(key->dsa, pub_key, NULL) == 0) { -+ BN_free(pub_key); -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } - } - #ifdef DEBUG_PK - DSA_print_fp(stderr, key->dsa, 8); -@@ -2171,26 +2238,53 @@ sshkey_demote(const struct sshkey *k, st - if ((ret = sshkey_cert_copy(k, pk)) != 0) - goto fail; - /* FALLTHROUGH */ -- case KEY_RSA: -- if ((pk->rsa = RSA_new()) == NULL || -- (pk->rsa->e = BN_dup(k->rsa->e)) == NULL || -- (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) { -- ret = SSH_ERR_ALLOC_FAIL; -- goto fail; -+ case KEY_RSA: { -+ const BIGNUM *k_e, *k_n; -+ BIGNUM *pk_e = NULL, *pk_n = NULL; -+ -+ RSA_get0_key(k->rsa, &k_n, &k_e, NULL); -+ if ((pk->rsa = RSA_new()) == NULL || -+ (pk_e = BN_dup(k_e)) == NULL || -+ (pk_n = BN_dup(k_n)) == NULL || -+ RSA_set0_key(pk->rsa, pk_n, pk_e, NULL) == 0) { -+ BN_free(pk_e); -+ BN_free(pk_n); -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto fail; - } -+ } - break; - case KEY_DSA_CERT: - if ((ret = sshkey_cert_copy(k, pk)) != 0) - goto fail; - /* FALLTHROUGH */ -- case KEY_DSA: -- if ((pk->dsa = DSA_new()) == NULL || -- (pk->dsa->p = BN_dup(k->dsa->p)) == NULL || -- (pk->dsa->q = BN_dup(k->dsa->q)) == NULL || -- (pk->dsa->g = BN_dup(k->dsa->g)) == NULL || -- (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) { -- ret = SSH_ERR_ALLOC_FAIL; -- goto fail; -+ case KEY_DSA: { -+ const BIGNUM *k_p, *k_q, *k_g, *k_pub_key; -+ BIGNUM *pk_p = NULL, *pk_q = NULL, *pk_g = NULL; -+ BIGNUM *pk_pub_key = NULL; -+ -+ DSA_get0_pqg(k->dsa, &k_p, &k_q, &k_g); -+ DSA_get0_key(k->dsa, &k_pub_key, NULL); -+ -+ if ((pk->dsa = DSA_new()) == NULL || -+ (pk_p = BN_dup(k_p)) == NULL || -+ (pk_q = BN_dup(k_q)) == NULL || -+ (pk_g = BN_dup(k_g)) == NULL || -+ (pk_pub_key = BN_dup(k_pub_key)) == NULL || -+ DSA_set0_pqg(pk->dsa, pk_p, pk_q, pk_g) == 0) { -+ BN_free(pk_p); -+ BN_free(pk_q); -+ BN_free(pk_g); -+ BN_free(pk_pub_key); -+ ret = SSH_ERR_ALLOC_FAIL; -+ goto fail; -+ } -+ -+ if (DSA_set0_key(pk->dsa, pk_pub_key, NULL) == 0) { -+ BN_free(pk_pub_key); -+ ret = SSH_ERR_LIBCRYPTO_ERROR; -+ goto fail; -+ } - } - break; - case KEY_ECDSA_CERT: -@@ -2312,12 +2406,17 @@ sshkey_certify_custom(struct sshkey *k, - /* XXX this substantially duplicates to_blob(); refactor */ - switch (k->type) { - #ifdef WITH_OPENSSL -- case KEY_DSA_CERT: -- if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 || -- (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 || -- (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 || -- (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0) -- goto out; -+ case KEY_DSA_CERT: { -+ const BIGNUM *p, *q, *g, *pub_key; -+ -+ DSA_get0_pqg(k->dsa, &p, &q, &g); -+ DSA_get0_key(k->dsa, &pub_key, NULL); -+ if ((ret = sshbuf_put_bignum2(cert, p)) != 0 || -+ (ret = sshbuf_put_bignum2(cert, q)) != 0 || -+ (ret = sshbuf_put_bignum2(cert, g)) != 0 || -+ (ret = sshbuf_put_bignum2(cert, pub_key)) != 0) -+ goto out; -+ } - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA_CERT: -@@ -2329,10 +2428,15 @@ sshkey_certify_custom(struct sshkey *k, - goto out; - break; - # endif /* OPENSSL_HAS_ECC */ -- case KEY_RSA_CERT: -- if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 || -- (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0) -- goto out; -+ case KEY_RSA_CERT: { -+ const BIGNUM *e, *n; -+ -+ RSA_get0_key(k->rsa, &n, &e, NULL); -+ if (e == NULL || n == NULL || -+ (ret = sshbuf_put_bignum2(cert, e)) != 0 || -+ (ret = sshbuf_put_bignum2(cert, n)) != 0) -+ goto out; -+ } - break; - #endif /* WITH_OPENSSL */ - case KEY_ED25519_CERT: -@@ -2505,43 +2609,65 @@ sshkey_private_serialize(const struct ss - goto out; - switch (key->type) { - #ifdef WITH_OPENSSL -- case KEY_RSA: -- if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) -- goto out; -+ case KEY_RSA: { -+ const BIGNUM *n, *e, *d, *iqmp, *p, *q; -+ RSA_get0_key(key->rsa, &n, &e, &d); -+ RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp); -+ RSA_get0_factors(key->rsa, &p, &q); -+ if ((r = sshbuf_put_bignum2(b, n)) != 0 || -+ (r = sshbuf_put_bignum2(b, e)) != 0 || -+ (r = sshbuf_put_bignum2(b, d)) != 0 || -+ (r = sshbuf_put_bignum2(b, iqmp)) != 0 || -+ (r = sshbuf_put_bignum2(b, p)) != 0 || -+ (r = sshbuf_put_bignum2(b, q)) != 0) -+ goto out; -+ } - break; - case KEY_RSA_CERT: - if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } -- if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 || -- (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0) -- goto out; -+ { -+ const BIGNUM *d, *iqmp, *p, *q; -+ -+ RSA_get0_key(key->rsa, NULL, NULL, &d); -+ RSA_get0_factors(key->rsa, &p, &q); -+ RSA_get0_crt_params(key->rsa, NULL, NULL, &iqmp); -+ if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || -+ (r = sshbuf_put_bignum2(b, d)) != 0 || -+ (r = sshbuf_put_bignum2(b, iqmp)) != 0 || -+ (r = sshbuf_put_bignum2(b, p)) != 0 || -+ (r = sshbuf_put_bignum2(b, q)) != 0) -+ goto out; -+ } - break; -- case KEY_DSA: -- if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 || -- (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 || -- (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 || -- (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 || -- (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) -- goto out; -+ case KEY_DSA: { -+ const BIGNUM *p, *q, *g, *pub_key, *priv_key; -+ -+ DSA_get0_pqg(key->dsa, &p, &q, &g); -+ DSA_get0_key(key->dsa, &pub_key, &priv_key); -+ if ((r = sshbuf_put_bignum2(b, p)) != 0 || -+ (r = sshbuf_put_bignum2(b, q)) != 0 || -+ (r = sshbuf_put_bignum2(b, g)) != 0 || -+ (r = sshbuf_put_bignum2(b, pub_key)) != 0 || -+ (r = sshbuf_put_bignum2(b, priv_key)) != 0) -+ goto out; -+ } - break; - case KEY_DSA_CERT: - if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) { - r = SSH_ERR_INVALID_ARGUMENT; - goto out; - } -- if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || -- (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0) -- goto out; -+ { -+ const BIGNUM *priv_key; -+ -+ DSA_get0_key(key->dsa, NULL, &priv_key); -+ if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 || -+ (r = sshbuf_put_bignum2(b, priv_key)) != 0) -+ goto out; -+ } - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: -@@ -2617,18 +2743,51 @@ sshkey_private_deserialize(struct sshbuf - r = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) -- goto out; -+ { -+ BIGNUM *p, *q, *g, *pub_key, *priv_key; -+ -+ p = BN_new(); -+ q = BN_new(); -+ g = BN_new(); -+ pub_key = BN_new(); -+ priv_key = BN_new(); -+ if (p == NULL || q == NULL || g == NULL || -+ pub_key == NULL || priv_key == NULL || -+ (r = sshbuf_get_bignum2(buf, p)) != 0 || -+ (r = sshbuf_get_bignum2(buf, q)) != 0 || -+ (r = sshbuf_get_bignum2(buf, g)) != 0 || -+ (r = sshbuf_get_bignum2(buf, pub_key)) != 0 || -+ (r = sshbuf_get_bignum2(buf, priv_key)) != 0 || -+ (r = ((DSA_set0_pqg(k->dsa, p, q, g) == 0) -+ ? SSH_ERR_LIBCRYPTO_ERROR : 0)) != 0) { -+ BN_free(p); -+ BN_free(q); -+ BN_free(g); -+ BN_free(pub_key); -+ BN_free(priv_key); -+ goto out; -+ } -+ if (DSA_set0_key(k->dsa, pub_key, priv_key) == 0) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ BN_free(pub_key); -+ BN_free(priv_key); -+ goto out; -+ } -+ } - break; -- case KEY_DSA_CERT: -- if ((r = sshkey_froms(buf, &k)) != 0 || -- (r = sshkey_add_private(k)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0) -- goto out; -+ case KEY_DSA_CERT: { -+ BIGNUM *priv_key = BN_new(); -+ -+ if (priv_key == NULL || -+ (r = sshkey_froms(buf, &k)) != 0 || -+ (r = sshkey_add_private(k)) != 0 || -+ (r = sshbuf_get_bignum2(buf, priv_key)) != 0 || -+ (r = ((DSA_set0_key(k->dsa, NULL, priv_key) == 0) -+ ? SSH_ERR_LIBCRYPTO_ERROR : 0)) != 0) { -+ BN_free(priv_key); -+ goto out; -+ } -+ } - break; - # ifdef OPENSSL_HAS_ECC - case KEY_ECDSA: -@@ -2687,29 +2846,89 @@ sshkey_private_deserialize(struct sshbuf - r = SSH_ERR_ALLOC_FAIL; - goto out; - } -- if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || -- (r = ssh_rsa_generate_additional_parameters(k)) != 0) -- goto out; -- if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { -+ { -+ BIGNUM *n, *e, *d, *iqmp, *p, *q; -+ -+ n = BN_new(); -+ e = BN_new(); -+ d = BN_new(); -+ iqmp = BN_new(); -+ p = BN_new(); -+ q = BN_new(); -+ -+ if (n == NULL || e == NULL || d == NULL || -+ iqmp == NULL || p == NULL || q == NULL || -+ (r = sshbuf_get_bignum2(buf, n)) != 0 || -+ (r = sshbuf_get_bignum2(buf, e)) != 0 || -+ (r = sshbuf_get_bignum2(buf, d)) != 0 || -+ (r = sshbuf_get_bignum2(buf, iqmp)) != 0 || -+ (r = sshbuf_get_bignum2(buf, p)) != 0 || -+ (r = sshbuf_get_bignum2(buf, q)) != 0 || -+ (r = ((RSA_set0_key(k->rsa, n, e, d) == 0) -+ ? SSH_ERR_LIBCRYPTO_ERROR : 0)) != 0) { -+ BN_free(n); -+ BN_free(e); -+ BN_free(d); -+ BN_free(iqmp); -+ BN_free(p); -+ BN_free(q); -+ goto out; -+ } -+ if (RSA_set0_factors(k->rsa, p, q) == 0) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ BN_free(iqmp); -+ BN_free(p); -+ BN_free(q); -+ goto out; -+ } -+ if ((r = ssh_rsa_generate_additional_parameters(k, iqmp)) != 0) { -+ BN_free(iqmp); -+ goto out; -+ } -+ } -+ if (RSA_bits(k->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - r = SSH_ERR_KEY_LENGTH; - goto out; - } - break; -- case KEY_RSA_CERT: -- if ((r = sshkey_froms(buf, &k)) != 0 || -- (r = sshkey_add_private(k)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 || -- (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 || -- (r = ssh_rsa_generate_additional_parameters(k)) != 0) -- goto out; -- if (BN_num_bits(k->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { -+ case KEY_RSA_CERT: { -+ BIGNUM *d, *iqmp, *p, *q; -+ -+ /* N and E are already set so make sure we will not overwrite them */ -+ d = BN_new(); -+ iqmp = BN_new(); -+ p = BN_new(); -+ q = BN_new(); -+ -+ if (d == NULL || iqmp == NULL || p == NULL || -+ q == NULL || -+ (r = sshkey_froms(buf, &k)) != 0 || -+ (r = sshkey_add_private(k)) != 0 || -+ (r = sshbuf_get_bignum2(buf, d)) != 0 || -+ (r = sshbuf_get_bignum2(buf, iqmp)) != 0 || -+ (r = sshbuf_get_bignum2(buf, p)) != 0 || -+ (r = sshbuf_get_bignum2(buf, q)) != 0 || -+ (r = ((RSA_set0_key(k->rsa, NULL, NULL, d) == 0) -+ ? SSH_ERR_LIBCRYPTO_ERROR : 0)) != 0) { -+ BN_free(d); -+ BN_free(iqmp); -+ BN_free(p); -+ BN_free(q); -+ goto out; -+ } -+ if (RSA_set0_factors(k->rsa, p, q) == 0) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ BN_free(p); -+ BN_free(q); -+ goto out; -+ } -+ if (ssh_rsa_generate_additional_parameters(k, iqmp) != 0) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ free(iqmp); -+ goto out; -+ } -+ } -+ if (RSA_bits(k->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - r = SSH_ERR_KEY_LENGTH; - goto out; - } -@@ -3427,7 +3646,9 @@ translate_libcrypto_error(unsigned long - switch (pem_reason) { - case EVP_R_BAD_DECRYPT: - return SSH_ERR_KEY_WRONG_PASSPHRASE; -+#ifdef EVP_R_BN_DECODE_ERROR - case EVP_R_BN_DECODE_ERROR: -+#endif - case EVP_R_DECODE_ERROR: - #ifdef EVP_R_PRIVATE_KEY_DECODE_ERROR - case EVP_R_PRIVATE_KEY_DECODE_ERROR: -@@ -3492,7 +3713,7 @@ sshkey_parse_private_pem_fileblob(struct - r = convert_libcrypto_error(); - goto out; - } -- if (pk->type == EVP_PKEY_RSA && -+ if (EVP_PKEY_id(pk) == EVP_PKEY_RSA && - (type == KEY_UNSPEC || type == KEY_RSA)) { - if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; -@@ -3507,11 +3728,11 @@ sshkey_parse_private_pem_fileblob(struct - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -- if (BN_num_bits(prv->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { -+ if (RSA_bits(prv->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) { - r = SSH_ERR_KEY_LENGTH; - goto out; - } -- } else if (pk->type == EVP_PKEY_DSA && -+ } else if (EVP_PKEY_id(pk) == EVP_PKEY_DSA && - (type == KEY_UNSPEC || type == KEY_DSA)) { - if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; -@@ -3523,7 +3744,7 @@ sshkey_parse_private_pem_fileblob(struct - DSA_print_fp(stderr, prv->dsa, 8); - #endif - #ifdef OPENSSL_HAS_ECC -- } else if (pk->type == EVP_PKEY_EC && -+ } else if (EVP_PKEY_id(pk) == EVP_PKEY_EC && - (type == KEY_UNSPEC || type == KEY_ECDSA)) { - if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) { - r = SSH_ERR_ALLOC_FAIL; -diff -up openssh/ssh-keygen.c.openssl openssh/ssh-keygen.c ---- openssh/ssh-keygen.c.openssl 2017-09-26 13:19:31.787249636 +0200 -+++ openssh/ssh-keygen.c 2017-09-26 13:19:31.802249728 +0200 -@@ -501,40 +501,67 @@ do_convert_private_ssh2_from_blob(u_char - free(type); - - switch (key->type) { -- case KEY_DSA: -- buffer_get_bignum_bits(b, key->dsa->p); -- buffer_get_bignum_bits(b, key->dsa->g); -- buffer_get_bignum_bits(b, key->dsa->q); -- buffer_get_bignum_bits(b, key->dsa->pub_key); -- buffer_get_bignum_bits(b, key->dsa->priv_key); -+ case KEY_DSA: { -+ BIGNUM *p = NULL, *g = NULL, *q = NULL, *pub_key = NULL, *priv_key = NULL; -+ -+ if ((p = BN_new()) == NULL || -+ (g = BN_new()) == NULL || -+ (q = BN_new()) == NULL || -+ (pub_key = BN_new()) == NULL || -+ (priv_key = BN_new()) == NULL) -+ fatal("BN_new() failed"); -+ buffer_get_bignum_bits(b, p); -+ buffer_get_bignum_bits(b, g); -+ buffer_get_bignum_bits(b, q); -+ buffer_get_bignum_bits(b, pub_key); -+ buffer_get_bignum_bits(b, priv_key); -+ if (DSA_set0_pqg(key->dsa, p, q, g) == 0 || -+ DSA_set0_key(key->dsa, pub_key, priv_key) == 0) { -+ fatal("failed to set DSA key"); -+ } -+ } - break; -- case KEY_RSA: -- if ((r = sshbuf_get_u8(b, &e1)) != 0 || -- (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || -- (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0)) -- fatal("%s: buffer error: %s", __func__, ssh_err(r)); -- e = e1; -- debug("e %lx", e); -- if (e < 30) { -- e <<= 8; -- e += e2; -- debug("e %lx", e); -- e <<= 8; -- e += e3; -+ case KEY_RSA: { -+ BIGNUM *bn_e = NULL, *bn_d = NULL, *bn_n = NULL, *bn_iqmp = NULL, *bn_p = NULL, *bn_q = NULL; -+ -+ if ((bn_e = BN_new()) == NULL || -+ (bn_d = BN_new()) == NULL || -+ (bn_n = BN_new()) == NULL || -+ (bn_iqmp = BN_new()) == NULL || -+ (bn_p = BN_new()) == NULL || -+ (bn_q = BN_new()) == NULL) -+ fatal("BN_new() failed"); -+ -+ if ((r = sshbuf_get_u8(b, &e1)) != 0 || -+ (e1 < 30 && (r = sshbuf_get_u8(b, &e2)) != 0) || -+ (e1 < 30 && (r = sshbuf_get_u8(b, &e3)) != 0)) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ e = e1; - debug("e %lx", e); -+ if (e < 30) { -+ e <<= 8; -+ e += e2; -+ debug("e %lx", e); -+ e <<= 8; -+ e += e3; -+ debug("e %lx", e); -+ } -+ if (!BN_set_word(bn_e, e)) { -+ sshbuf_free(b); -+ sshkey_free(key); -+ return NULL; -+ } -+ buffer_get_bignum_bits(b, bn_d); -+ buffer_get_bignum_bits(b, bn_n); -+ buffer_get_bignum_bits(b, bn_iqmp); -+ buffer_get_bignum_bits(b, bn_q); -+ buffer_get_bignum_bits(b, bn_p); -+ if (RSA_set0_key(key->rsa, bn_n, bn_e, bn_d) == 0 || -+ RSA_set0_factors(key->rsa, bn_p, bn_q) == 0) -+ fatal("Failed to set RSA parameters"); -+ if ((r = ssh_rsa_generate_additional_parameters(key, bn_iqmp)) != 0) -+ fatal("generate RSA parameters failed: %s", ssh_err(r)); - } -- if (!BN_set_word(key->rsa->e, e)) { -- sshbuf_free(b); -- sshkey_free(key); -- return NULL; -- } -- buffer_get_bignum_bits(b, key->rsa->d); -- buffer_get_bignum_bits(b, key->rsa->n); -- buffer_get_bignum_bits(b, key->rsa->iqmp); -- buffer_get_bignum_bits(b, key->rsa->q); -- buffer_get_bignum_bits(b, key->rsa->p); -- if ((r = ssh_rsa_generate_additional_parameters(key)) != 0) -- fatal("generate RSA parameters failed: %s", ssh_err(r)); - break; - } - rlen = sshbuf_len(b); -@@ -642,7 +669,7 @@ do_convert_from_pkcs8(struct sshkey **k, - identity_file); - } - fclose(fp); -- switch (EVP_PKEY_type(pubkey->type)) { -+ switch (EVP_PKEY_base_id(pubkey)) { - case EVP_PKEY_RSA: - if ((*k = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); -@@ -666,7 +693,7 @@ do_convert_from_pkcs8(struct sshkey **k, - #endif - default: - fatal("%s: unsupported pubkey type %d", __func__, -- EVP_PKEY_type(pubkey->type)); -+ EVP_PKEY_base_id(pubkey)); - } - EVP_PKEY_free(pubkey); - return; -@@ -1798,6 +1825,7 @@ do_ca_sign(struct passwd *pw, int argc, - #ifdef ENABLE_PKCS11 - pkcs11_terminate(); - #endif -+ free(ca); - exit(0); - } - -diff -up openssh/sshkey.h.openssl openssh/sshkey.h ---- openssh/sshkey.h.openssl 2017-09-26 13:19:31.780249593 +0200 -+++ openssh/sshkey.h 2017-09-26 13:19:31.803249734 +0200 -@@ -199,7 +199,7 @@ int sshkey_parse_private_fileblob_type(s - const char *passphrase, struct sshkey **keyp, char **commentp); - - /* XXX should be internal, but used by ssh-keygen */ --int ssh_rsa_generate_additional_parameters(struct sshkey *); -+int ssh_rsa_generate_additional_parameters(struct sshkey *, BIGNUM *iqmp); - - /* stateful keys (e.g. XMSS) */ - #ifdef NO_ATTRIBUTE_ON_PROTOTYPE_ARGS -diff -up openssh/ssh-pkcs11-client.c.openssl openssh/ssh-pkcs11-client.c ---- openssh/ssh-pkcs11-client.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/ssh-pkcs11-client.c 2017-09-26 13:19:31.803249734 +0200 -@@ -143,12 +143,16 @@ pkcs11_rsa_private_encrypt(int flen, con - static int - wrap_rsa_key(RSA *rsa) - { -- static RSA_METHOD helper_rsa; -+ static RSA_METHOD *helper_rsa; - -- memcpy(&helper_rsa, RSA_get_default_method(), sizeof(helper_rsa)); -- helper_rsa.name = "ssh-pkcs11-helper"; -- helper_rsa.rsa_priv_enc = pkcs11_rsa_private_encrypt; -- RSA_set_method(rsa, &helper_rsa); -+ if (helper_rsa == NULL) { -+ helper_rsa = RSA_meth_dup(RSA_get_default_method()); -+ if (helper_rsa == NULL) -+ error("RSA_meth_dup failed"); -+ RSA_meth_set1_name(helper_rsa, "ssh-pkcs11-helper"); -+ RSA_meth_set_priv_enc(helper_rsa, pkcs11_rsa_private_encrypt); -+ } -+ RSA_set_method(rsa, helper_rsa); - return (0); - } - -diff -up openssh/ssh-pkcs11.c.openssl openssh/ssh-pkcs11.c ---- openssh/ssh-pkcs11.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/ssh-pkcs11.c 2017-09-26 13:19:31.803249734 +0200 -@@ -67,7 +67,7 @@ struct pkcs11_key { - CK_ULONG slotidx; - CK_ULONG key_type; - int (*orig_finish)(RSA *rsa); -- RSA_METHOD rsa_method; -+ RSA_METHOD *rsa_method; - char *keyid; - int keyid_len; - char *label; -@@ -183,6 +183,7 @@ pkcs11_rsa_finish(RSA *rsa) - pkcs11_provider_unref(k11->provider); - free(k11->keyid); - free(k11->label); -+ RSA_meth_free(k11->rsa_method); - free(k11); - } - return (rv); -@@ -326,13 +326,21 @@ pkcs11_rsa_wrap(struct pkcs11_provider * - memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); - k11->label[label_attrib->ulValueLen] = 0; - } -- k11->orig_finish = def->finish; -- memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method)); -- k11->rsa_method.name = "pkcs11"; -- k11->rsa_method.rsa_priv_enc = pkcs11_rsa_private_encrypt; -- k11->rsa_method.rsa_priv_dec = pkcs11_rsa_private_decrypt; -- k11->rsa_method.finish = pkcs11_rsa_finish; -- RSA_set_method(rsa, &k11->rsa_method); -+ k11->orig_finish = RSA_meth_get_finish(def); -+ if ((k11->rsa_method = RSA_meth_dup(def)) == NULL || -+ RSA_meth_set1_name(k11->rsa_method, "pkcs11") == 0 || -+ RSA_meth_set_priv_enc(k11->rsa_method, pkcs11_rsa_private_encrypt) == 0 || -+ RSA_meth_set_priv_dec(k11->rsa_method, pkcs11_rsa_private_decrypt) == 0 || -+ RSA_meth_set_finish(k11->rsa_method, pkcs11_rsa_finish) == 0) { -+ RSA_meth_free(k11->rsa_method); -+ k11->rsa_method = NULL; -+ pkcs11_provider_unref(k11->provider); -+ free(k11->keyid); -+ free(k11); -+ return (-1); -+ } -+ -+ RSA_set_method(rsa, k11->rsa_method); - RSA_set_app_data(rsa, k11); - return (0); - } -@@ -460,6 +468,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - CK_ULONG nfound; - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f; -+ const BIGNUM *n, *e; - - f = p->module->function_list; - session = p->module->slotinfo[slotidx].session; -@@ -512,10 +521,16 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - if ((rsa = RSA_new()) == NULL) { - error("RSA_new failed"); - } else { -- rsa->n = BN_bin2bn(attribs[2].pValue, -+ BIGNUM *rsa_n, *rsa_e; -+ -+ rsa_n = BN_bin2bn(attribs[2].pValue, - attribs[2].ulValueLen, NULL); -- rsa->e = BN_bin2bn(attribs[3].pValue, -+ rsa_e = BN_bin2bn(attribs[3].pValue, - attribs[3].ulValueLen, NULL); -+ if (rsa_n == NULL || rsa_e == NULL) -+ error("BN_bin2bn failed"); -+ if (RSA_set0_key(rsa, rsa_n, rsa_e, NULL) == 0) -+ error("RSA_set0_key failed"); - } - #ifdef ENABLE_PKCS11_ECDSA - } else if (attribs[2].type == CKA_EC_PARAMS ) { -@@ -920,19 +936,19 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - } else if ((evp = X509_get_pubkey(x509)) == NULL) { - debug("X509_get_pubkey failed"); - } else { -- switch (evp->type) { -+ switch (EVP_PKEY_id(evp)) { - case EVP_PKEY_RSA: -- if (evp->pkey.rsa == NULL) -+ if (EVP_PKEY_get0_RSA(evp) == NULL) - debug("Missing RSA key"); -- else if ((rsa = RSAPublicKey_dup( -- evp->pkey.rsa)) == NULL) -+ else if ((rsa = RSAPublicKey_dup( -+ EVP_PKEY_get0_RSA(evp))) == NULL) - error("RSAPublicKey_dup failed"); - break; - case EVP_PKEY_EC: -- if (evp->pkey.ecdsa == NULL) -+ if (EVP_PKEY_get0_EC_KEY(evp) == NULL) - debug("Missing ECDSA key"); -- else if ((ecdsa = EC_KEY_dup( -- evp->pkey.ecdsa)) == NULL) -+ else if ((ecdsa = EC_KEY_dup( -+ EVP_PKEY_get0_EC_KEY(evp))) == NULL) - error("EC_KEY_dup failed"); - break; - default: -@@ -538,7 +551,9 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - } - key = NULL; - if (rsa || ecdsa) { -- if (rsa && rsa->n && rsa->e && -+ if (rsa) -+ RSA_get0_key(rsa, &n, &e, NULL); -+ if (rsa && n && e && - pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) { - if ((key = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); -diff -up openssh/ssh-rsa.c.openssl openssh/ssh-rsa.c ---- openssh/ssh-rsa.c.openssl 2017-09-19 06:26:43.000000000 +0200 -+++ openssh/ssh-rsa.c 2017-09-26 13:19:31.803249734 +0200 -@@ -78,38 +78,50 @@ rsa_hash_alg_nid(int type) - } - - int --ssh_rsa_generate_additional_parameters(struct sshkey *key) -+ssh_rsa_generate_additional_parameters(struct sshkey *key, BIGNUM *iqmp) - { - BIGNUM *aux = NULL; - BN_CTX *ctx = NULL; -- BIGNUM d; -+ BIGNUM *d = NULL; - int r; -+ const BIGNUM *p, *q, *rsa_d; -+ BIGNUM *dmp1 = NULL, *dmq1 = NULL; - - if (key == NULL || key->rsa == NULL || - sshkey_type_plain(key->type) != KEY_RSA) - return SSH_ERR_INVALID_ARGUMENT; - -- if ((ctx = BN_CTX_new()) == NULL) -- return SSH_ERR_ALLOC_FAIL; -- if ((aux = BN_new()) == NULL) { -+ RSA_get0_factors(key->rsa, &p, &q); -+ RSA_get0_key(key->rsa, NULL, NULL, &rsa_d); -+ -+ if ((ctx = BN_CTX_new()) == NULL || -+ (aux = BN_new()) == NULL || -+ (d = BN_new()) == NULL || -+ (dmp1 = BN_new()) == NULL || -+ (dmq1 = BN_new()) == NULL) { - r = SSH_ERR_ALLOC_FAIL; - goto out; - } - BN_set_flags(aux, BN_FLG_CONSTTIME); - -- BN_init(&d); -- BN_with_flags(&d, key->rsa->d, BN_FLG_CONSTTIME); -+ BN_with_flags(d, rsa_d, BN_FLG_CONSTTIME); - -- if ((BN_sub(aux, key->rsa->q, BN_value_one()) == 0) || -- (BN_mod(key->rsa->dmq1, &d, aux, ctx) == 0) || -- (BN_sub(aux, key->rsa->p, BN_value_one()) == 0) || -- (BN_mod(key->rsa->dmp1, &d, aux, ctx) == 0)) { -+ if ((BN_sub(aux, q, BN_value_one()) == 0) || -+ (BN_mod(dmq1, d, aux, ctx) == 0) || -+ (BN_sub(aux, p, BN_value_one()) == 0) || -+ (BN_mod(dmp1, d, aux, ctx) == 0) || -+ (RSA_set0_crt_params(key->rsa, dmp1, dmq1, iqmp) == 0)) { - r = SSH_ERR_LIBCRYPTO_ERROR; - goto out; - } -+ dmp1 = NULL; -+ dmq1 = NULL; - r = 0; - out: -+ BN_free(d); - BN_clear_free(aux); -+ BN_clear_free(dmp1); -+ BN_clear_free(dmq1); - BN_CTX_free(ctx); - return r; - } -@@ -136,7 +145,7 @@ ssh_rsa_sign(const struct sshkey *key, u - if (key == NULL || key->rsa == NULL || hash_alg == -1 || - sshkey_type_plain(key->type) != KEY_RSA) - return SSH_ERR_INVALID_ARGUMENT; -- if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) -+ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) - return SSH_ERR_KEY_LENGTH; - slen = RSA_size(key->rsa); - if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) -@@ -210,7 +219,7 @@ ssh_rsa_verify(const struct sshkey *key, - sshkey_type_plain(key->type) != KEY_RSA || - sig == NULL || siglen == 0) - return SSH_ERR_INVALID_ARGUMENT; -- if (BN_num_bits(key->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) ---- openssh-7.6p1/configure.ac.openssl 2017-10-04 15:47:48.440672023 +0200 -+++ openssh-7.6p1/configure.ac 2017-10-04 15:47:23.327531495 +0200 -@@ -2730,6 +2730,7 @@ - AC_MSG_ERROR([OpenSSL >= 1.0.1 required (have "$ssl_library_ver")]) - ;; - 100*) ;; # 1.0.x -+ 101*) ;; # 1.1.x is supported by this patch too - 200*) ;; # LibreSSL - *) - AC_MSG_ERROR([OpenSSL >= 1.1.0 is not yet supported (have "$ssl_library_ver")]) diff --git a/openssh-7.3p1-x11-max-displays.patch b/openssh-7.3p1-x11-max-displays.patch index 94dac8f5bf4525b81cada77c0626f6c631836380..c8a147b809e9f4f1d9a7ede2e98e2dbc16c21a03 100644 --- a/openssh-7.3p1-x11-max-displays.patch +++ b/openssh-7.3p1-x11-max-displays.patch @@ -59,7 +59,7 @@ diff -up openssh-7.4p1/channels.c.x11max openssh-7.4p1/channels.c ssh_gai_strerror(gaierr)); @@ -4457,7 +4463,7 @@ x11_connect_display(void) /* Connect it to the display. */ - if (connect(sock, ai->ai_addr, ai->ai_addrlen) < 0) { + if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { debug2("connect %.100s port %u: %.100s", buf, - 6000 + display_number, strerror(errno)); + X11_PORT_MIN + display_number, strerror(errno)); @@ -197,7 +197,7 @@ diff -up openssh-7.4p1/sshd_config.5.x11max openssh-7.4p1/sshd_config.5 +.Cm X11MaxDisplays , .Cm X11Forwarding and - .Cm X11UseLocalHost . + .Cm X11UseLocalhost . @@ -1566,6 +1567,12 @@ Specifies the first display number avail X11 forwarding. This prevents sshd from interfering with real X11 servers. diff --git a/openssh-7.5p1-gssapi-kex-with-ec.patch b/openssh-7.5p1-gssapi-kex-with-ec.patch deleted file mode 100644 index 5f2763a08d8ef37a7c3194b6052498986af3cf57..0000000000000000000000000000000000000000 --- a/openssh-7.5p1-gssapi-kex-with-ec.patch +++ /dev/null @@ -1,1377 +0,0 @@ -From 6ff8f667f792052fd47689c3e421fcd6ddca1cd0 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Fri, 25 Aug 2017 19:15:48 +0200 -Subject: [PATCH 1/3] GSSAPI Key exchange methods with DH and SHA2 - ---- - gss-genr.c | 10 ++++++++++ - kex.c | 2 ++ - kex.h | 2 ++ - kexgssc.c | 6 ++++++ - kexgsss.c | 6 ++++++ - monitor.c | 2 ++ - regress/kextype.sh | 4 +++- - regress/rekey.sh | 8 ++++++-- - ssh-gss.h | 2 ++ - ssh_config.5 | 4 +++- - sshconnect2.c | 2 ++ - sshd.c | 2 ++ - sshd_config.5 | 4 +++- - 13 files changed, 49 insertions(+), 5 deletions(-) - -diff --git a/gss-genr.c b/gss-genr.c -index dc63682d..c6eff3d7 100644 ---- a/gss-genr.c -+++ b/gss-genr.c -@@ -183,6 +183,16 @@ ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { - return GSS_C_NO_OID; - name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; - break; -+ case KEX_GSS_GRP14_SHA256: -+ if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA256_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GRP14_SHA256_ID) - 1; -+ break; -+ case KEX_GSS_GRP16_SHA512: -+ if (strlen(name) < sizeof(KEX_GSS_GRP16_SHA512_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GRP16_SHA512_ID) - 1; -+ break; - case KEX_GSS_GEX_SHA1: - if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) - return GSS_C_NO_OID; -diff --git a/kex.c b/kex.c -index 63e028fa..e798fecb 100644 ---- a/kex.c -+++ b/kex.c -@@ -112,6 +112,8 @@ static const struct kexalg kexalgs[] = { - { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, - { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, - { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, -+ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, - #endif - { NULL, -1, -1, -1}, - }; -diff --git a/kex.h b/kex.h -index 8a2b37c5..f27958ae 100644 ---- a/kex.h -+++ b/kex.h -@@ -102,6 +102,8 @@ enum kex_exchange { - #ifdef GSSAPI - KEX_GSS_GRP1_SHA1, - KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GRP14_SHA256, -+ KEX_GSS_GRP16_SHA512, - KEX_GSS_GEX_SHA1, - #endif - KEX_MAX -diff --git a/kexgssc.c b/kexgssc.c -index 132df8b5..ed23f06d 100644 ---- a/kexgssc.c -+++ b/kexgssc.c -@@ -88,8 +88,12 @@ kexgss_client(struct ssh *ssh) { - dh = dh_new_group1(); - break; - case KEX_GSS_GRP14_SHA1: -+ case KEX_GSS_GRP14_SHA256: - dh = dh_new_group14(); - break; -+ case KEX_GSS_GRP16_SHA512: -+ dh = dh_new_group16(); -+ break; - case KEX_GSS_GEX_SHA1: - debug("Doing group exchange\n"); - nbits = dh_estimate(ssh->kex->we_need * 8); -@@ -272,6 +276,8 @@ kexgss_client(struct ssh *ssh) { - switch (ssh->kex->kex_type) { - case KEX_GSS_GRP1_SHA1: - case KEX_GSS_GRP14_SHA1: -+ case KEX_GSS_GRP14_SHA256: -+ case KEX_GSS_GRP16_SHA512: - kex_dh_hash(ssh->kex->hash_alg, ssh->kex->client_version_string, - ssh->kex->server_version_string, - sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), -diff --git a/kexgsss.c b/kexgsss.c -index 82a715cc..b7da8823 100644 ---- a/kexgsss.c -+++ b/kexgsss.c -@@ -104,8 +104,12 @@ kexgss_server(struct ssh *ssh) - dh = dh_new_group1(); - break; - case KEX_GSS_GRP14_SHA1: -+ case KEX_GSS_GRP14_SHA256: - dh = dh_new_group14(); - break; -+ case KEX_GSS_GRP16_SHA512: -+ dh = dh_new_group16(); -+ break; - case KEX_GSS_GEX_SHA1: - debug("Doing group exchange"); - packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); -@@ -223,6 +227,8 @@ kexgss_server(struct ssh *ssh) - switch (ssh->kex->kex_type) { - case KEX_GSS_GRP1_SHA1: - case KEX_GSS_GRP14_SHA1: -+ case KEX_GSS_GRP14_SHA256: -+ case KEX_GSS_GRP16_SHA512: - kex_dh_hash(ssh->kex->hash_alg, - ssh->kex->client_version_string, ssh->kex->server_version_string, - sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), -diff --git a/monitor.c b/monitor.c -index 17046936..d6bc7ac7 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -1648,6 +1648,8 @@ monitor_apply_keystate(struct monitor *pmonitor) - if (options.gss_keyex) { - kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; - kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; -+ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; - } - #endif -diff --git a/regress/kextype.sh b/regress/kextype.sh -index 780362ca..45f4f16d 100644 ---- a/regress/kextype.sh -+++ b/regress/kextype.sh -@@ -14,7 +14,9 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy - - tries="1 2 3 4" - for k in `${SSH} -Q kex`; do -- if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o $k = "gss-group14-sha1-" ]; then -+ if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o \ -+ $k = "gss-group14-sha1-" -o $k = "gss-group14-sha256-" -o \ -+ $k = "gss-group16-sha512-" ]; then - continue - fi - verbose "kex $k" -diff --git a/regress/rekey.sh b/regress/rekey.sh -index 9fbe9b38..a2921bef 100644 ---- a/regress/rekey.sh -+++ b/regress/rekey.sh -@@ -38,7 +38,9 @@ increase_datafile_size 300 - - opts="" - for i in `${SSH} -Q kex`; do -- if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o $i = "gss-group14-sha1-" ]; then -+ if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o \ -+ $i = "gss-group14-sha1-" -o $i = "gss-group14-sha256-" -o \ -+ $i = "gss-group16-sha512-" ]; then - continue - fi - opts="$opts KexAlgorithms=$i" -@@ -59,7 +61,9 @@ done - if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then - for c in `${SSH} -Q cipher-auth`; do - for kex in `${SSH} -Q kex`; do -- if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o $kex = "gss-group14-sha1-" ]; then -+ if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o \ -+ $kex = "gss-group14-sha1-" -o $kex = "gss-group14-sha256-" -o \ -+ $kex = "gss-group16-sha512-" ]; then - continue - fi - verbose "client rekey $c $kex" -diff --git a/ssh-gss.h b/ssh-gss.h -index 6b6adb2b..7bf8d75e 100644 ---- a/ssh-gss.h -+++ b/ssh-gss.h -@@ -70,6 +70,8 @@ - #define SSH2_MSG_KEXGSS_GROUP 41 - #define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" - #define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" -+#define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-" -+#define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-" - #define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" - - #define GSS_KEX_DEFAULT_KEX \ -diff --git a/ssh_config.5 b/ssh_config.5 -index 6b24649e..3d6da510 100644 ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -760,7 +760,9 @@ key exchange. Possible values are - .Bd -literal -offset 3n - gss-gex-sha1-, - gss-group1-sha1-, --gss-group14-sha1- -+gss-group14-sha1-, -+gss-group14-sha256-, -+gss-group16-sha512- - .Ed - .Pp - The default is -diff --git a/sshconnect2.c b/sshconnect2.c -index 8db98293..5d6b8be0 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -253,6 +253,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) - if (options.gss_keyex) { - kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; - kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; -+ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client; -+ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; - } - #endif -diff --git a/sshd.c b/sshd.c -index 895df26f..e4c879a2 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -2244,6 +2244,8 @@ do_ssh2_kex(void) - if (options.gss_keyex) { - kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; - kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; -+ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; - } - #endif -diff --git a/sshd_config.5 b/sshd_config.5 -index bf81f6af..0793418b 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -675,7 +675,9 @@ key exchange. Possible values are - .Bd -literal -offset 3n - gss-gex-sha1-, - gss-group1-sha1-, --gss-group14-sha1- -+gss-group14-sha1-, -+gss-group14-sha256-, -+gss-group16-sha512- - .Ed - .Pp - The default is --- -2.13.5 - - -From 7d56144903fc625c33da7fabf103f4f6bba4d43a Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Tue, 29 Aug 2017 15:32:14 +0200 -Subject: [PATCH 2/3] GSSAPI Key exchange using ECDH and SHA2 - ---- - gss-genr.c | 10 ++ - kex.c | 3 + - kex.h | 4 + - kexgssc.c | 392 ++++++++++++++++++++++++++++++++++++++++++++++++++++- - kexgsss.c | 333 +++++++++++++++++++++++++++++++++++++++++++++ - monitor.c | 5 +- - regress/kextype.sh | 1 + - regress/rekey.sh | 2 + - ssh-gss.h | 2 + - ssh_config.5 | 4 +- - sshconnect2.c | 2 + - sshd.c | 2 + - sshd_config.5 | 4 +- - 13 files changed, 754 insertions(+), 10 deletions(-) - -diff --git a/gss-genr.c b/gss-genr.c -index c6eff3d7..22040244 100644 ---- a/gss-genr.c -+++ b/gss-genr.c -@@ -198,6 +198,16 @@ ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { - return GSS_C_NO_OID; - name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; - break; -+ case KEX_GSS_NISTP256_SHA256: -+ if (strlen(name) < sizeof(KEX_GSS_NISTP256_SHA256_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_NISTP256_SHA256_ID) - 1; -+ break; -+ case KEX_GSS_C25519_SHA256: -+ if (strlen(name) < sizeof(KEX_GSS_C25519_SHA256_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_C25519_SHA256_ID) - 1; -+ break; - default: - return GSS_C_NO_OID; - } -diff --git a/kex.c b/kex.c -index e798fecb..bdeeada9 100644 ---- a/kex.c -+++ b/kex.c -@@ -114,6 +114,9 @@ static const struct kexalg kexalgs[] = { - { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, - { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, - { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, -+ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, -+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, -+ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, - #endif - { NULL, -1, -1, -1}, - }; -diff --git a/kex.h b/kex.h -index f27958ae..7def8561 100644 ---- a/kex.h -+++ b/kex.h -@@ -105,6 +105,8 @@ enum kex_exchange { - KEX_GSS_GRP14_SHA256, - KEX_GSS_GRP16_SHA512, - KEX_GSS_GEX_SHA1, -+ KEX_GSS_NISTP256_SHA256, -+ KEX_GSS_C25519_SHA256, - #endif - KEX_MAX - }; -@@ -211,6 +213,8 @@ int kexecdh_server(struct ssh *); - int kexc25519_client(struct ssh *); - int kexc25519_server(struct ssh *); - #ifdef GSSAPI -+int kexecgss_client(struct ssh *); -+int kexecgss_server(struct ssh *); - int kexgss_client(struct ssh *); - int kexgss_server(struct ssh *); - #endif -diff --git a/kexgssc.c b/kexgssc.c -index ed23f06d..bdb3109a 100644 ---- a/kexgssc.c -+++ b/kexgssc.c -@@ -43,6 +43,7 @@ - #include "packet.h" - #include "dh.h" - #include "digest.h" -+#include "ssherr.h" - - #include "ssh-gss.h" - -@@ -52,7 +53,7 @@ kexgss_client(struct ssh *ssh) { - gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; - Gssctxt *ctxt; - OM_uint32 maj_status, min_status, ret_flags; -- u_int klen, kout, slen = 0, strlen; -+ u_int klen, kout, slen = 0, packet_len; - DH *dh; - BIGNUM *dh_server_pub = NULL; - BIGNUM *shared_secret = NULL; -@@ -201,20 +202,20 @@ kexgss_client(struct ssh *ssh) { - debug("Received GSSAPI_CONTINUE"); - if (maj_status == GSS_S_COMPLETE) - fatal("GSSAPI Continue received from server when complete"); -- recv_tok.value = packet_get_string(&strlen); -- recv_tok.length = strlen; -+ recv_tok.value = packet_get_string(&packet_len); -+ recv_tok.length = packet_len; - break; - case SSH2_MSG_KEXGSS_COMPLETE: - debug("Received GSSAPI_COMPLETE"); - packet_get_bignum2(dh_server_pub); -- msg_tok.value = packet_get_string(&strlen); -- msg_tok.length = strlen; -+ msg_tok.value = packet_get_string(&packet_len); -+ msg_tok.length = packet_len; - - /* Is there a token included? */ - if (packet_get_char()) { - recv_tok.value= -- packet_get_string(&strlen); -- recv_tok.length = strlen; -+ packet_get_string(&packet_len); -+ recv_tok.length = packet_len; - /* If we're already complete - protocol error */ - if (maj_status == GSS_S_COMPLETE) - packet_disconnect("Protocol error: received token when complete"); -@@ -344,4 +345,382 @@ kexgss_client(struct ssh *ssh) { - return kex_send_newkeys(ssh); - } - -+int -+kexecgss_client(struct ssh *ssh) { -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; -+ Gssctxt *ctxt; -+ OM_uint32 maj_status, min_status, ret_flags; -+ u_int klen = 0, slen = 0, packet_len; -+ u_char *server_pub = NULL; -+ u_int server_pub_len = 0; -+ BIGNUM *shared_secret = NULL; -+ u_char *kbuf = NULL; -+ u_char *serverhostkey = NULL; -+ u_char *empty = ""; -+ char *msg; -+ char *lang; -+ int type = 0; -+ int first = 1; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; -+ const EC_GROUP *group = NULL; -+ const EC_POINT *public_key; -+ struct sshbuf *Q_C = NULL; -+ struct kex *kex = ssh->kex; -+ EC_POINT *server_public = NULL; -+ struct sshbuf *c25519_shared_secret = NULL; -+ int r; -+ -+ /* Initialise our GSSAPI world */ -+ ssh_gssapi_build_ctx(&ctxt); -+ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) -+ == GSS_C_NO_OID) -+ fatal("Couldn't identify host exchange"); -+ -+ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) -+ fatal("Couldn't import hostname"); -+ -+ if (kex->gss_client && -+ ssh_gssapi_client_identity(ctxt, kex->gss_client)) -+ fatal("Couldn't acquire client credentials"); -+ -+ if ((Q_C = sshbuf_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ if ((kex->ec_client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ if (EC_KEY_generate_key(kex->ec_client_key) != 1) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ group = EC_KEY_get0_group(kex->ec_client_key); -+ public_key = EC_KEY_get0_public_key(kex->ec_client_key); -+#ifdef DEBUG_KEXECDH -+ fputs("client private key:\n", stderr); -+ sshkey_dump_ec_key(kex->ec_client_key); -+#endif -+ -+ sshbuf_put_ec(Q_C, public_key, group); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ kexc25519_keygen(kex->c25519_client_key, kex->c25519_client_pubkey); -+#ifdef DEBUG_KEXECDH -+ dump_digest("client private key:", kex->c25519_client_key, -+ sizeof(kex->c25519_client_key)); -+#endif -+ -+ if ((r = sshbuf_put_string(Q_C, kex->c25519_client_pubkey, -+ sizeof(kex->c25519_client_pubkey))) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ token_ptr = GSS_C_NO_BUFFER; -+ -+ do { -+ /* Step 2 - call GSS_Init_sec_context() */ -+ debug("Calling gss_init_sec_context"); -+ -+ maj_status = ssh_gssapi_init_ctx(ctxt, -+ kex->gss_deleg_creds, token_ptr, &send_tok, -+ &ret_flags); -+ -+ if (GSS_ERROR(maj_status)) { -+ if (send_tok.length != 0) { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ } -+ fatal("gss_init_context failed"); -+ } -+ -+ /* If we've got an old receive buffer get rid of it */ -+ if (token_ptr != GSS_C_NO_BUFFER) -+ free(recv_tok.value); -+ -+ if (maj_status == GSS_S_COMPLETE) { -+ /* If mutual state flag is not true, kex fails */ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual authentication failed"); -+ -+ /* If integ avail flag is not true kex fails */ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity check failed"); -+ } -+ -+ /* -+ * If we have data to send, then the last message that we -+ * received cannot have been a 'complete'. -+ */ -+ if (send_tok.length != 0) { -+ if (first) { -+ const u_char * ptr; -+ size_t len; -+ -+ packet_start(SSH2_MSG_KEXGSS_INIT); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ sshbuf_get_string_direct(Q_C, &ptr, &len); -+ packet_put_string(ptr, len); -+ first = 0; -+ } else { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ } -+ packet_send(); -+ gss_release_buffer(&min_status, &send_tok); -+ -+ /* If we've sent them data, they should reply */ -+ do { -+ type = packet_read(); -+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { -+ debug("Received KEXGSS_HOSTKEY"); -+ if (serverhostkey) -+ fatal("Server host key received more than once"); -+ serverhostkey = -+ packet_get_string(&slen); -+ } -+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); -+ -+ switch (type) { -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ debug("Received GSSAPI_CONTINUE"); -+ if (maj_status == GSS_S_COMPLETE) -+ fatal("GSSAPI Continue received from server when complete"); -+ recv_tok.value = packet_get_string(&packet_len); -+ recv_tok.length = packet_len; -+ break; -+ case SSH2_MSG_KEXGSS_COMPLETE: -+ debug("Received GSSAPI_COMPLETE"); -+ server_pub = packet_get_string(&server_pub_len); -+ msg_tok.value = packet_get_string(&packet_len); -+ msg_tok.length = packet_len; -+ -+ /* Is there a token included? */ -+ if (packet_get_char()) { -+ recv_tok.value= -+ packet_get_string(&packet_len); -+ recv_tok.length = packet_len; -+ /* If we're already complete - protocol error */ -+ if (maj_status == GSS_S_COMPLETE) -+ packet_disconnect("Protocol error: received token when complete"); -+ } else { -+ /* No token included */ -+ if (maj_status != GSS_S_COMPLETE) -+ packet_disconnect("Protocol error: did not receive final token"); -+ } -+ break; -+ case SSH2_MSG_KEXGSS_ERROR: -+ debug("Received Error"); -+ maj_status = packet_get_int(); -+ min_status = packet_get_int(); -+ msg = packet_get_string(NULL); -+ lang = packet_get_string(NULL); -+ fatal("GSSAPI Error: \n%.400s",msg); -+ default: -+ packet_disconnect("Protocol error: didn't expect packet type %d", -+ type); -+ } -+ token_ptr = &recv_tok; -+ } else { -+ /* No data, and not complete */ -+ if (maj_status != GSS_S_COMPLETE) -+ fatal("Not complete, and no token output"); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ /* -+ * We _must_ have received a COMPLETE message in reply from the -+ * server, which will have set dh_server_pub and msg_tok -+ */ -+ -+ if (type != SSH2_MSG_KEXGSS_COMPLETE) -+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); -+ -+ /* 7. C verifies that the key Q_S is valid */ -+ /* 8. C computes shared secret */ -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ if (server_pub_len != 65) -+ fatal("The received NIST-P256 key did not match" -+ "expected length (expected 65, got %d)", server_pub_len); -+ -+ if (server_pub[0] != POINT_CONVERSION_UNCOMPRESSED) -+ fatal("The received NIST-P256 key does not have first octet 0x04"); -+ -+ if ((server_public = EC_POINT_new(group)) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if (!EC_POINT_oct2point(group, server_public, server_pub, -+ server_pub_len, NULL)) -+ fatal("Can not decode received NIST-P256 client key"); -+#ifdef DEBUG_KEXECDH -+ fputs("server public key:\n", stderr); -+ sshkey_dump_ec_point(group, server_public); -+#endif -+ -+ if (sshkey_ec_validate_public(group, server_public) != 0) { -+ sshpkt_disconnect(ssh, "invalid client public key"); -+ r = SSH_ERR_MESSAGE_INCOMPLETE; -+ goto out; -+ } -+ -+ if (!EC_POINT_is_on_curve(group, server_public, NULL)) -+ fatal("Received NIST-P256 client key is not on curve"); -+ -+ /* Calculate shared_secret */ -+ klen = (EC_GROUP_get_degree(group) + 7) / 8; -+ if ((kbuf = malloc(klen)) == NULL || -+ (shared_secret = BN_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ if (ECDH_compute_key(kbuf, klen, server_public, -+ kex->ec_client_key, NULL) != (int)klen || -+ BN_bin2bn(kbuf, klen, shared_secret) == NULL) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+#ifdef DEBUG_KEXECDH -+ dump_digest("shared secret", kbuf, klen); -+#endif -+ break; -+ case KEX_GSS_C25519_SHA256: -+ if (server_pub_len != 32) -+ fatal("The received curve25519 key did not match" -+ "expected length (expected 32, got %d)", server_pub_len); -+ -+ if (server_pub[server_pub_len-1] & 0x80) -+ fatal("The received key has MSB of last octet set!"); -+#ifdef DEBUG_KEXECDH -+ dump_digest("server public key:", server_pub, CURVE25519_SIZE); -+#endif -+ -+ /* generate shared secret */ -+ if ((c25519_shared_secret = sshbuf_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ if ((r = kexc25519_shared_key(kex->c25519_client_key, -+ server_pub, c25519_shared_secret)) < 0) -+ goto out; -+ -+ /* if all octets of the shared secret are zero octets, -+ * is already checked in kexc25519_shared_key() */ -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ hashlen = sizeof(hash); -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ kex_ecdh_hash( -+ kex->hash_alg, -+ group, -+ kex->client_version_string, -+ kex->server_version_string, -+ sshbuf_ptr(kex->my), sshbuf_len(kex->my), -+ sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), -+ (serverhostkey ? serverhostkey : empty), slen, -+ EC_KEY_get0_public_key(kex->ec_client_key), -+ server_public, -+ shared_secret, -+ hash, &hashlen -+ ); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ kex_c25519_hash( -+ kex->hash_alg, -+ kex->client_version_string, kex->server_version_string, -+ sshbuf_ptr(kex->my), sshbuf_len(kex->my), -+ sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), -+ (serverhostkey ? serverhostkey : empty), slen, -+ kex->c25519_client_pubkey, server_pub, -+ sshbuf_ptr(c25519_shared_secret), sshbuf_len(c25519_shared_secret), -+ hash, &hashlen -+ ); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ -+ /* Verify that the hash matches the MIC we just got. */ -+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) -+ packet_disconnect("Hash's MIC didn't verify"); -+ -+ free(msg_tok.value); -+ -+ /* save session id */ -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); -+ } -+ -+ if (kex->gss_deleg_creds) -+ ssh_gssapi_credentials_updated(ctxt); -+ -+ if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; -+ else -+ ssh_gssapi_delete_ctx(&ctxt); -+ -+ /* Finally derive the keys and send them */ -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) != 0) -+ goto out; -+ break; -+ case KEX_GSS_C25519_SHA256: -+ if ((r = kex_derive_keys(ssh, hash, hashlen, c25519_shared_secret)) != 0) -+ goto out; -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ r = kex_send_newkeys(ssh); -+out: -+ free(serverhostkey); -+ explicit_bzero(hash, sizeof(hash)); -+ sshbuf_free(Q_C); -+ if (server_pub) -+ free(server_pub); -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ if (kex->ec_client_key) { -+ EC_KEY_free(kex->ec_client_key); -+ kex->ec_client_key = NULL; -+ } -+ if (server_public) -+ EC_POINT_clear_free(server_public); -+ if (kbuf) { -+ explicit_bzero(kbuf, klen); -+ free(kbuf); -+ } -+ if (shared_secret) -+ BN_clear_free(shared_secret); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); -+ sshbuf_free(c25519_shared_secret); -+ break; -+ } -+ return r; -+} - #endif /* GSSAPI */ -diff --git a/kexgsss.c b/kexgsss.c -index b7da8823..a7c42803 100644 ---- a/kexgsss.c -+++ b/kexgsss.c -@@ -46,6 +46,7 @@ - #include "servconf.h" - #include "ssh-gss.h" - #include "digest.h" -+#include "ssherr.h" - - extern ServerOptions options; - -@@ -303,4 +304,338 @@ kexgss_server(struct ssh *ssh) - ssh_gssapi_rekey_creds(); - return 0; - } -+ -+int -+kexecgss_server(struct ssh *ssh) -+{ -+ OM_uint32 maj_status, min_status; -+ -+ /* -+ * Some GSSAPI implementations use the input value of ret_flags (an -+ * output variable) as a means of triggering mechanism specific -+ * features. Initializing it to zero avoids inadvertently -+ * activating this non-standard behaviour. -+ */ -+ -+ OM_uint32 ret_flags = 0; -+ gss_buffer_desc gssbuf, recv_tok, msg_tok; -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ Gssctxt *ctxt = NULL; -+ u_int slen, klen = 0; -+ u_char *kbuf = NULL; -+ BIGNUM *shared_secret = NULL; -+ int type = 0; -+ gss_OID oid; -+ char *mechs; -+ u_char hash[SSH_DIGEST_MAX_LENGTH]; -+ size_t hashlen; -+ u_char *client_pub = NULL; -+ u_int client_pub_len = 0; -+ const EC_GROUP *group = NULL; -+ EC_POINT *client_public = NULL; -+ EC_KEY *server_key = NULL; -+ const EC_POINT *public_key; -+ u_char c25519_server_key[CURVE25519_SIZE]; -+ u_char c25519_server_pubkey[CURVE25519_SIZE]; -+ struct sshbuf *c25519_shared_secret = NULL; -+ struct sshbuf *Q_S; -+ struct kex *kex = ssh->kex; -+ int r; -+ -+ /* Initialise GSSAPI */ -+ -+ /* If we're rekeying, privsep means that some of the private structures -+ * in the GSSAPI code are no longer available. This kludges them back -+ * into life -+ */ -+ if (!ssh_gssapi_oid_table_ok()) -+ if ((mechs = ssh_gssapi_server_mechanisms())) -+ free(mechs); -+ -+ debug2("%s: Identifying %s", __func__, kex->name); -+ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); -+ if (oid == GSS_C_NO_OID) -+ fatal("Unknown gssapi mechanism"); -+ -+ debug2("%s: Acquiring credentials", __func__); -+ -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) -+ fatal("Unable to acquire credentials for the server"); -+ -+ if ((Q_S = sshbuf_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ /* 5. S generates an ephemeral key pair (do the allocations early) */ -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ 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) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ group = EC_KEY_get0_group(server_key); -+ public_key = EC_KEY_get0_public_key(server_key); -+ -+ sshbuf_put_ec(Q_S, public_key, group); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ kexc25519_keygen(c25519_server_key, c25519_server_pubkey); -+#ifdef DEBUG_KEXECDH -+ dump_digest("server private key:", c25519_server_key, -+ sizeof(c25519_server_key)); -+#endif -+ if ((r = sshbuf_put_string(Q_S, c25519_server_pubkey, -+ sizeof(c25519_server_pubkey))) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ do { -+ debug("Wait SSH2_MSG_GSSAPI_INIT"); -+ type = packet_read(); -+ switch(type) { -+ case SSH2_MSG_KEXGSS_INIT: -+ if (client_pub != NULL) -+ fatal("Received KEXGSS_INIT after initialising"); -+ recv_tok.value = packet_get_string(&slen); -+ recv_tok.length = slen; -+ -+ client_pub = packet_get_string(&client_pub_len); -+ -+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ -+ break; -+ case SSH2_MSG_KEXGSS_CONTINUE: -+ recv_tok.value = packet_get_string(&slen); -+ recv_tok.length = slen; -+ break; -+ default: -+ packet_disconnect( -+ "Protocol error: didn't expect packet type %d", -+ type); -+ } -+ -+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, -+ &send_tok, &ret_flags)); -+ -+ free(recv_tok.value); -+ -+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) -+ fatal("Zero length token output when incomplete"); -+ -+ if (client_pub == NULL) -+ fatal("No client public key"); -+ -+ if (maj_status & GSS_S_CONTINUE_NEEDED) { -+ debug("Sending GSSAPI_CONTINUE"); -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, send_tok.length); -+ packet_send(); -+ gss_release_buffer(&min_status, &send_tok); -+ } -+ } while (maj_status & GSS_S_CONTINUE_NEEDED); -+ -+ if (GSS_ERROR(maj_status)) { -+ if (send_tok.length > 0) { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, send_tok.length); -+ packet_send(); -+ } -+ fatal("accept_ctx died"); -+ } -+ -+ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) -+ fatal("Mutual Authentication flag wasn't set"); -+ -+ if (!(ret_flags & GSS_C_INTEG_FLAG)) -+ fatal("Integrity flag wasn't set"); -+ -+ /* 3. S verifies that the (client) key is valid */ -+ /* calculate shared secret */ -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ if (client_pub_len != 65) -+ fatal("The received NIST-P256 key did not match" -+ "expected length (expected 65, got %d)", client_pub_len); -+ -+ if (client_pub[0] != POINT_CONVERSION_UNCOMPRESSED) -+ fatal("The received NIST-P256 key does not have first octet 0x04"); -+ -+ if ((client_public = EC_POINT_new(group)) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ -+ if (!EC_POINT_oct2point(group, client_public, client_pub, -+ client_pub_len, NULL)) -+ fatal("Can not decode received NIST-P256 client key"); -+ -+ if (sshkey_ec_validate_public(group, client_public) != 0) { -+ sshpkt_disconnect(ssh, "invalid client public key"); -+ r = SSH_ERR_MESSAGE_INCOMPLETE; -+ goto out; -+ } -+ -+ if (!EC_POINT_is_on_curve(group, client_public, NULL)) -+ fatal("Received NIST-P256 client key is not on curve"); -+ -+ /* Calculate shared_secret */ -+ klen = (EC_GROUP_get_degree(group) + 7) / 8; -+ if ((kbuf = malloc(klen)) == NULL || -+ (shared_secret = BN_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ if (ECDH_compute_key(kbuf, klen, client_public, -+ server_key, NULL) != (int)klen || -+ BN_bin2bn(kbuf, klen, shared_secret) == NULL) { -+ r = SSH_ERR_LIBCRYPTO_ERROR; -+ goto out; -+ } -+ break; -+ case KEX_GSS_C25519_SHA256: -+ if (client_pub_len != 32) -+ fatal("The received curve25519 key did not match" -+ "expected length (expected 32, got %d)", client_pub_len); -+ -+ if (client_pub[client_pub_len-1] & 0x80) -+ fatal("The received key has MSB of last octet set!"); -+ -+ /* generate shared secret */ -+ if ((c25519_shared_secret = sshbuf_new()) == NULL) { -+ r = SSH_ERR_ALLOC_FAIL; -+ goto out; -+ } -+ if ((r = kexc25519_shared_key(c25519_server_key, -+ client_pub, c25519_shared_secret)) < 0) -+ goto out; -+ -+ /* if all octets of the shared secret are zero octets, -+ * is already checked in kexc25519_shared_key() */ -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ hashlen = sizeof(hash); -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ kex_ecdh_hash( -+ kex->hash_alg, -+ group, -+ kex->client_version_string, -+ kex->server_version_string, -+ sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), -+ sshbuf_ptr(kex->my), sshbuf_len(kex->my), -+ NULL, 0, -+ client_public, -+ EC_KEY_get0_public_key(server_key), -+ shared_secret, -+ hash, &hashlen -+ ); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ kex_c25519_hash( -+ kex->hash_alg, -+ kex->client_version_string, kex->server_version_string, -+ sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), -+ sshbuf_ptr(kex->my), sshbuf_len(kex->my), -+ NULL, 0, -+ client_pub, c25519_server_pubkey, -+ sshbuf_ptr(c25519_shared_secret), sshbuf_len(c25519_shared_secret), -+ hash, &hashlen -+ ); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ -+ if (kex->session_id == NULL) { -+ kex->session_id_len = hashlen; -+ kex->session_id = xmalloc(kex->session_id_len); -+ memcpy(kex->session_id, hash, kex->session_id_len); -+ } -+ -+ gssbuf.value = hash; -+ gssbuf.length = hashlen; -+ -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) -+ fatal("Couldn't get MIC"); -+ -+ packet_start(SSH2_MSG_KEXGSS_COMPLETE); -+ { -+ const u_char *ptr; -+ size_t len; -+ if ((r = sshbuf_get_string_direct(Q_S, &ptr, &len)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ packet_put_string(ptr, len); -+ } -+ packet_put_string(msg_tok.value, msg_tok.length); -+ -+ if (send_tok.length != 0) { -+ packet_put_char(1); /* true */ -+ packet_put_string(send_tok.value, send_tok.length); -+ } else { -+ packet_put_char(0); /* false */ -+ } -+ packet_send(); -+ -+ gss_release_buffer(&min_status, &send_tok); -+ gss_release_buffer(&min_status, &msg_tok); -+ -+ if (gss_kex_context == NULL) -+ gss_kex_context = ctxt; -+ else -+ ssh_gssapi_delete_ctx(&ctxt); -+ -+ /* Finally derive the keys and send them */ -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ if ((r = kex_derive_keys_bn(ssh, hash, hashlen, shared_secret)) != 0) -+ goto out; -+ break; -+ case KEX_GSS_C25519_SHA256: -+ if ((r = kex_derive_keys(ssh, hash, hashlen, c25519_shared_secret)) != 0) -+ goto out; -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); -+ } -+ if ((r = kex_send_newkeys(ssh)) != 0) -+ goto out; -+ -+ /* If this was a rekey, then save out any delegated credentials we -+ * just exchanged. */ -+ if (options.gss_store_rekey) -+ ssh_gssapi_rekey_creds(); -+out: -+ explicit_bzero(hash, sizeof(hash)); -+ if (Q_S) -+ sshbuf_free(Q_S); -+ if (client_pub) -+ free(client_pub); -+ switch (kex->kex_type) { -+ case KEX_GSS_NISTP256_SHA256: -+ if (server_key) -+ EC_KEY_free(server_key); -+ if (kbuf) { -+ explicit_bzero(kbuf, klen); -+ free(kbuf); -+ } -+ if (shared_secret) -+ BN_clear_free(shared_secret); -+ break; -+ case KEX_GSS_C25519_SHA256: -+ explicit_bzero(c25519_server_key, sizeof(c25519_server_key)); -+ sshbuf_free(c25519_shared_secret); -+ break; -+ } -+ return r; -+} - #endif /* GSSAPI */ -diff --git a/monitor.c b/monitor.c -index d6bc7ac7..b11616c8 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -1651,6 +1651,8 @@ monitor_apply_keystate(struct monitor *pmonitor) - kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; - kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_NISTP256_SHA256] = kexecgss_server; -+ kex->kex[KEX_GSS_C25519_SHA256] = kexecgss_server; - } - #endif - kex->load_host_public_key=&get_hostkey_public_by_type; -@@ -1867,7 +1869,8 @@ mm_answer_gss_sign(int socket, Buffer *m) - - if ((r = sshbuf_get_string(m, (u_char **)&data.value, &data.length)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); -- if (data.length != 20) -+ /* Lengths of SHA-1, SHA-256 and SHA-512 hashes that are used */ -+ if (data.length != 20 && data.length != 32 && data.length != 64) - fatal("%s: data length incorrect: %d", __func__, - (int) data.length); - -diff --git a/regress/kextype.sh b/regress/kextype.sh -index 45f4f16d..d5b4a713 100644 ---- a/regress/kextype.sh -+++ b/regress/kextype.sh -@@ -15,6 +15,7 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy - tries="1 2 3 4" - for k in `${SSH} -Q kex`; do - if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o \ -+ $k = "gss-nistp256-sha256-" -o $k = "gss-curve25519-sha256-" -o \ - $k = "gss-group14-sha1-" -o $k = "gss-group14-sha256-" -o \ - $k = "gss-group16-sha512-" ]; then - continue -diff --git a/regress/rekey.sh b/regress/rekey.sh -index a2921bef..b118c6c8 100644 ---- a/regress/rekey.sh -+++ b/regress/rekey.sh -@@ -39,6 +39,7 @@ increase_datafile_size 300 - opts="" - for i in `${SSH} -Q kex`; do - if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o \ -+ $i = "gss-nistp256-sha256-" -o $i = "gss-curve25519-sha256-" -o \ - $i = "gss-group14-sha1-" -o $i = "gss-group14-sha256-" -o \ - $i = "gss-group16-sha512-" ]; then - continue -@@ -62,6 +63,7 @@ if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then - for c in `${SSH} -Q cipher-auth`; do - for kex in `${SSH} -Q kex`; do - if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o \ -+ $kex = "gss-nistp256-sha256-" -o $kex = "gss-curve25519-sha256-" -o \ - $kex = "gss-group14-sha1-" -o $kex = "gss-group14-sha256-" -o \ - $kex = "gss-group16-sha512-" ]; then - continue -diff --git a/ssh-gss.h b/ssh-gss.h -index 7bf8d75e..1f73721d 100644 ---- a/ssh-gss.h -+++ b/ssh-gss.h -@@ -73,6 +73,8 @@ - #define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-" - #define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-" - #define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" -+#define KEX_GSS_NISTP256_SHA256_ID "gss-nistp256-sha256-" -+#define KEX_GSS_C25519_SHA256_ID "gss-curve25519-sha256-" - - #define GSS_KEX_DEFAULT_KEX \ - KEX_GSS_GEX_SHA1_ID "," \ -diff --git a/ssh_config.5 b/ssh_config.5 -index 3d6da510..1dc29bf1 100644 ---- a/ssh_config.5 -+++ b/ssh_config.5 -@@ -762,7 +762,9 @@ gss-gex-sha1-, - gss-group1-sha1-, - gss-group14-sha1-, - gss-group14-sha256-, --gss-group16-sha512- -+gss-group16-sha512-, -+gss-nistp256-sha256-, -+gss-curve25519-sha256- - .Ed - .Pp - The default is -diff --git a/sshconnect2.c b/sshconnect2.c -index 5d6b8be0..280ae5a6 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -256,6 +256,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) - kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client; - kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; -+ kex->kex[KEX_GSS_NISTP256_SHA256] = kexecgss_client; -+ kex->kex[KEX_GSS_C25519_SHA256] = kexecgss_client; - } - #endif - kex->kex[KEX_C25519_SHA256] = kexc25519_client; -diff --git a/sshd.c b/sshd.c -index e4c879a2..a35735d8 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -2247,6 +2247,8 @@ do_ssh2_kex(void) - kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; - kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; - kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_NISTP256_SHA256] = kexecgss_server; -+ kex->kex[KEX_GSS_C25519_SHA256] = kexecgss_server; - } - #endif - kex->server = 1; -diff --git a/sshd_config.5 b/sshd_config.5 -index 0793418b..888316bf 100644 ---- a/sshd_config.5 -+++ b/sshd_config.5 -@@ -677,7 +677,9 @@ gss-gex-sha1-, - gss-group1-sha1-, - gss-group14-sha1-, - gss-group14-sha256-, --gss-group16-sha512- -+gss-group16-sha512-, -+gss-nistp256-sha256-, -+gss-curve25519-sha256- - .Ed - .Pp - The default is --- -2.13.5 - - -From 0431695660d5eb1dd1169d42a1624c75a92aa5d2 Mon Sep 17 00:00:00 2001 -From: Jakub Jelen -Date: Wed, 30 Aug 2017 15:30:51 +0200 -Subject: [PATCH 3/3] Simplify rough edges of GSSAPI Kex - ---- - gss-genr.c | 53 +++++++++++++++++------------------------------------ - regress/kextype.sh | 10 ++++------ - regress/rekey.sh | 20 ++++++++------------ - 3 files changed, 29 insertions(+), 54 deletions(-) - -diff --git a/gss-genr.c b/gss-genr.c -index 22040244..c671be31 100644 ---- a/gss-genr.c -+++ b/gss-genr.c -@@ -171,47 +171,28 @@ ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, - gss_OID - ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { - int i = 0; -- -- switch (kex_type) { -- case KEX_GSS_GRP1_SHA1: -- if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) -- return GSS_C_NO_OID; -- name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; -- break; -- case KEX_GSS_GRP14_SHA1: -- if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) -- return GSS_C_NO_OID; -- name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; -- break; -- case KEX_GSS_GRP14_SHA256: -- if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA256_ID)) -- return GSS_C_NO_OID; -- name += sizeof(KEX_GSS_GRP14_SHA256_ID) - 1; -- break; -- case KEX_GSS_GRP16_SHA512: -- if (strlen(name) < sizeof(KEX_GSS_GRP16_SHA512_ID)) -- return GSS_C_NO_OID; -- name += sizeof(KEX_GSS_GRP16_SHA512_ID) - 1; -- break; -- case KEX_GSS_GEX_SHA1: -- if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) -- return GSS_C_NO_OID; -- name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; -- break; -- case KEX_GSS_NISTP256_SHA256: -- if (strlen(name) < sizeof(KEX_GSS_NISTP256_SHA256_ID)) -- return GSS_C_NO_OID; -- name += sizeof(KEX_GSS_NISTP256_SHA256_ID) - 1; -- break; -- case KEX_GSS_C25519_SHA256: -- if (strlen(name) < sizeof(KEX_GSS_C25519_SHA256_ID)) -- return GSS_C_NO_OID; -- name += sizeof(KEX_GSS_C25519_SHA256_ID) - 1; -+ -+#define SKIP_KEX_NAME(type) \ -+ case type: \ -+ if (strlen(name) < sizeof(type##_ID)) \ -+ return GSS_C_NO_OID; \ -+ name += sizeof(type##_ID) - 1; \ - break; -+ -+ switch (kex_type) { -+ SKIP_KEX_NAME(KEX_GSS_GRP1_SHA1) -+ SKIP_KEX_NAME(KEX_GSS_GRP14_SHA1) -+ SKIP_KEX_NAME(KEX_GSS_GRP14_SHA256) -+ SKIP_KEX_NAME(KEX_GSS_GRP16_SHA512) -+ SKIP_KEX_NAME(KEX_GSS_GEX_SHA1) -+ SKIP_KEX_NAME(KEX_GSS_NISTP256_SHA256) -+ SKIP_KEX_NAME(KEX_GSS_C25519_SHA256) - default: - return GSS_C_NO_OID; - } - -+#undef SKIP_KEX_NAME -+ - while (gss_enc2oid[i].encoded != NULL && - strcmp(name, gss_enc2oid[i].encoded) != 0) - i++; -diff --git a/regress/kextype.sh b/regress/kextype.sh -index d5b4a713..6b4af28a 100644 ---- a/regress/kextype.sh -+++ b/regress/kextype.sh -@@ -14,12 +14,10 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy - - tries="1 2 3 4" - for k in `${SSH} -Q kex`; do -- if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o \ -- $k = "gss-nistp256-sha256-" -o $k = "gss-curve25519-sha256-" -o \ -- $k = "gss-group14-sha1-" -o $k = "gss-group14-sha256-" -o \ -- $k = "gss-group16-sha512-" ]; then -- continue -- fi -+ # ignore GSSAPI key exchange mechanisms (all of them start with gss-) -+ case $k in -+ gss-* ) continue ;; -+ esac - verbose "kex $k" - for i in $tries; do - ${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true -diff --git a/regress/rekey.sh b/regress/rekey.sh -index b118c6c8..d6a8742f 100644 ---- a/regress/rekey.sh -+++ b/regress/rekey.sh -@@ -38,12 +38,10 @@ increase_datafile_size 300 - - opts="" - for i in `${SSH} -Q kex`; do -- if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o \ -- $i = "gss-nistp256-sha256-" -o $i = "gss-curve25519-sha256-" -o \ -- $i = "gss-group14-sha1-" -o $i = "gss-group14-sha256-" -o \ -- $i = "gss-group16-sha512-" ]; then -- continue -- fi -+ # ignore GSSAPI key exchange mechanisms (all of them start with gss-) -+ case $i in -+ gss-* ) continue ;; -+ esac - opts="$opts KexAlgorithms=$i" - done - for i in `${SSH} -Q cipher`; do -@@ -62,12 +60,10 @@ done - if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then - for c in `${SSH} -Q cipher-auth`; do - for kex in `${SSH} -Q kex`; do -- if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o \ -- $kex = "gss-nistp256-sha256-" -o $kex = "gss-curve25519-sha256-" -o \ -- $kex = "gss-group14-sha1-" -o $kex = "gss-group14-sha256-" -o \ -- $kex = "gss-group16-sha512-" ]; then -- continue -- fi -+ # ignore GSSAPI key exchange mechanisms (all of them start with gss-) -+ case $kex in -+ gss-* ) continue ;; -+ esac - verbose "client rekey $c $kex" - ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c - done --- -2.13.5 - diff --git a/openssh-7.5p1-sandbox.patch b/openssh-7.5p1-sandbox.patch index b761962fd6e6b7d8eff372b0bad9f21c605b5fed..7217c6419144681ee08064f1d606708d1087c6b1 100644 --- a/openssh-7.5p1-sandbox.patch +++ b/openssh-7.5p1-sandbox.patch @@ -20,8 +20,8 @@ index ca75cc7..6e7de31 100644 +#if defined(__NR_flock) && defined(__s390__) + SC_ALLOW(__NR_flock), +#endif - #ifdef __NR_geteuid - SC_ALLOW(__NR_geteuid), + #ifdef __NR_futex + SC_ALLOW(__NR_futex), #endif @@ -178,6 +181,9 @@ static const struct sock_filter preauth_insns[] = { #ifdef __NR_gettimeofday @@ -69,29 +69,6 @@ index 6e7de31..e86aa2c 100644 SC_ALLOW(__NR_getrandom), #endif -- 1.9.1 - -The EP11 crypto card needs to make an ioctl call, which receives an -specific argument. This crypto card is for s390 only. - -Signed-off-by: Eduardo Barretto ---- - sandbox-seccomp-filter.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c -index e86aa2c..98062f1 100644 ---- a/sandbox-seccomp-filter.c -+++ b/sandbox-seccomp-filter.c -@@ -250,6 +250,8 @@ static const struct sock_filter preauth_insns[] = { - SC_ALLOW_ARG(__NR_ioctl, 1, Z90STAT_STATUS_MASK), - SC_ALLOW_ARG(__NR_ioctl, 1, ICARSAMODEXPO), - SC_ALLOW_ARG(__NR_ioctl, 1, ICARSACRT), -+ /* Allow ioctls for EP11 crypto card on s390 */ -+ SC_ALLOW_ARG(__NR_ioctl, 1, ZSENDEP11CPRB), - #endif - #if defined(__x86_64__) && defined(__ILP32__) && defined(__X32_SYSCALL_BIT) - /* --- 1.9.1 diff -up openssh-7.6p1/sandbox-seccomp-filter.c.sandbox openssh-7.6p1/sandbox-seccomp-filter.c --- openssh-7.6p1/sandbox-seccomp-filter.c.sandbox 2017-12-12 13:59:30.563874059 +0100 @@ -106,3 +83,4 @@ diff -up openssh-7.6p1/sandbox-seccomp-filter.c.sandbox openssh-7.6p1/sandbox-se #ifdef __NR_getrandom SC_ALLOW(__NR_getrandom), #endif + diff --git a/openssh-7.6p1-audit.patch b/openssh-7.6p1-audit.patch index e18489421eeb231abab2136c827e57e608d844b4..98d5709742f12125cc7848529870e51b57a90d56 100644 --- a/openssh-7.6p1-audit.patch +++ b/openssh-7.6p1-audit.patch @@ -1,83 +1,80 @@ -diff -up openssh-7.6p1/audit-bsm.c.audit openssh-7.6p1/audit-bsm.c ---- openssh-7.6p1/audit-bsm.c.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/audit-bsm.c 2017-10-04 17:18:32.834505048 +0200 -@@ -373,10 +373,23 @@ audit_connection_from(const char *host, +diff -up openssh/audit-bsm.c.audit openssh/audit-bsm.c +--- openssh/audit-bsm.c.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/audit-bsm.c 2019-04-03 17:02:20.713886041 +0200 +@@ -372,13 +372,26 @@ audit_connection_from(const char *host, #endif } --void +int - audit_run_command(const char *command) - { - /* not implemented */ -+ return 0; -+} -+ -+void -+audit_end_command(int handle, const char *command) ++audit_run_command(struct ssh *ssh, const char *command) +{ + /* not implemented */ ++ return 0; +} + -+void -+audit_count_session_open(void) -+{ -+ /* not necessary */ + void +-audit_run_command(const char *command) ++audit_end_command(struct ssh *ssh, int handle, const char *command) + { + /* not implemented */ } void -@@ -391,6 +404,12 @@ audit_session_close(struct logininfo *li ++audit_count_session_open(void) ++{ ++ /* not necessary */ ++} ++ ++void + audit_session_open(struct logininfo *li) + { + /* not implemented */ +@@ -390,6 +403,12 @@ audit_session_close(struct logininfo *li /* not implemented */ } +int -+audit_keyusage(int host_user, char *fp, int rv) ++audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) +{ + /* not implemented */ +} + void - audit_event(ssh_audit_event_t event) + audit_event(struct ssh *ssh, ssh_audit_event_t event) { -@@ -452,4 +471,34 @@ audit_event(ssh_audit_event_t event) +@@ -451,4 +470,28 @@ audit_event(struct ssh *ssh, ssh_audit_e debug("%s: unhandled event %d", __func__, event); } } + +void -+audit_unsupported_body(int what) ++audit_unsupported_body(struct ssh *ssh, int what) +{ + /* not implemented */ +} + +void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, uid_t uid) ++audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, uid_t uid) +{ + /* not implemented */ +} + +void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++audit_session_key_free_body(struct ssh * ssh, int ctos, pid_t pid, uid_t uid) +{ + /* not implemented */ +} + +void -+audit_destroy_sensitive_data(const char *fp) -+{ -+ /* not implemented */ -+} -+ -+void -+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) ++audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) +{ + /* not implemented */ +} #endif /* BSM */ -diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c ---- openssh-7.6p1/audit.c.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/audit.c 2017-10-04 17:18:32.834505048 +0200 -@@ -34,6 +35,12 @@ +diff -up openssh/audit.c.audit openssh/audit.c +--- openssh/audit.c.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/audit.c 2019-04-03 17:02:20.713886041 +0200 +@@ -34,6 +34,12 @@ #include "log.h" #include "hostfile.h" #include "auth.h" @@ -119,38 +116,38 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c } +void -+audit_key(int host_user, int *rv, const struct sshkey *key) ++audit_key(struct ssh *ssh, int host_user, int *rv, const struct sshkey *key) +{ + char *fp; + + fp = sshkey_fingerprint(key, options.fingerprint_hash, SSH_FP_HEX); -+ if (audit_keyusage(host_user, fp, (*rv == 0)) == 0) ++ if (audit_keyusage(ssh, host_user, fp, (*rv == 0)) == 0) + *rv = -SSH_ERR_INTERNAL_ERROR; + free(fp); +} + +void -+audit_unsupported(int what) ++audit_unsupported(struct ssh *ssh, int what) +{ -+ PRIVSEP(audit_unsupported_body(what)); ++ PRIVSEP(audit_unsupported_body(ssh, what)); +} + +void -+audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs) ++audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) +{ -+ PRIVSEP(audit_kex_body(ctos, enc, mac, comp, pfs, getpid(), getuid())); ++ PRIVSEP(audit_kex_body(ssh, ctos, enc, mac, comp, pfs, getpid(), getuid())); +} + +void -+audit_session_key_free(int ctos) ++audit_session_key_free(struct ssh *ssh, int ctos) +{ -+ PRIVSEP(audit_session_key_free_body(ctos, getpid(), getuid())); ++ PRIVSEP(audit_session_key_free_body(ssh, ctos, getpid(), getuid())); +} + # ifndef CUSTOM_SSH_AUDIT_EVENTS /* * Null implementations of audit functions. -@@ -138,6 +173,17 @@ audit_event(ssh_audit_event_t event) +@@ -138,6 +171,17 @@ audit_event(struct ssh *ssh, ssh_audit_e } /* @@ -168,7 +165,7 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c * Called when a user session is started. Argument is the tty allocated to * the session, or NULL if no tty was allocated. * -@@ -172,13 +218,82 @@ audit_session_close(struct logininfo *li +@@ -172,13 +216,82 @@ audit_session_close(struct logininfo *li /* * This will be called when a user runs a non-interactive command. Note that * it may be called multiple times for a single connection since SSH2 allows @@ -177,8 +174,9 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c + * audit_end_command. */ -void +-audit_run_command(const char *command) +int - audit_run_command(const char *command) ++audit_run_command(struct ssh *ssh, const char *command) { debug("audit run command euid %d user %s command '%.200s'", geteuid(), audit_username(), command); @@ -192,7 +190,7 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c + * the corresponding audit_run_command. + */ +void -+audit_end_command(int handle, const char *command) ++audit_end_command(struct ssh *ssh, int handle, const char *command) +{ + debug("audit end nopty exec euid %d user %s command '%.200s'", geteuid(), + audit_username(), command); @@ -204,7 +202,7 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c + * Type is the key type, len is the key length(byte) and fp is the fingerprint of the key. + */ +int -+audit_keyusage(int host_user, char *fp, int rv) ++audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) +{ + debug("audit %s key usage euid %d user %s fingerprint %s, result %d", + host_user ? "pubkey" : "hostbased", geteuid(), audit_username(), @@ -215,7 +213,7 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c + * This will be called when the protocol negotiation fails. + */ +void -+audit_unsupported_body(int what) ++audit_unsupported_body(struct ssh *ssh, int what) +{ + debug("audit unsupported protocol euid %d type %d", geteuid(), what); +} @@ -224,7 +222,7 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c + * This will be called on succesfull protocol negotiation. + */ +void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, ++audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, char *pfs, pid_t pid, + uid_t uid) +{ + debug("audit protocol negotiation euid %d direction %d cipher %s mac %s compresion %s pfs %s from pid %ld uid %u", @@ -236,7 +234,7 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c + * This will be called on succesfull session key discard + */ +void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++audit_session_key_free_body(struct ssh *, int ctos, pid_t pid, uid_t uid) +{ + debug("audit session key discard euid %u direction %d from pid %ld uid %u", + (unsigned)geteuid(), ctos, (long)pid, (unsigned)uid); @@ -246,25 +244,25 @@ diff -up openssh-7.6p1/audit.c.audit openssh-7.6p1/audit.c + * This will be called on destroy private part of the server key + */ +void -+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) ++audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) +{ + debug("audit destroy sensitive data euid %d fingerprint %s from pid %ld uid %u", + geteuid(), fp, (long)pid, (unsigned)uid); } # endif /* !defined CUSTOM_SSH_AUDIT_EVENTS */ #endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-7.6p1/audit.h.audit openssh-7.6p1/audit.h ---- openssh-7.6p1/audit.h.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/audit.h 2017-10-04 17:18:32.834505048 +0200 +diff -up openssh/audit.h.audit openssh/audit.h +--- openssh/audit.h.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/audit.h 2019-04-03 17:02:20.713886041 +0200 @@ -26,6 +26,7 @@ # define _SSH_AUDIT_H #include "loginrec.h" +#include "sshkey.h" - enum ssh_audit_event_type { - SSH_LOGIN_EXCEED_MAXTRIES, -@@ -43,13 +44,32 @@ enum ssh_audit_event_type { + struct ssh; + +@@ -45,13 +46,32 @@ enum ssh_audit_event_type { SSH_CONNECTION_ABANDON, /* closed without completing auth */ SSH_AUDIT_UNKNOWN }; @@ -279,28 +277,28 @@ diff -up openssh-7.6p1/audit.h.audit openssh-7.6p1/audit.h +int listening_for_clients(void); + void audit_connection_from(const char *, int); - void audit_event(ssh_audit_event_t); + void audit_event(struct ssh *, ssh_audit_event_t); +void audit_count_session_open(void); void audit_session_open(struct logininfo *); void audit_session_close(struct logininfo *); -void audit_run_command(const char *); -+int audit_run_command(const char *); -+void audit_end_command(int, const char *); ++int audit_run_command(struct ssh *, const char *); ++void audit_end_command(struct ssh *, int, const char *); ssh_audit_event_t audit_classify_auth(const char *); -+int audit_keyusage(int, char *, int); -+void audit_key(int, int *, const struct sshkey *); -+void audit_unsupported(int); -+void audit_kex(int, char *, char *, char *, char *); -+void audit_unsupported_body(int); -+void audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t); -+void audit_session_key_free(int ctos); -+void audit_session_key_free_body(int ctos, pid_t, uid_t); -+void audit_destroy_sensitive_data(const char *, pid_t, uid_t); ++int audit_keyusage(struct ssh *, int, char *, int); ++void audit_key(struct ssh *, int, int *, const struct sshkey *); ++void audit_unsupported(struct ssh *, int); ++void audit_kex(struct ssh *, int, char *, char *, char *, char *); ++void audit_unsupported_body(struct ssh *, int); ++void audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t); ++void audit_session_key_free(struct ssh *, int ctos); ++void audit_session_key_free_body(struct ssh *, int ctos, pid_t, uid_t); ++void audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); #endif /* _SSH_AUDIT_H */ -diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c ---- openssh-7.6p1/audit-linux.c.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/audit-linux.c 2017-10-04 17:18:32.835505053 +0200 +diff -up openssh/audit-linux.c.audit openssh/audit-linux.c +--- openssh/audit-linux.c.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/audit-linux.c 2019-04-03 17:02:20.713886041 +0200 @@ -33,27 +33,40 @@ #include "log.h" @@ -414,7 +412,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c +} + +int -+audit_keyusage(int host_user, char *fp, int rv) ++audit_keyusage(struct ssh *ssh, int host_user, char *fp, int rv) +{ + char buf[AUDIT_LOG_SIZE]; + int audit_fd, rc, saved_errno; @@ -429,12 +427,12 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c + } + snprintf(buf, sizeof(buf), "%s_auth grantors=auth-key", host_user ? "pubkey" : "hostbased"); + rc = audit_log_acct_message(audit_fd, AUDIT_USER_AUTH, NULL, -+ buf, audit_username(), -1, NULL, ssh_remote_ipaddr(active_state), NULL, rv); ++ buf, audit_username(), -1, NULL, ssh_remote_ipaddr(ssh), NULL, rv); + if ((rc < 0) && ((rc != -1) || (getuid() == 0))) + goto out; + snprintf(buf, sizeof(buf), "op=negotiate kind=auth-key fp=%s", fp); + rc = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, buf, NULL, -+ ssh_remote_ipaddr(active_state), NULL, rv); ++ ssh_remote_ipaddr(ssh), NULL, rv); +out: + saved_errno = errno; + audit_close(audit_fd); @@ -448,34 +446,34 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c /* Below is the sshd audit API code */ void -@@ -76,24 +177,55 @@ audit_connection_from(const char *host, +@@ -76,49 +176,210 @@ audit_connection_from(const char *host, /* not implemented */ } --void +int - audit_run_command(const char *command) - { -- /* not implemented */ ++audit_run_command(struct ssh *ssh, const char *command) ++{ + if (!user_login_count++) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ ssh_remote_ipaddr(active_state), ++ ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGIN); + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ ssh_remote_ipaddr(active_state), ++ ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_START); + return 0; +} + -+void -+audit_end_command(int handle, const char *command) -+{ + void +-audit_run_command(const char *command) ++audit_end_command(struct ssh *ssh, int handle, const char *command) + { +- /* not implemented */ + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ ssh_remote_ipaddr(active_state), ++ ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_END); + if (user_login_count && !--user_login_count) + linux_audit_user_logxxx(the_authctxt->pw->pw_uid, NULL, -+ ssh_remote_ipaddr(active_state), ++ ssh_remote_ipaddr(ssh), + "ssh", 1, AUDIT_USER_LOGOUT); +} + @@ -510,9 +508,8 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c } void -@@ -102,25 +231,155 @@ audit_event(ssh_audit_event_t event) - struct ssh *ssh = active_state; /* XXX */ - + audit_event(struct ssh *ssh, ssh_audit_event_t event) + { switch(event) { - case SSH_AUTH_SUCCESS: - case SSH_CONNECTION_CLOSE: @@ -563,7 +560,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c } + +void -+audit_unsupported_body(int what) ++audit_unsupported_body(struct ssh *ssh, int what) +{ +#ifdef AUDIT_CRYPTO_SESSION + char buf[AUDIT_LOG_SIZE]; @@ -572,15 +569,15 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c + int audit_fd; + + snprintf(buf, sizeof(buf), "op=unsupported-%s direction=? cipher=? ksize=? rport=%d laddr=%s lport=%d ", -+ name[what], ssh_remote_port(active_state), (s = get_local_ipaddr(packet_get_connection_in())), -+ ssh_local_port(active_state)); ++ name[what], ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ++ ssh_local_port(ssh)); + free(s); + audit_fd = audit_open(); + if (audit_fd < 0) + /* no problem, the next instruction will be fatal() */ + return; + audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, -+ buf, NULL, ssh_remote_ipaddr(active_state), NULL, 0); ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 0); + audit_close(audit_fd); +#endif +} @@ -588,7 +585,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c +const static char *direction[] = { "from-server", "from-client", "both" }; + +void -+audit_kex_body(int ctos, char *enc, char *mac, char *compress, ++audit_kex_body(struct ssh *ssh, int ctos, char *enc, char *mac, char *compress, + char *pfs, pid_t pid, uid_t uid) +{ +#ifdef AUDIT_CRYPTO_SESSION @@ -600,7 +597,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c + snprintf(buf, sizeof(buf), "op=start direction=%s cipher=%s ksize=%d mac=%s pfs=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", + direction[ctos], enc, cipher ? 8 * cipher->key_len : 0, mac, pfs, + (intmax_t)pid, (intmax_t)uid, -+ ssh_remote_port(active_state), (s = get_local_ipaddr(packet_get_connection_in())), ssh_local_port(active_state)); ++ ssh_remote_port(ssh), (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ssh_local_port(ssh)); + free(s); + audit_fd = audit_open(); + if (audit_fd < 0) { @@ -611,7 +608,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c + fatal("cannot open audit"); /* Must prevent login */ + } + audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_SESSION, -+ buf, NULL, ssh_remote_ipaddr(active_state), NULL, 1); ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1); + audit_close(audit_fd); + /* do not abort if the error is EPERM and sshd is run as non root user */ + if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) @@ -620,7 +617,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c +} + +void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) +{ + char buf[AUDIT_LOG_SIZE]; + int audit_fd, audit_ok; @@ -628,9 +625,9 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c + + snprintf(buf, sizeof(buf), "op=destroy kind=session fp=? direction=%s spid=%jd suid=%jd rport=%d laddr=%s lport=%d ", + direction[ctos], (intmax_t)pid, (intmax_t)uid, -+ ssh_remote_port(active_state), -+ (s = get_local_ipaddr(packet_get_connection_in())), -+ ssh_local_port(active_state)); ++ ssh_remote_port(ssh), ++ (s = get_local_ipaddr(ssh_packet_get_connection_in(ssh))), ++ ssh_local_port(ssh)); + free(s); + audit_fd = audit_open(); + if (audit_fd < 0) { @@ -640,7 +637,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c + return; + } + audit_ok = audit_log_user_message(audit_fd, AUDIT_CRYPTO_KEY_USER, -+ buf, NULL, ssh_remote_ipaddr(active_state), NULL, 1); ++ buf, NULL, ssh_remote_ipaddr(ssh), NULL, 1); + audit_close(audit_fd); + /* do not abort if the error is EPERM and sshd is run as non root user */ + if ((audit_ok < 0) && ((audit_ok != -1) || (getuid() == 0))) @@ -648,7 +645,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c +} + +void -+audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) ++audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) +{ + char buf[AUDIT_LOG_SIZE]; + int audit_fd, audit_ok; @@ -664,7 +661,7 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.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(active_state), ++ 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 */ @@ -672,10 +669,10 @@ diff -up openssh-7.6p1/audit-linux.c.audit openssh-7.6p1/audit-linux.c + error("cannot write into audit"); +} #endif /* USE_LINUX_AUDIT */ -diff -up openssh-7.6p1/auditstub.c.audit openssh-7.6p1/auditstub.c ---- openssh-7.6p1/auditstub.c.audit 2017-10-04 17:18:32.835505053 +0200 -+++ openssh-7.6p1/auditstub.c 2017-10-04 17:18:32.835505053 +0200 -@@ -0,0 +1,50 @@ +diff -up openssh/auditstub.c.audit openssh/auditstub.c +--- openssh/auditstub.c.audit 2019-04-03 17:02:20.714886050 +0200 ++++ openssh/auditstub.c 2019-04-03 17:02:20.714886050 +0200 +@@ -0,0 +1,52 @@ +/* $Id: auditstub.c,v 1.1 jfch Exp $ */ + +/* @@ -707,95 +704,99 @@ diff -up openssh-7.6p1/auditstub.c.audit openssh-7.6p1/auditstub.c + +#include + ++struct ssh; ++ +void -+audit_unsupported(int n) ++audit_unsupported(struct ssh *ssh, int n) +{ +} + +void -+audit_kex(int ctos, char *enc, char *mac, char *comp, char *pfs) ++audit_kex(struct ssh *ssh, int ctos, char *enc, char *mac, char *comp, char *pfs) +{ +} + +void -+audit_session_key_free(int ctos) ++audit_session_key_free(struct ssh *ssh, int ctos) +{ +} + +void -+audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) +{ +} -diff -up openssh-7.6p1/auth2.c.audit openssh-7.6p1/auth2.c ---- openssh-7.6p1/auth2.c.audit 2017-10-04 17:18:32.746504598 +0200 -+++ openssh-7.6p1/auth2.c 2017-10-04 17:18:32.835505053 +0200 -@@ -255,9 +255,6 @@ input_userauth_request(int type, u_int32 +diff -up openssh/auth2.c.audit openssh/auth2.c +--- openssh/auth2.c.audit 2019-04-03 17:02:20.651885453 +0200 ++++ openssh/auth2.c 2019-04-03 17:02:20.714886050 +0200 +@@ -303,9 +303,6 @@ input_userauth_request(int type, u_int32 } else { /* Invalid user, fake password information */ authctxt->pw = fakepw(); -#ifdef SSH_AUDIT_EVENTS -- PRIVSEP(audit_event(SSH_INVALID_USER)); +- PRIVSEP(audit_event(ssh, SSH_INVALID_USER)); -#endif } #ifdef USE_PAM if (options.use_pam) -diff -up openssh-7.6p1/auth2-hostbased.c.audit openssh-7.6p1/auth2-hostbased.c ---- openssh-7.6p1/auth2-hostbased.c.audit 2017-10-04 17:18:32.683504276 +0200 -+++ openssh-7.6p1/auth2-hostbased.c 2017-10-04 17:18:32.835505053 +0200 -@@ -152,7 +152,7 @@ userauth_hostbased(struct ssh *ssh) - /* test for allowed key and correct signature */ +diff -up openssh/auth2-hostbased.c.audit openssh/auth2-hostbased.c +--- openssh/auth2-hostbased.c.audit 2019-04-03 17:02:20.612885083 +0200 ++++ openssh/auth2-hostbased.c 2019-04-03 17:02:20.714886050 +0200 +@@ -158,7 +158,7 @@ userauth_hostbased(struct ssh *ssh) authenticated = 0; - if (PRIVSEP(hostbased_key_allowed(authctxt->pw, cuser, chost, key)) && + if (PRIVSEP(hostbased_key_allowed(ssh, authctxt->pw, cuser, + chost, key)) && - PRIVSEP(sshkey_verify(key, sig, slen, -+ PRIVSEP(hostbased_key_verify(key, sig, slen, - sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat)) == 0) ++ PRIVSEP(hostbased_key_verify(ssh, key, sig, slen, + sshbuf_ptr(b), sshbuf_len(b), pkalg, ssh->compat, NULL)) == 0) authenticated = 1; -@@ -169,6 +169,19 @@ done: +@@ -175,6 +175,20 @@ done: return authenticated; } +int -+hostbased_key_verify(const struct sshkey *key, const u_char *sig, size_t slen, -+ const u_char *data, size_t datalen, const char *pkalg, u_int compat) ++hostbased_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, ++ size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ + int rv; + -+ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat); ++ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat, detailsp); +#ifdef SSH_AUDIT_EVENTS -+ audit_key(0, &rv, key); ++ audit_key(ssh, 0, &rv, key); +#endif + return rv; +} + /* return 1 if given hostkey is allowed */ int - hostbased_key_allowed(struct passwd *pw, const char *cuser, char *chost, -diff -up openssh-7.6p1/auth2-pubkey.c.audit openssh-7.6p1/auth2-pubkey.c ---- openssh-7.6p1/auth2-pubkey.c.audit 2017-10-04 17:18:32.828505018 +0200 -+++ openssh-7.6p1/auth2-pubkey.c 2017-10-04 17:18:32.835505053 +0200 -@@ -206,7 +206,7 @@ userauth_pubkey(struct ssh *ssh) + hostbased_key_allowed(struct ssh *ssh, struct passwd *pw, +diff -up openssh/auth2-pubkey.c.audit openssh/auth2-pubkey.c +--- openssh/auth2-pubkey.c.audit 2019-04-03 17:02:20.691885832 +0200 ++++ openssh/auth2-pubkey.c 2019-04-03 17:02:20.714886050 +0200 +@@ -219,7 +219,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(key, sig, slen, ++ PRIVSEP(user_key_verify(ssh, key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), (ssh->compat & SSH_BUG_SIGTYPE) == 0 ? pkalg : NULL, - ssh->compat)) == 0) { -@@ -250,6 +250,19 @@ done: + ssh->compat, &sig_details)) == 0) { +@@ -278,6 +278,20 @@ done: return authenticated; } +int -+user_key_verify(const struct sshkey *key, const u_char *sig, size_t slen, -+ const u_char *data, size_t datalen, const char *pkalg, u_int compat) ++user_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, ++ size_t slen, const u_char *data, size_t datalen, const char *pkalg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ + int rv; + -+ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat); ++ rv = sshkey_verify(key, sig, slen, data, datalen, pkalg, compat, detailsp); +#ifdef SSH_AUDIT_EVENTS -+ audit_key(1, &rv, key); ++ audit_key(ssh, 1, &rv, key); +#endif + return rv; +} @@ -803,52 +804,52 @@ diff -up openssh-7.6p1/auth2-pubkey.c.audit openssh-7.6p1/auth2-pubkey.c static int match_principals_option(const char *principal_list, struct sshkey_cert *cert) { -diff -up openssh-7.6p1/auth.c.audit openssh-7.6p1/auth.c ---- openssh-7.6p1/auth.c.audit 2017-10-04 17:18:32.746504598 +0200 -+++ openssh-7.6p1/auth.c 2017-10-04 17:18:32.835505053 +0200 -@@ -360,7 +360,7 @@ auth_log(Authctxt *authctxt, int authent +diff -up openssh/auth.c.audit openssh/auth.c +--- openssh/auth.c.audit 2019-04-03 17:02:20.691885832 +0200 ++++ openssh/auth.c 2019-04-03 17:02:20.714886050 +0200 +@@ -366,7 +366,7 @@ auth_log(struct ssh *ssh, int authentica # endif #endif #ifdef SSH_AUDIT_EVENTS - if (authenticated == 0 && !authctxt->postponed) + if (authenticated == 0 && !authctxt->postponed && !partial) - audit_event(audit_classify_auth(method)); + audit_event(ssh, audit_classify_auth(method)); #endif } -@@ -599,9 +599,6 @@ getpwnamallow(const char *user) - record_failed_login(user, +@@ -592,9 +592,6 @@ getpwnamallow(struct ssh *ssh, const cha + record_failed_login(ssh, user, auth_get_canonical_hostname(ssh, options.use_dns), "ssh"); #endif -#ifdef SSH_AUDIT_EVENTS -- audit_event(SSH_INVALID_USER); +- audit_event(ssh, SSH_INVALID_USER); -#endif /* SSH_AUDIT_EVENTS */ return (NULL); } - if (!allowed_user(pw)) -diff -up openssh-7.6p1/auth.h.audit openssh-7.6p1/auth.h ---- openssh-7.6p1/auth.h.audit 2017-10-04 17:18:32.768504711 +0200 -+++ openssh-7.6p1/auth.h 2017-10-04 17:18:32.836505059 +0200 -@@ -198,6 +198,8 @@ struct passwd * getpwnamallow(const char + if (!allowed_user(ssh, pw)) +diff -up openssh/auth.h.audit openssh/auth.h +--- openssh/auth.h.audit 2019-04-03 17:02:20.692885842 +0200 ++++ openssh/auth.h 2019-04-03 17:02:20.714886050 +0200 +@@ -195,6 +195,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(const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int); ++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); -@@ -217,6 +218,8 @@ struct sshkey *get_hostkey_private_by_ty +@@ -214,6 +216,8 @@ struct sshkey *get_hostkey_private_by_ty int get_hostkey_index(struct sshkey *, int, struct ssh *); - int sshd_hostkey_sign(struct sshkey *, struct sshkey *, u_char **, - size_t *, const u_char *, size_t, const char *, u_int); -+int hostbased_key_verify(const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int); + int sshd_hostkey_sign(struct ssh *, struct sshkey *, struct sshkey *, + u_char **, size_t *, const u_char *, size_t, const char *); ++int hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); /* Key / cert options linkage to auth layer */ const struct sshauthopt *auth_options(struct ssh *); -diff -up openssh-7.6p1/cipher.c.audit openssh-7.6p1/cipher.c ---- openssh-7.6p1/cipher.c.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/cipher.c 2017-10-04 17:18:32.836505059 +0200 +diff -up openssh/cipher.c.audit openssh/cipher.c +--- openssh/cipher.c.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/cipher.c 2019-04-03 17:02:20.714886050 +0200 @@ -61,25 +61,6 @@ struct sshcipher_ctx { const struct sshcipher *cipher; }; @@ -875,18 +876,18 @@ diff -up openssh-7.6p1/cipher.c.audit openssh-7.6p1/cipher.c static const struct sshcipher ciphers[] = { #ifdef WITH_OPENSSL #ifndef OPENSSL_NO_DES -@@ -409,7 +409,7 @@ cipher_get_length(struct sshcipher_ctx * +@@ -410,7 +391,7 @@ cipher_get_length(struct sshcipher_ctx * void cipher_free(struct sshcipher_ctx *cc) { - if (cc == NULL) + if (cc == NULL || cc->cipher == NULL) return; - if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) - explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); -diff -up openssh-7.6p1/cipher.h.audit openssh-7.6p1/cipher.h ---- openssh-7.6p1/cipher.h.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/cipher.h 2017-10-04 17:18:32.836505059 +0200 + if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { + chachapoly_free(cc->cp_ctx); +diff -up openssh/cipher.h.audit openssh/cipher.h +--- openssh/cipher.h.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/cipher.h 2019-04-03 17:02:20.714886050 +0200 @@ -45,7 +45,25 @@ #define CIPHER_ENCRYPT 1 #define CIPHER_DECRYPT 0 @@ -914,10 +915,10 @@ diff -up openssh-7.6p1/cipher.h.audit openssh-7.6p1/cipher.h struct sshcipher_ctx; const struct sshcipher *cipher_by_name(const char *); -diff -up openssh-7.6p1/kex.c.audit openssh-7.6p1/kex.c ---- openssh-7.6p1/kex.c.audit 2017-10-04 17:18:32.822504987 +0200 -+++ openssh-7.6p1/kex.c 2017-10-04 17:18:32.836505059 +0200 -@@ -54,6 +54,7 @@ +diff -up openssh/kex.c.audit openssh/kex.c +--- openssh/kex.c.audit 2019-04-03 17:02:20.652885462 +0200 ++++ openssh/kex.c 2019-04-03 17:02:20.715886060 +0200 +@@ -60,6 +60,7 @@ #include "ssherr.h" #include "sshbuf.h" #include "digest.h" @@ -925,64 +926,91 @@ diff -up openssh-7.6p1/kex.c.audit openssh-7.6p1/kex.c #ifdef GSSAPI #include "ssh-gss.h" -@@ -692,8 +693,12 @@ choose_enc(struct sshenc *enc, char *cli +@@ -758,12 +759,16 @@ kex_start_rekex(struct ssh *ssh) + } + + static int +-choose_enc(struct sshenc *enc, char *client, char *server) ++choose_enc(struct ssh *ssh, struct sshenc *enc, char *client, char *server) { char *name = match_list(client, server, NULL); - if (name == NULL) + if (name == NULL) { +#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(SSH_AUDIT_UNSUPPORTED_CIPHER); ++ audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_CIPHER); +#endif return SSH_ERR_NO_CIPHER_ALG_MATCH; + } if ((enc->cipher = cipher_by_name(name)) == NULL) { + error("%s: unsupported cipher %s", __func__, name); free(name); - return SSH_ERR_INTERNAL_ERROR; -@@ -713,8 +718,12 @@ choose_mac(struct ssh *ssh, struct sshma +@@ -783,8 +788,12 @@ choose_mac(struct ssh *ssh, struct sshma { char *name = match_list(client, server, NULL); - if (name == NULL) + if (name == NULL) { +#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(SSH_AUDIT_UNSUPPORTED_MAC); ++ audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_MAC); +#endif return SSH_ERR_NO_MAC_ALG_MATCH; + } if (mac_setup(mac, name) < 0) { + error("%s: unsupported MAC %s", __func__, name); free(name); - return SSH_ERR_INTERNAL_ERROR; -@@ -733,8 +742,12 @@ choose_comp(struct sshcomp *comp, char * +@@ -796,12 +805,16 @@ choose_mac(struct ssh *ssh, struct sshma + } + + static int +-choose_comp(struct sshcomp *comp, char *client, char *server) ++choose_comp(struct ssh *ssh, struct sshcomp *comp, char *client, char *server) { char *name = match_list(client, server, NULL); - if (name == NULL) + if (name == NULL) { +#ifdef SSH_AUDIT_EVENTS -+ audit_unsupported(SSH_AUDIT_UNSUPPORTED_COMPRESSION); ++ audit_unsupported(ssh, SSH_AUDIT_UNSUPPORTED_COMPRESSION); +#endif return SSH_ERR_NO_COMPRESS_ALG_MATCH; + } + #ifdef WITH_ZLIB if (strcmp(name, "zlib@openssh.com") == 0) { comp->type = COMP_DELAYED; - } else if (strcmp(name, "zlib") == 0) { -@@ -904,6 +917,10 @@ kex_choose_conf(struct ssh *ssh) +@@ -933,7 +946,7 @@ kex_choose_conf(struct ssh *ssh) + nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; + nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; + ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; +- if ((r = choose_enc(&newkeys->enc, cprop[nenc], ++ if ((r = choose_enc(ssh, &newkeys->enc, cprop[nenc], + sprop[nenc])) != 0) { + kex->failed_choice = peer[nenc]; + peer[nenc] = NULL; +@@ -948,7 +961,7 @@ kex_choose_conf(struct ssh *ssh) + peer[nmac] = NULL; + goto out; + } +- if ((r = choose_comp(&newkeys->comp, cprop[ncomp], ++ if ((r = choose_comp(ssh, &newkeys->comp, cprop[ncomp], + sprop[ncomp])) != 0) { + kex->failed_choice = peer[ncomp]; + peer[ncomp] = NULL; +@@ -971,6 +984,10 @@ kex_choose_conf(struct ssh *ssh) dh_need = MAXIMUM(dh_need, newkeys->enc.block_size); dh_need = MAXIMUM(dh_need, newkeys->enc.iv_len); dh_need = MAXIMUM(dh_need, newkeys->mac.key_len); + debug("kex: %s need=%d dh_need=%d", kex->name, need, dh_need); +#ifdef SSH_AUDIT_EVENTS -+ audit_kex(mode, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name, kex->name); ++ audit_kex(ssh, mode, newkeys->enc.name, newkeys->mac.name, newkeys->comp.name, kex->name); +#endif } /* XXX need runden? */ kex->we_need = need; -@@ -1037,3 +1054,33 @@ dump_digest(char *msg, u_char *digest, i - sshbuf_dump_data(digest, len, stderr); +@@ -1129,6 +1146,36 @@ dump_digest(const char *msg, const u_cha } #endif -+ + +static void +enc_destroy(struct sshenc *enc) +{ @@ -1012,22 +1040,26 @@ diff -up openssh-7.6p1/kex.c.audit openssh-7.6p1/kex.c + mac_destroy(&newkeys->mac); + memset(&newkeys->comp, 0, sizeof(newkeys->comp)); +} -diff -up openssh-7.6p1/kex.h.audit openssh-7.6p1/kex.h ---- openssh-7.6p1/kex.h.audit 2017-10-04 17:18:32.822504987 +0200 -+++ openssh-7.6p1/kex.h 2017-10-04 17:18:32.836505059 +0200 -@@ -219,6 +219,8 @@ int kexgss_client(struct ssh *); ++ + /* + * 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/kex.h.audit openssh/kex.h +--- openssh/kex.h.audit 2019-04-03 17:02:20.652885462 +0200 ++++ openssh/kex.h 2019-04-03 17:02:20.715886060 +0200 +@@ -226,6 +226,8 @@ int kexgss_client(struct ssh *); int kexgss_server(struct ssh *); #endif +void newkeys_destroy(struct newkeys *newkeys); + - int kex_dh_hash(int, const char *, const char *, - const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, - const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); -diff -up openssh-7.6p1/mac.c.audit openssh-7.6p1/mac.c ---- openssh-7.6p1/mac.c.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/mac.c 2017-10-04 17:18:32.836505059 +0200 -@@ -242,6 +242,20 @@ mac_clear(struct sshmac *mac) + int kex_dh_keypair(struct kex *); + int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, + struct sshbuf **); +diff -up openssh/mac.c.audit openssh/mac.c +--- openssh/mac.c.audit 2019-04-03 17:02:20.652885462 +0200 ++++ openssh/mac.c 2019-04-03 17:02:20.715886060 +0200 +@@ -243,6 +243,20 @@ mac_clear(struct sshmac *mac) mac->umac_ctx = NULL; } @@ -1048,9 +1080,9 @@ diff -up openssh-7.6p1/mac.c.audit openssh-7.6p1/mac.c /* XXX copied from ciphers_valid */ #define MAC_SEP "," int -diff -up openssh-7.6p1/mac.h.audit openssh-7.6p1/mac.h ---- openssh-7.6p1/mac.h.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/mac.h 2017-10-04 17:18:32.837505064 +0200 +diff -up openssh/mac.h.audit openssh/mac.h +--- openssh/mac.h.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/mac.h 2019-04-03 17:02:20.715886060 +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); @@ -1058,52 +1090,51 @@ diff -up openssh-7.6p1/mac.h.audit openssh-7.6p1/mac.h +void mac_destroy(struct sshmac *); #endif /* SSHMAC_H */ -diff -up openssh-7.6p1/Makefile.in.audit openssh-7.6p1/Makefile.in ---- openssh-7.6p1/Makefile.in.audit 2017-10-04 17:18:32.749504614 +0200 -+++ openssh-7.6p1/Makefile.in 2017-10-04 17:18:32.837505064 +0200 -@@ -100,7 +100,8 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ - kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ - kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ -- platform-pledge.o platform-tracing.o platform-misc.o -+ platform-pledge.o platform-tracing.o platform-misc.o \ -+ auditstub.o - - SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ - sshconnect.o sshconnect2.o mux.o -diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c ---- openssh-7.6p1/monitor.c.audit 2017-10-04 17:18:32.824504997 +0200 -+++ openssh-7.6p1/monitor.c 2017-10-04 17:18:32.837505064 +0200 -@@ -102,6 +102,7 @@ +diff -up openssh/Makefile.in.audit openssh/Makefile.in +--- openssh/Makefile.in.audit 2019-04-03 17:02:20.705885965 +0200 ++++ openssh/Makefile.in 2019-04-03 17:02:20.715886060 +0200 +@@ -109,7 +109,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ + kexgssc.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ +- sshbuf-io.o ++ sshbuf-io.o auditstub.o + + SKOBJS= ssh-sk-client.o + +diff -up openssh/monitor.c.audit openssh/monitor.c +--- openssh/monitor.c.audit 2019-04-03 17:02:20.674885671 +0200 ++++ openssh/monitor.c 2019-04-03 17:03:17.201421405 +0200 +@@ -93,6 +93,7 @@ #include "compat.h" #include "ssh2.h" #include "authfd.h" +#include "audit.h" #include "match.h" #include "ssherr.h" - -@@ -117,6 +118,8 @@ extern Buffer auth_debug; + #include "sk-api.h" +@@ -107,6 +108,8 @@ extern u_char session_id[]; extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; /* XXX move to permanent ssh->authctxt? */ -+extern void destroy_sensitive_data(int); ++extern void destroy_sensitive_data(struct ssh *, int); + /* State exported from the child */ static struct sshbuf *child_state; -@@ -167,6 +170,11 @@ int mm_answer_gss_updatecreds(int, Buffe +@@ -157,6 +160,11 @@ int mm_answer_gss_updatecreds(struct ssh #ifdef SSH_AUDIT_EVENTS - int mm_answer_audit_event(int, struct sshbuf *); - int mm_answer_audit_command(int, struct sshbuf *); -+int mm_answer_audit_end_command(int, struct sshbuf *); -+int mm_answer_audit_unsupported_body(int, struct sshbuf *); -+int mm_answer_audit_kex_body(int, struct sshbuf *); -+int mm_answer_audit_session_key_free_body(int, struct sshbuf *); -+int mm_answer_audit_server_key_free(int, struct sshbuf *); + int mm_answer_audit_event(struct ssh *, int, struct sshbuf *); + int mm_answer_audit_command(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_end_command(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_unsupported_body(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_kex_body(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_session_key_free_body(struct ssh *, int, struct sshbuf *); ++int mm_answer_audit_server_key_free(struct ssh *, int, struct sshbuf *); #endif - static int monitor_read_log(struct monitor *); -@@ -222,6 +230,10 @@ struct mon_table mon_dispatch_proto20[] + static Authctxt *authctxt; +@@ -215,6 +223,10 @@ struct mon_table mon_dispatch_proto20[] #endif #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, @@ -1114,7 +1145,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c #endif #ifdef BSD_AUTH {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery}, -@@ -260,6 +272,11 @@ struct mon_table mon_dispatch_postauth20 +@@ -249,6 +261,11 @@ struct mon_table mon_dispatch_postauth20 #ifdef SSH_AUDIT_EVENTS {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, @@ -1126,19 +1157,19 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c #endif {0, 0, NULL} }; -@@ -1396,8 +1413,10 @@ mm_answer_keyverify(int sock, struct ssh - char *sigalg; +@@ -1445,8 +1462,10 @@ mm_answer_keyverify(struct ssh *ssh, int size_t signaturelen, datalen, bloblen; - int r, ret, valid_data = 0, encoded_ret; + int r, ret, req_presence = 0, valid_data = 0, encoded_ret; + struct sshkey_sig_details *sig_details = NULL; + int type = 0; -- if ((r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || +- if ((r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || + if ((r = sshbuf_get_u32(m, &type)) != 0 || -+ (r = sshbuf_get_string(m, &blob, &bloblen)) != 0 || - (r = sshbuf_get_string(m, &signature, &signaturelen)) != 0 || - (r = sshbuf_get_string(m, &data, &datalen)) != 0 || ++ (r = sshbuf_get_string_direct(m, &blob, &bloblen)) != 0 || + (r = sshbuf_get_string_direct(m, &signature, &signaturelen)) != 0 || + (r = sshbuf_get_string_direct(m, &data, &datalen)) != 0 || (r = sshbuf_get_cstring(m, &sigalg, NULL)) != 0) -@@ -1405,6 +1424,8 @@ mm_answer_keyverify(int sock, struct ssh +@@ -1455,6 +1474,8 @@ mm_answer_keyverify(struct ssh *ssh, int if (hostbased_cuser == NULL || hostbased_chost == NULL || !monitor_allowed_key(blob, bloblen)) fatal("%s: bad key, not previously allowed", __func__); @@ -1147,19 +1178,19 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c /* Empty signature algorithm means NULL. */ if (*sigalg == '\0') { -@@ -1414,21 +1435,24 @@ mm_answer_keyverify(int sock, struct ssh +@@ -1470,25 +1491,28 @@ mm_answer_keyverify(struct ssh *ssh, int case MM_USERKEY: valid_data = monitor_valid_userblob(data, datalen); auth_method = "publickey"; -+ ret = user_key_verify(key, signature, signaturelen, data, -+ datalen, sigalg, active_state->compat); ++ ret = user_key_verify(ssh, key, signature, signaturelen, data, ++ datalen, sigalg, ssh->compat, &sig_details); break; case MM_HOSTKEY: valid_data = monitor_valid_hostbasedblob(data, datalen, hostbased_cuser, hostbased_chost); -+ ret = hostbased_key_verify(key, signature, signaturelen, data, -+ datalen, sigalg, active_state->compat); auth_method = "hostbased"; ++ ret = hostbased_key_verify(ssh, key, signature, signaturelen, data, ++ datalen, sigalg, ssh->compat, &sig_details); break; default: valid_data = 0; @@ -1169,34 +1200,64 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c if (!valid_data) fatal("%s: bad signature data blob", __func__); + if ((fp = sshkey_fingerprint(key, options.fingerprint_hash, + SSH_FP_DEFAULT)) == NULL) + fatal("%s: sshkey_fingerprint failed", __func__); + - ret = sshkey_verify(key, signature, signaturelen, data, datalen, -- sigalg, active_state->compat); - debug3("%s: %s %p signature %s", __func__, auth_method, key, - (ret == 0) ? "verified" : "unverified"); - auth2_record_key(authctxt, ret == 0, key); -@@ -1485,6 +1509,12 @@ mm_session_close(Session *s) +- sigalg, ssh->compat, &sig_details); + debug3("%s: %s %p signature %s%s%s", __func__, auth_method, key, + (ret == 0) ? "verified" : "unverified", + (ret != 0) ? ": " : "", (ret != 0) ? ssh_err(ret) : ""); +@@ -1536,13 +1560,19 @@ mm_record_login(struct ssh *ssh, Session + } + + static void +-mm_session_close(Session *s) ++mm_session_close(struct ssh *ssh, Session *s) + { + debug3("%s: session %d pid %ld", __func__, s->self, (long)s->pid); + if (s->ttyfd != -1) { debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ptyfd); session_pty_cleanup2(s); } +#ifdef SSH_AUDIT_EVENTS + if (s->command != NULL) { + debug3("%s: command %d", __func__, s->command_handle); -+ session_end_command2(s); ++ session_end_command2(ssh, s); + } +#endif session_unused(s->self); } -@@ -1588,6 +1618,8 @@ mm_answer_term(int sock, Buffer *req) +@@ -1609,7 +1639,7 @@ mm_answer_pty(struct ssh *ssh, int sock, + + error: + if (s != NULL) +- mm_session_close(s); ++ mm_session_close(ssh, s); + if ((r = sshbuf_put_u32(m, 0)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + mm_request_send(sock, MONITOR_ANS_PTY, m); +@@ -1628,7 +1658,7 @@ mm_answer_pty_cleanup(struct ssh *ssh, i + if ((r = sshbuf_get_cstring(m, &tty, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + if ((s = session_by_tty(tty)) != NULL) +- mm_session_close(s); ++ mm_session_close(ssh, s); + sshbuf_reset(m); + free(tty); + return (0); +@@ -1650,6 +1680,8 @@ mm_answer_term(struct ssh *ssh, int sock sshpam_cleanup(); #endif -+ destroy_sensitive_data(0); ++ destroy_sensitive_data(ssh, 0); + while (waitpid(pmonitor->m_pid, &status, 0) == -1) if (errno != EINTR) exit(1); -@@ -1630,12 +1662,47 @@ mm_answer_audit_command(int socket, Buff +@@ -1696,12 +1728,47 @@ mm_answer_audit_command(struct ssh *ssh, { char *cmd; int r; @@ -1213,7 +1274,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c + fatal("%s: error allocating a session", __func__); + s->command = cmd; +#ifdef SSH_AUDIT_EVENTS -+ s->command_handle = audit_run_command(cmd); ++ s->command_handle = audit_run_command(ssh, cmd); +#endif + + sshbuf_reset(m); @@ -1225,7 +1286,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c +} + +int -+mm_answer_audit_end_command(int socket, struct sshbuf *m) ++mm_answer_audit_end_command(struct ssh *ssh, int socket, struct sshbuf *m) +{ + int handle, r; + size_t len; @@ -1241,19 +1302,19 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c + if (s == NULL || s->ttyfd != -1 || s->command == NULL || + strcmp(s->command, cmd) != 0) + fatal("%s: invalid handle", __func__); -+ mm_session_close(s); ++ mm_session_close(ssh, s); free(cmd); return (0); } -@@ -1702,6 +1768,7 @@ monitor_apply_keystate(struct monitor *p +@@ -1767,6 +1834,7 @@ monitor_apply_keystate(struct ssh *ssh, void - mm_get_keystate(struct monitor *pmonitor) + mm_get_keystate(struct ssh *ssh, struct monitor *pmonitor) { + struct sshbuf *m; debug3("%s: Waiting for new keys", __func__); if ((child_state = sshbuf_new()) == NULL) -@@ -1709,6 +1776,19 @@ mm_get_keystate(struct monitor *pmonitor +@@ -1774,6 +1842,19 @@ mm_get_keystate(struct ssh *ssh, struct mm_request_receive_expect(pmonitor->m_sendfd, MONITOR_REQ_KEYEXPORT, child_state); debug3("%s: GOT new keys", __func__); @@ -1262,7 +1323,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c + m = sshbuf_new(); + mm_request_receive_expect(pmonitor->m_sendfd, + MONITOR_REQ_AUDIT_SESSION_KEY_FREE, m); -+ mm_answer_audit_session_key_free_body(pmonitor->m_sendfd, m); ++ mm_answer_audit_session_key_free_body(ssh, pmonitor->m_sendfd, m); + sshbuf_free(m); +#endif + @@ -1273,20 +1334,20 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c } -@@ -1976,3 +2056,102 @@ mm_answer_gss_updatecreds(int socket, Bu +@@ -2066,3 +2147,102 @@ mm_answer_gss_updatecreds(struct ssh *ss #endif /* GSSAPI */ +#ifdef SSH_AUDIT_EVENTS +int -+mm_answer_audit_unsupported_body(int sock, struct sshbuf *m) ++mm_answer_audit_unsupported_body(struct ssh *ssh, int sock, struct sshbuf *m) +{ + int what, r; + + if ((r = sshbuf_get_u32(m, &what)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + -+ audit_unsupported_body(what); ++ audit_unsupported_body(ssh, what); + + sshbuf_reset(m); + @@ -1295,7 +1356,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c +} + +int -+mm_answer_audit_kex_body(int sock, struct sshbuf *m) ++mm_answer_audit_kex_body(struct ssh *ssh, int sock, struct sshbuf *m) +{ + int ctos, r; + char *cipher, *mac, *compress, *pfs; @@ -1315,7 +1376,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + uid = (pid_t) tmp; + -+ audit_kex_body(ctos, cipher, mac, compress, pfs, pid, uid); ++ audit_kex_body(ssh, ctos, cipher, mac, compress, pfs, pid, uid); + + free(cipher); + free(mac); @@ -1328,7 +1389,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c +} + +int -+mm_answer_audit_session_key_free_body(int sock, struct sshbuf *m) ++mm_answer_audit_session_key_free_body(struct ssh *ssh, int sock, struct sshbuf *m) +{ + int ctos, r; + u_int64_t tmp; @@ -1343,7 +1404,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + uid = (uid_t) tmp; + -+ audit_session_key_free_body(ctos, pid, uid); ++ audit_session_key_free_body(ssh, ctos, pid, uid); + + sshbuf_reset(m); + @@ -1352,7 +1413,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c +} + +int -+mm_answer_audit_server_key_free(int sock, struct sshbuf *m) ++mm_answer_audit_server_key_free(struct ssh *ssh, int sock, struct sshbuf *m) +{ + size_t len, r; + char *fp; @@ -1368,7 +1429,7 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + uid = (uid_t) tmp; + -+ audit_destroy_sensitive_data(fp, pid, uid); ++ audit_destroy_sensitive_data(ssh, fp, pid, uid); + + free(fp); + sshbuf_reset(m); @@ -1376,10 +1437,10 @@ diff -up openssh-7.6p1/monitor.c.audit openssh-7.6p1/monitor.c + return 0; +} +#endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-7.6p1/monitor.h.audit openssh-7.6p1/monitor.h ---- openssh-7.6p1/monitor.h.audit 2017-10-04 17:18:32.781504777 +0200 -+++ openssh-7.6p1/monitor.h 2017-10-04 17:18:32.837505064 +0200 -@@ -69,7 +69,13 @@ enum monitor_reqtype { +diff -up openssh/monitor.h.audit openssh/monitor.h +--- openssh/monitor.h.audit 2019-04-03 17:02:20.674885671 +0200 ++++ openssh/monitor.h 2019-04-03 17:02:20.715886060 +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, MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, @@ -1390,24 +1451,24 @@ diff -up openssh-7.6p1/monitor.h.audit openssh-7.6p1/monitor.h + MONITOR_REQ_AUDIT_UNSUPPORTED = 118, MONITOR_ANS_AUDIT_UNSUPPORTED = 119, + MONITOR_REQ_AUDIT_KEX = 120, MONITOR_ANS_AUDIT_KEX = 121, + MONITOR_REQ_AUDIT_SESSION_KEY_FREE = 122, MONITOR_ANS_AUDIT_SESSION_KEY_FREE = 123, -+ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124 - - }; - -diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c ---- openssh-7.6p1/monitor_wrap.c.audit 2017-10-04 17:18:32.750504619 +0200 -+++ openssh-7.6p1/monitor_wrap.c 2017-10-04 17:18:32.838505069 +0200 -@@ -463,7 +463,7 @@ mm_key_allowed(enum mm_keytype type, con ++ MONITOR_REQ_AUDIT_SERVER_KEY_FREE = 124, + + MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, + MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, +diff -up openssh/monitor_wrap.c.audit openssh/monitor_wrap.c +--- openssh/monitor_wrap.c.audit 2019-04-03 17:02:20.653885472 +0200 ++++ openssh/monitor_wrap.c 2019-04-03 17:02:20.716886069 +0200 +@@ -513,7 +513,7 @@ mm_key_allowed(enum mm_keytype type, con */ int -mm_sshkey_verify(const struct sshkey *key, const u_char *sig, size_t siglen, +mm_sshkey_verify(enum mm_keytype type, const struct sshkey *key, const u_char *sig, size_t siglen, - const u_char *data, size_t datalen, const char *sigalg, u_int compat) + const u_char *data, size_t datalen, const char *sigalg, u_int compat, + struct sshkey_sig_details **sig_detailsp) { - struct sshbuf *m; -@@ -478,7 +478,8 @@ mm_sshkey_verify(const struct sshkey *ke - +@@ -525,7 +525,8 @@ mm_sshkey_verify(const struct sshkey *ke + *sig_detailsp = NULL; if ((m = sshbuf_new()) == NULL) fatal("%s: sshbuf_new failed", __func__); - if ((r = sshkey_puts(key, m)) != 0 || @@ -1416,34 +1477,37 @@ diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c (r = sshbuf_put_string(m, sig, siglen)) != 0 || (r = sshbuf_put_string(m, data, datalen)) != 0 || (r = sshbuf_put_cstring(m, sigalg == NULL ? "" : sigalg)) != 0) -@@ -497,6 +498,20 @@ mm_sshkey_verify(const struct sshkey *ke +@@ -547,6 +548,22 @@ mm_sshkey_verify(const struct sshkey *ke return 0; } +int -+mm_hostbased_key_verify(const struct sshkey *key, const u_char *sig, size_t siglen, -+ const u_char *data, size_t datalen, const char *pkalg, u_int compat) ++mm_hostbased_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, size_t siglen, ++ const u_char *data, size_t datalen, const char *pkalg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ -+ return mm_sshkey_verify(MM_HOSTKEY, key, sig, siglen, data, datalen, pkalg, compat); ++ return mm_sshkey_verify(MM_HOSTKEY, key, sig, siglen, data, datalen, pkalg, compat, detailsp); +} + +int -+mm_user_key_verify(const struct sshkey *key, const u_char *sig, size_t siglen, -+ const u_char *data, size_t datalen, const char *pkalg, u_int compat) ++mm_user_key_verify(struct ssh *ssh, const struct sshkey *key, const u_char *sig, size_t siglen, ++ const u_char *data, size_t datalen, const char *pkalg, u_int compat, ++ struct sshkey_sig_details **detailsp) +{ -+ return mm_sshkey_verify(MM_USERKEY, key, sig, siglen, data, datalen, pkalg, compat); ++ return mm_sshkey_verify(MM_USERKEY, key, sig, siglen, data, datalen, pkalg, compat, detailsp); +} + void - mm_send_keystate(struct monitor *monitor) + mm_send_keystate(struct ssh *ssh, struct monitor *monitor) { -@@ -874,11 +889,12 @@ mm_audit_event(ssh_audit_event_t event) +@@ -900,11 +915,12 @@ mm_audit_event(struct ssh *ssh, ssh_audi sshbuf_free(m); } -void +-mm_audit_run_command(const char *command) +int - mm_audit_run_command(const char *command) ++mm_audit_run_command(struct ssh *ssh, const char *command) { struct sshbuf *m; int r; @@ -1451,7 +1515,7 @@ diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c debug3("%s entering command %s", __func__, command); -@@ -885,6 +901,30 @@ mm_audit_run_command(const char *command +@@ -914,6 +930,30 @@ mm_audit_run_command(const char *command fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUDIT_COMMAND, m); @@ -1465,7 +1529,7 @@ diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c +} + +void -+mm_audit_end_command(int handle, const char *command) ++mm_audit_end_command(struct ssh *ssh, int handle, const char *command) +{ + int r; + struct sshbuf *m; @@ -1482,13 +1546,13 @@ diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c sshbuf_free(m); } #endif /* SSH_AUDIT_EVENTS */ -@@ -1020,3 +1056,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc - return (ok); +@@ -1074,3 +1114,83 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_cc } + #endif /* GSSAPI */ +#ifdef SSH_AUDIT_EVENTS +void -+mm_audit_unsupported_body(int what) ++mm_audit_unsupported_body(struct ssh *ssh, int what) +{ + int r; + struct sshbuf *m; @@ -1506,7 +1570,7 @@ diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c +} + +void -+mm_audit_kex_body(int ctos, char *cipher, char *mac, char *compress, char *fps, pid_t pid, ++mm_audit_kex_body(struct ssh *ssh, int ctos, char *cipher, char *mac, char *compress, char *fps, pid_t pid, + uid_t uid) +{ + int r; @@ -1531,7 +1595,7 @@ diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c +} + +void -+mm_audit_session_key_free_body(int ctos, pid_t pid, uid_t uid) ++mm_audit_session_key_free_body(struct ssh *ssh, int ctos, pid_t pid, uid_t uid) +{ + int r; + struct sshbuf *m; @@ -1550,7 +1614,7 @@ diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c +} + +void -+mm_audit_destroy_sensitive_data(const char *fp, pid_t pid, uid_t uid) ++mm_audit_destroy_sensitive_data(struct ssh *ssh, const char *fp, pid_t pid, uid_t uid) +{ + int r; + struct sshbuf *m; @@ -1566,46 +1630,46 @@ diff -up openssh-7.6p1/monitor_wrap.c.audit openssh-7.6p1/monitor_wrap.c + sshbuf_free(m); +} +#endif /* SSH_AUDIT_EVENTS */ -diff -up openssh-7.6p1/monitor_wrap.h.audit openssh-7.6p1/monitor_wrap.h ---- openssh-7.6p1/monitor_wrap.h.audit 2017-10-04 17:18:32.750504619 +0200 -+++ openssh-7.6p1/monitor_wrap.h 2017-10-04 17:18:32.838505069 +0200 -@@ -53,7 +53,9 @@ int mm_key_allowed(enum mm_keytype, cons +diff -up openssh/monitor_wrap.h.audit openssh/monitor_wrap.h +--- openssh/monitor_wrap.h.audit 2019-04-03 17:02:20.653885472 +0200 ++++ openssh/monitor_wrap.h 2019-04-03 17:02:20.716886069 +0200 +@@ -57,7 +57,9 @@ int mm_user_key_allowed(struct ssh *, st struct sshauthopt **); - int mm_hostbased_key_allowed(struct passwd *, const char *, + int mm_hostbased_key_allowed(struct ssh *, struct passwd *, const char *, const char *, struct sshkey *); -int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, -+int mm_hostbased_key_verify(const struct sshkey *, const u_char *, size_t, -+ const u_char *, size_t, const char *, u_int); -+int mm_user_key_verify(const struct sshkey *, const u_char *, size_t, - const u_char *, size_t, const char *, u_int); ++int mm_hostbased_key_verify(struct ssh *, const struct sshkey *, const u_char *, size_t, ++ const u_char *, size_t, const char *, u_int, struct sshkey_sig_details **); ++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 -@@ -78,7 +80,12 @@ void mm_sshpam_free_ctx(void *); +@@ -82,7 +84,12 @@ void mm_sshpam_free_ctx(void *); #ifdef SSH_AUDIT_EVENTS #include "audit.h" - void mm_audit_event(ssh_audit_event_t); + void mm_audit_event(struct ssh *, ssh_audit_event_t); -void mm_audit_run_command(const char *); -+int mm_audit_run_command(const char *); -+void mm_audit_end_command(int, const char *); -+void mm_audit_unsupported_body(int); -+void mm_audit_kex_body(int, char *, char *, char *, char *, pid_t, uid_t); -+void mm_audit_session_key_free_body(int, pid_t, uid_t); -+void mm_audit_destroy_sensitive_data(const char *, pid_t, uid_t); ++int mm_audit_run_command(struct ssh *ssh, const char *); ++void mm_audit_end_command(struct ssh *ssh, int, const char *); ++void mm_audit_unsupported_body(struct ssh *, int); ++void mm_audit_kex_body(struct ssh *, int, char *, char *, char *, char *, pid_t, uid_t); ++void mm_audit_session_key_free_body(struct ssh *, int, pid_t, uid_t); ++void mm_audit_destroy_sensitive_data(struct ssh *, const char *, pid_t, uid_t); #endif struct Session; -diff -up openssh-7.6p1/packet.c.audit openssh-7.6p1/packet.c ---- openssh-7.6p1/packet.c.audit 2017-10-04 17:18:32.672504220 +0200 -+++ openssh-7.6p1/packet.c 2017-10-04 17:25:48.141741390 +0200 -@@ -67,6 +67,7 @@ - #include +diff -up openssh/packet.c.audit openssh/packet.c +--- openssh/packet.c.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/packet.c 2019-04-03 17:02:20.716886069 +0200 +@@ -77,6 +77,7 @@ + #endif #include "xmalloc.h" +#include "audit.h" - #include "crc32.h" #include "compat.h" #include "ssh2.h" -@@ -502,6 +503,13 @@ ssh_packet_get_connection_out(struct ssh + #include "cipher.h" +@@ -510,6 +511,13 @@ ssh_packet_get_connection_out(struct ssh return ssh->state->connection_out; } @@ -1619,7 +1683,7 @@ diff -up openssh-7.6p1/packet.c.audit openssh-7.6p1/packet.c /* * Returns the IP-address of the remote host as a string. The returned * string must not be freed. -@@ -566,22 +574,19 @@ ssh_packet_close_internal(struct ssh *ss +@@ -587,22 +595,19 @@ ssh_packet_close_internal(struct ssh *ss { struct session_state *state = ssh->state; u_int mode; @@ -1642,18 +1706,18 @@ diff -up openssh-7.6p1/packet.c.audit openssh-7.6p1/packet.c + state->output = NULL; sshbuf_free(state->outgoing_packet); + state->outgoing_packet = NULL; - sshbuf_free(state->incoming_packet); + sshbuf_free(state->incoming_packet); + state->incoming_packet = NULL; for (mode = 0; mode < MODE_MAX; mode++) { kex_free_newkeys(state->newkeys[mode]); /* current keys */ state->newkeys[mode] = NULL; -@@ -615,8 +616,18 @@ ssh_packet_close_internal(struct ssh *ss - } +@@ -636,8 +641,18 @@ ssh_packet_close_internal(struct ssh *ss + #endif /* WITH_ZLIB */ cipher_free(state->send_context); cipher_free(state->receive_context); + if (had_keys && state->server_side) { + /* Assuming this is called only from privsep child */ -+ audit_session_key_free(MODE_MAX); ++ audit_session_key_free(ssh, MODE_MAX); + } state->send_context = state->receive_context = NULL; if (do_close) { @@ -1666,15 +1730,15 @@ diff -up openssh-7.6p1/packet.c.audit openssh-7.6p1/packet.c free(ssh->local_ipaddr); ssh->local_ipaddr = NULL; free(ssh->remote_ipaddr); -@@ -854,6 +863,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod - (unsigned long long)state->p_read.blocks, +@@ -864,6 +879,7 @@ ssh_set_newkeys(struct ssh *ssh, int mod (unsigned long long)state->p_send.bytes, (unsigned long long)state->p_send.blocks); -+ audit_session_key_free(mode); - cipher_free(*ccp); - *ccp = NULL; kex_free_newkeys(state->newkeys[mode]); -@@ -2135,6 +2145,72 @@ ssh_packet_get_output(struct ssh *ssh) ++ audit_session_key_free(ssh, mode); + state->newkeys[mode] = NULL; + } + /* note that both bytes and the seqnr are not reset */ +@@ -2167,6 +2183,72 @@ ssh_packet_get_output(struct ssh *ssh) return (void *)ssh->state->output; } @@ -1705,6 +1769,7 @@ diff -up openssh-7.6p1/packet.c.audit openssh-7.6p1/packet.c + + cipher_free(state->receive_context); + cipher_free(state->send_context); ++ state->send_context = state->receive_context = NULL; + + sshbuf_free(state->input); + state->input = NULL; @@ -1728,18 +1793,17 @@ diff -up openssh-7.6p1/packet.c.audit openssh-7.6p1/packet.c +} + +void -+packet_destroy_all(int audit_it, int privsep) ++packet_destroy_all(struct ssh *ssh, int audit_it, int privsep) +{ + if (audit_it) -+ audit_it = (active_state != NULL && packet_state_has_keys(active_state->state)); -+ if (active_state != NULL) -+ packet_destroy_state(active_state->state); ++ audit_it = packet_state_has_keys(ssh->state); ++ packet_destroy_state(ssh->state); + if (audit_it) { +#ifdef SSH_AUDIT_EVENTS + if (privsep) -+ audit_session_key_free(MODE_MAX); ++ audit_session_key_free(ssh, MODE_MAX); + else -+ audit_session_key_free_body(MODE_MAX, getpid(), getuid()); ++ audit_session_key_free_body(ssh, MODE_MAX, getpid(), getuid()); +#endif + } +} @@ -1747,28 +1811,28 @@ diff -up openssh-7.6p1/packet.c.audit openssh-7.6p1/packet.c /* Reset after_authentication and reset compression in post-auth privsep */ static int ssh_packet_set_postauth(struct ssh *ssh) -diff -up openssh-7.6p1/packet.h.audit openssh-7.6p1/packet.h ---- openssh-7.6p1/packet.h.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/packet.h 2017-10-04 17:18:32.838505069 +0200 -@@ -217,4 +217,5 @@ extern struct ssh *active_state; +diff -up openssh/packet.h.audit openssh/packet.h +--- openssh/packet.h.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/packet.h 2019-04-03 17:02:20.716886069 +0200 +@@ -217,4 +217,5 @@ const u_char *sshpkt_ptr(struct ssh *, s # undef EC_POINT #endif -+void packet_destroy_all(int, int); ++void packet_destroy_all(struct ssh *, int, int); #endif /* PACKET_H */ -diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c ---- openssh-7.6p1/session.c.audit 2017-10-04 17:18:32.812504936 +0200 -+++ openssh-7.6p1/session.c 2017-10-04 17:18:32.839505074 +0200 -@@ -138,7 +138,7 @@ extern char *__progname; +diff -up openssh/session.c.audit openssh/session.c +--- openssh/session.c.audit 2019-04-03 17:02:20.712886031 +0200 ++++ openssh/session.c 2019-04-03 17:02:20.716886069 +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(int); ++extern void destroy_sensitive_data(struct ssh *, int); extern struct sshbuf *loginmsg; extern struct sshauthopt *auth_opts; - char *tun_fwd_ifnames; /* serverloop.c */ -@@ -605,6 +605,14 @@ do_exec_pty(struct ssh *ssh, Session *s, + extern char *tun_fwd_ifnames; /* serverloop.c */ +@@ -648,6 +648,14 @@ do_exec_pty(struct ssh *ssh, Session *s, /* Parent. Close the slave side of the pseudo tty. */ close(ttyfd); @@ -1782,8 +1846,8 @@ diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c + /* Enter interactive session. */ s->ptymaster = ptymaster; - packet_set_interactive(1, -@@ -724,15 +732,19 @@ do_exec(struct ssh *ssh, Session *s, con + ssh_packet_set_interactive(ssh, 1, +@@ -740,15 +748,19 @@ do_exec(struct ssh *ssh, Session *s, con s->self); #ifdef SSH_AUDIT_EVENTS @@ -1801,24 +1865,24 @@ diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c + s->command = xstrdup(shell); } + if (s->command != NULL && s->ptyfd == -1) -+ s->command_handle = PRIVSEP(audit_run_command(s->command)); ++ s->command_handle = PRIVSEP(audit_run_command(ssh, s->command)); #endif if (s->ttyfd != -1) ret = do_exec_pty(ssh, s, command); -@@ -1499,8 +1511,11 @@ do_child(struct ssh *ssh, Session *s, co - int r = 0; +@@ -1556,8 +1568,11 @@ do_child(struct ssh *ssh, Session *s, co + sshpkt_fmt_connection_id(ssh, remote_id, sizeof(remote_id)); /* remove hostkey from the child's memory */ - destroy_sensitive_data(); -+ destroy_sensitive_data(1); - packet_clear_keys(); ++ destroy_sensitive_data(ssh, 1); + 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. */ -+ packet_destroy_all(0, 1); ++ packet_destroy_all(ssh, 0, 1); /* Force a password change */ if (s->authctxt->force_pwchange) { -@@ -1714,6 +1729,9 @@ session_unused(int id) +@@ -1769,6 +1784,9 @@ session_unused(int id) sessions[id].ttyfd = -1; sessions[id].ptymaster = -1; sessions[id].x11_chanids = NULL; @@ -1828,7 +1892,7 @@ diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c sessions[id].next_unused = sessions_first_unused; sessions_first_unused = id; } -@@ -1796,6 +1814,19 @@ session_open(Authctxt *authctxt, int cha +@@ -1851,6 +1869,19 @@ session_open(Authctxt *authctxt, int cha } Session * @@ -1848,17 +1912,17 @@ diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c session_by_tty(char *tty) { int i; -@@ -2307,6 +2338,32 @@ session_exit_message(struct ssh *ssh, Se +@@ -2461,6 +2492,32 @@ session_exit_message(struct ssh *ssh, Se chan_write_failed(ssh, c); } +#ifdef SSH_AUDIT_EVENTS +void -+session_end_command2(Session *s) ++session_end_command2(struct ssh *ssh, Session *s) +{ + if (s->command != NULL) { + if (s->command_handle != -1) -+ audit_end_command(s->command_handle, s->command); ++ audit_end_command(ssh, s->command_handle, s->command); + free(s->command); + s->command = NULL; + s->command_handle = -1; @@ -1866,11 +1930,11 @@ diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c +} + +static void -+session_end_command(Session *s) ++session_end_command(struct ssh *ssh, Session *s) +{ + if (s->command != NULL) { + if (s->command_handle != -1) -+ PRIVSEP(audit_end_command(s->command_handle, s->command)); ++ PRIVSEP(audit_end_command(ssh, s->command_handle, s->command)); + free(s->command); + s->command = NULL; + s->command_handle = -1; @@ -1881,34 +1945,51 @@ diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c void session_close(struct ssh *ssh, Session *s) { -@@ -2320,6 +2377,10 @@ session_close(struct ssh *ssh, Session * +@@ -2474,6 +2531,10 @@ session_close(struct ssh *ssh, Session * if (s->ttyfd != -1) session_pty_cleanup(s); +#ifdef SSH_AUDIT_EVENTS + if (s->command) -+ session_end_command(s); ++ session_end_command(ssh, s); +#endif free(s->term); free(s->display); free(s->x11_chanids); -@@ -2528,6 +2589,15 @@ do_authenticated2(struct ssh *ssh, Authc +@@ -2549,14 +2610,14 @@ session_close_by_channel(struct ssh *ssh + } + + void +-session_destroy_all(struct ssh *ssh, void (*closefunc)(Session *)) ++session_destroy_all(struct ssh *ssh, void (*closefunc)(struct ssh *ssh, Session *)) + { + int i; + for (i = 0; i < sessions_nalloc; i++) { + Session *s = &sessions[i]; + if (s->used) { + if (closefunc != NULL) +- closefunc(s); ++ closefunc(ssh, s); + else + session_close(ssh, s); + } +@@ -2683,6 +2744,15 @@ do_authenticated2(struct ssh *ssh, Authc server_loop2(ssh, authctxt); } +static void -+do_cleanup_one_session(Session *s) ++do_cleanup_one_session(struct ssh *ssh, Session *s) +{ + session_pty_cleanup2(s); +#ifdef SSH_AUDIT_EVENTS -+ session_end_command2(s); ++ session_end_command2(ssh, s); +#endif +} + void do_cleanup(struct ssh *ssh, Authctxt *authctxt) { -@@ -2585,7 +2655,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au +@@ -2746,7 +2816,7 @@ do_cleanup(struct ssh *ssh, Authctxt *au * or if running in monitor. */ if (!use_privsep || mm_is_monitor()) @@ -1917,10 +1998,10 @@ diff -up openssh-7.6p1/session.c.audit openssh-7.6p1/session.c } /* Return a name for the remote host that fits inside utmp_size */ -diff -up openssh-7.6p1/session.h.audit openssh-7.6p1/session.h ---- openssh-7.6p1/session.h.audit 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/session.h 2017-10-04 17:18:32.839505074 +0200 -@@ -60,6 +60,12 @@ struct Session { +diff -up openssh/session.h.audit openssh/session.h +--- openssh/session.h.audit 2019-03-27 23:26:14.000000000 +0100 ++++ openssh/session.h 2019-04-03 17:02:20.717886079 +0200 +@@ -61,6 +61,12 @@ struct Session { char *name; char *val; } *env; @@ -1933,20 +2014,23 @@ diff -up openssh-7.6p1/session.h.audit openssh-7.6p1/session.h }; void do_authenticated(struct ssh *, Authctxt *); -@@ -72,8 +78,10 @@ void session_close_by_pid(struct ssh *s +@@ -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_destroy_all(struct ssh *, void (*)(Session *)); +-void session_destroy_all(struct ssh *, void (*)(Session *)); ++void session_destroy_all(struct ssh *, void (*)(struct ssh*, Session *)); void session_pty_cleanup2(Session *); -+void session_end_command2(Session *); ++void session_end_command2(struct ssh *ssh, Session *); Session *session_new(void); +Session *session_by_id(int); Session *session_by_tty(char *); void session_close(struct ssh *, Session *); void do_setusercontext(struct passwd *); -diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c ---- openssh-7.6p1/sshd.c.audit 2017-10-04 17:18:32.830505028 +0200 -+++ openssh-7.6p1/sshd.c 2017-10-04 17:18:32.839505074 +0200 +diff -up openssh/sshd.c.audit openssh/sshd.c +--- openssh/sshd.c.audit 2019-04-03 17:02:20.692885842 +0200 ++++ openssh/sshd.c 2019-04-03 17:02:20.717886079 +0200 @@ -122,6 +122,7 @@ #include "ssh-gss.h" #endif @@ -1955,16 +2039,18 @@ diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c #include "ssh-sandbox.h" #include "auth-options.h" #include "version.h" -@@ -248,7 +249,7 @@ Buffer loginmsg; +@@ -261,8 +262,8 @@ struct sshbuf *loginmsg; struct passwd *privsep_pw = NULL; /* Prototypes for various functions defined later in this file. */ -void destroy_sensitive_data(void); -+void destroy_sensitive_data(int); - void demote_sensitive_data(void); - static void do_ssh2_kex(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 *); -@@ -265,6 +266,15 @@ close_listen_socks(void) + static char *listener_proctitle; +@@ -278,6 +279,15 @@ close_listen_socks(void) num_listen_socks = -1; } @@ -1980,8 +2066,8 @@ diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c static void close_startup_pipes(void) { -@@ -475,18 +485,45 @@ sshd_exchange_identification(struct ssh - } +@@ -380,18 +390,45 @@ grace_alarm_handler(int sig) + ssh_remote_port(the_active_state)); } -/* Destroy the host and server keys. They will no longer be needed. */ @@ -1991,7 +2077,7 @@ diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c + */ void -destroy_sensitive_data(void) -+destroy_sensitive_data(int privsep) ++destroy_sensitive_data(struct ssh *ssh, int privsep) { u_int i; +#ifdef SSH_AUDIT_EVENTS @@ -2014,10 +2100,10 @@ diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c + if (fp != NULL) { +#ifdef SSH_AUDIT_EVENTS + if (privsep) -+ PRIVSEP(audit_destroy_sensitive_data(fp, ++ PRIVSEP(audit_destroy_sensitive_data(ssh, fp, + pid, uid)); + else -+ audit_destroy_sensitive_data(fp, ++ audit_destroy_sensitive_data(ssh, fp, + pid, uid); +#endif + free(fp); @@ -2029,7 +2115,13 @@ diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c sshkey_free(sensitive_data.host_certificates[i]); sensitive_data.host_certificates[i] = NULL; } -@@ -499,16 +536,34 @@ demote_sensitive_data(void) +@@ -400,14 +437,26 @@ destroy_sensitive_data(void) + + /* Demote private to public keys for network child */ + void +-demote_sensitive_data(void) ++demote_sensitive_data(struct ssh *ssh) + { struct sshkey *tmp; u_int i; int r; @@ -2048,23 +2140,41 @@ diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c + fp = sshkey_fingerprint(sensitive_data.host_keys[i], options.fingerprint_hash, SSH_FP_HEX); + else + fp = NULL; - if ((r = sshkey_demote(sensitive_data.host_keys[i], - &tmp)) != 0) - fatal("could not demote host %s key: %s", - sshkey_type(sensitive_data.host_keys[i]), - ssh_err(r)); - sshkey_free(sensitive_data.host_keys[i]); + if ((r = sshkey_from_private( + sensitive_data.host_keys[i], &tmp)) != 0) + fatal("could not demote host %s key: %s", +@@ -415,6 +464,12 @@ demote_sensitive_data(void) + ssh_err(r)); + sshkey_free(sensitive_data.host_keys[i]); sensitive_data.host_keys[i] = tmp; + if (fp != NULL) { +#ifdef SSH_AUDIT_EVENTS -+ audit_destroy_sensitive_data(fp, pid, uid); ++ audit_destroy_sensitive_data(ssh, fp, pid, uid); +#endif + free(fp); + } } /* Certs do not need demotion */ } -@@ -587,7 +642,7 @@ privsep_preauth(Authctxt *authctxt) +@@ -442,7 +497,7 @@ reseed_prngs(void) + } + + static void +-privsep_preauth_child(void) ++privsep_preauth_child(struct ssh *ssh) + { + gid_t gidset[1]; + +@@ -457,7 +512,7 @@ privsep_preauth_child(void) + reseed_prngs(); + + /* Demote the private keys to public keys. */ +- demote_sensitive_data(); ++ demote_sensitive_data(ssh); + + #ifdef WITH_SELINUX + sshd_selinux_change_privsep_preauth_context(); +@@ -496,7 +551,7 @@ privsep_preauth(struct ssh *ssh) if (use_privsep == PRIVSEP_ON) box = ssh_sandbox_init(pmonitor); @@ -2073,28 +2183,64 @@ diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c if (pid == -1) { fatal("fork of unprivileged child failed"); } else if (pid != 0) { -@@ -1162,6 +1217,7 @@ server_accept_loop(int *sock_in, int *so +@@ -542,7 +597,7 @@ privsep_preauth(struct ssh *ssh) + /* Arrange for logging to be sent to the monitor */ + set_log_handler(mm_log_handler, pmonitor); + +- privsep_preauth_child(); ++ privsep_preauth_child(ssh); + setproctitle("%s", "[net]"); + if (box != NULL) + ssh_sandbox_child(box); +@@ -594,7 +649,7 @@ privsep_postauth(struct ssh *ssh, Authct + set_log_handler(mm_log_handler, pmonitor); + + /* Demote the private keys to public keys. */ +- demote_sensitive_data(); ++ demote_sensitive_data(ssh); + + reseed_prngs(); + +@@ -1057,7 +1112,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; +@@ -1112,6 +1167,7 @@ server_accept_loop(int *sock_in, int *so if (received_sigterm) { logit("Received signal %d; terminating.", (int) received_sigterm); -+ destroy_sensitive_data(0); ++ destroy_sensitive_data(ssh, 0); close_listen_socks(); if (options.pid_file != NULL) unlink(options.pid_file); -@@ -2165,6 +2221,9 @@ main(int ac, char **av) +@@ -1978,7 +2034,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); + } + +@@ -2222,6 +2278,9 @@ main(int ac, char **av) do_authenticated(ssh, authctxt); /* The connection has been terminated. */ -+ packet_destroy_all(1, 1); -+ destroy_sensitive_data(1); ++ packet_destroy_all(ssh, 1, 1); ++ destroy_sensitive_data(ssh, 1); + - packet_get_bytes(&ibytes, &obytes); + ssh_packet_get_bytes(ssh, &ibytes, &obytes); verbose("Transferred: sent %llu, received %llu bytes", (unsigned long long)obytes, (unsigned long long)ibytes); -@@ -2344,6 +2403,15 @@ void +@@ -2401,6 +2460,15 @@ do_ssh2_kex(struct ssh *ssh) + void cleanup_exit(int i) { - struct ssh *ssh = active_state; /* XXX */ + static int in_cleanup = 0; + int is_privsep_child; + @@ -2104,29 +2250,31 @@ diff -up openssh-7.6p1/sshd.c.audit openssh-7.6p1/sshd.c + if (in_cleanup) + _exit(i); + in_cleanup = 1; - - if (the_authctxt) { - do_cleanup(ssh, the_authctxt); -@@ -2356,9 +2424,14 @@ cleanup_exit(int i) + if (the_active_state != NULL && the_authctxt != NULL) { + do_cleanup(the_active_state, the_authctxt); + if (use_privsep && privsep_is_preauth && +@@ -2414,9 +2482,16 @@ cleanup_exit(int i) pmonitor->m_pid, strerror(errno)); } } + is_privsep_child = use_privsep && pmonitor != NULL && pmonitor->m_pid == 0; -+ if (sensitive_data.host_keys != NULL) -+ destroy_sensitive_data(is_privsep_child); -+ packet_destroy_all(1, is_privsep_child); ++ 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 (!use_privsep || mm_is_monitor()) -+ if ((the_authctxt == NULL || !the_authctxt->authenticated) && +- if (the_active_state != NULL && (!use_privsep || mm_is_monitor())) ++ if (the_active_state != NULL && ++ (the_authctxt == NULL || !the_authctxt->authenticated) && + (!use_privsep || mm_is_monitor())) - audit_event(SSH_CONNECTION_ABANDON); + audit_event(the_active_state, SSH_CONNECTION_ABANDON); #endif _exit(i); -diff -up openssh-7.6p1/sshkey.c.audit openssh-7.6p1/sshkey.c ---- openssh-7.6p1/sshkey.c.audit 2017-10-04 17:18:32.758504660 +0200 -+++ openssh-7.6p1/sshkey.c 2017-10-04 17:18:32.839505074 +0200 -@@ -295,6 +295,32 @@ sshkey_type_is_valid_ca(int type) +diff -up openssh/sshkey.c.audit openssh/sshkey.c +--- openssh/sshkey.c.audit 2019-04-03 17:02:20.657885510 +0200 ++++ openssh/sshkey.c 2019-04-03 17:02:20.718886088 +0200 +@@ -331,6 +331,38 @@ sshkey_type_is_valid_ca(int type) } int @@ -2135,11 +2283,17 @@ diff -up openssh-7.6p1/sshkey.c.audit openssh-7.6p1/sshkey.c + switch (k->type) { +#ifdef WITH_OPENSSL + case KEY_RSA_CERT: -+ case KEY_RSA: -+ return k->rsa->d != NULL; ++ case KEY_RSA: { ++ const BIGNUM *d; ++ RSA_get0_key(k->rsa, NULL, NULL, &d); ++ return d != NULL; ++ } + case KEY_DSA_CERT: -+ case KEY_DSA: -+ return k->dsa->priv_key != NULL; ++ 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: @@ -2159,14 +2313,14 @@ diff -up openssh-7.6p1/sshkey.c.audit openssh-7.6p1/sshkey.c sshkey_is_cert(const struct sshkey *k) { if (k == NULL) -diff -up openssh-7.6p1/sshkey.h.audit openssh-7.6p1/sshkey.h ---- openssh-7.6p1/sshkey.h.audit 2017-10-04 17:18:32.758504660 +0200 -+++ openssh-7.6p1/sshkey.h 2017-10-04 17:18:32.840505079 +0200 -@@ -133,6 +133,7 @@ u_int sshkey_size(const struct sshkey - int sshkey_generate(int type, u_int bits, struct sshkey **keyp); - int sshkey_from_private(const struct sshkey *, struct sshkey **); +diff -up openssh/sshkey.h.audit openssh/sshkey.h +--- openssh/sshkey.h.audit 2019-04-03 17:02:20.657885510 +0200 ++++ openssh/sshkey.h 2019-04-03 17:02:20.718886088 +0200 +@@ -148,6 +148,7 @@ u_int sshkey_size(const struct sshkey + 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); - int sshkey_type_plain(int); diff --git a/openssh-7.6p1-cleanup-selinux.patch b/openssh-7.6p1-cleanup-selinux.patch index 3b5001a53885f747a97c46a8194221a66f3a7acb..08cd349efe1e3ca98834ede2311b8e3e9ce9ca0e 100644 --- a/openssh-7.6p1-cleanup-selinux.patch +++ b/openssh-7.6p1-cleanup-selinux.patch @@ -1,6 +1,6 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c ---- openssh/auth2-pubkey.c.refactor 2017-09-27 13:10:19.556830609 +0200 -+++ openssh/auth2-pubkey.c 2017-09-27 13:10:19.677831274 +0200 +--- 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 @@ extern ServerOptions options; extern u_char *session_id2; @@ -11,7 +11,7 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c static char * format_key(const struct sshkey *key) -@@ -432,7 +435,8 @@ match_principals_command(struct passwd * +@@ -511,7 +514,8 @@ match_principals_command(struct ssh *ssh if ((pid = subprocess("AuthorizedPrincipalsCommand", runas_pw, command, ac, av, &f, @@ -21,7 +21,7 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c goto out; uid_swapped = 1; -@@ -762,7 +766,8 @@ user_key_command_allowed2(struct passwd +@@ -981,7 +985,8 @@ user_key_command_allowed2(struct ssh *ss if ((pid = subprocess("AuthorizedKeysCommand", runas_pw, command, ac, av, &f, @@ -32,9 +32,9 @@ diff -up openssh/auth2-pubkey.c.refactor openssh/auth2-pubkey.c uid_swapped = 1; diff -up openssh/auth.c.refactor openssh/auth.c ---- openssh/auth.c.refactor 2017-09-27 13:10:19.640831071 +0200 -+++ openssh/auth.c 2017-09-27 13:10:19.678831279 +0200 -@@ -1435,7 +1435,8 @@ argv_assemble(int argc, char **argv) +--- openssh/auth.c.refactor 2019-04-04 13:19:12.235821686 +0200 ++++ openssh/auth.c 2019-04-04 13:19:12.276822078 +0200 +@@ -756,7 +756,8 @@ auth_get_canonical_hostname(struct ssh * */ pid_t subprocess(const char *tag, struct passwd *pw, const char *command, @@ -44,7 +44,7 @@ diff -up openssh/auth.c.refactor openssh/auth.c { FILE *f = NULL; struct stat st; -@@ -1551,7 +1552,7 @@ subprocess(const char *tag, struct passw +@@ -872,7 +873,7 @@ subprocess(const char *tag, struct passw } #ifdef WITH_SELINUX @@ -54,9 +54,9 @@ diff -up openssh/auth.c.refactor openssh/auth.c strerror(errno)); _exit(127); diff -up openssh/auth.h.refactor openssh/auth.h ---- openssh/auth.h.refactor 2017-09-25 01:48:10.000000000 +0200 -+++ openssh/auth.h 2017-09-27 13:10:19.678831279 +0200 -@@ -144,7 +144,7 @@ int exited_cleanly(pid_t, const char *, +--- openssh/auth.h.refactor 2019-04-04 13:19:12.251821839 +0200 ++++ openssh/auth.h 2019-04-04 13:19:12.276822078 +0200 +@@ -235,7 +235,7 @@ struct passwd *fakepw(void); #define SSH_SUBPROCESS_STDOUT_CAPTURE (1<<1) /* Redirect stdout */ #define SSH_SUBPROCESS_STDERR_DISCARD (1<<2) /* Discard stderr */ pid_t subprocess(const char *, struct passwd *, @@ -66,8 +66,8 @@ diff -up openssh/auth.h.refactor openssh/auth.h int sys_auth_passwd(struct ssh *, const char *); diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/port-linux.h ---- openssh/openbsd-compat/port-linux.h.refactor 2017-09-27 13:10:19.634831038 +0200 -+++ openssh/openbsd-compat/port-linux.h 2017-09-27 13:10:54.954025248 +0200 +--- openssh/openbsd-compat/port-linux.h.refactor 2019-04-04 13:19:12.256821887 +0200 ++++ openssh/openbsd-compat/port-linux.h 2019-04-04 13:19:12.276822078 +0200 @@ -26,8 +26,8 @@ void ssh_selinux_setfscreatecon(const ch int sshd_selinux_enabled(void); @@ -80,9 +80,9 @@ diff -up openssh/openbsd-compat/port-linux.h.refactor openssh/openbsd-compat/por #endif diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compat/port-linux-sshd.c ---- openssh/openbsd-compat/port-linux-sshd.c.refactor 2017-09-27 13:10:19.634831038 +0200 -+++ openssh/openbsd-compat/port-linux-sshd.c 2017-09-27 13:12:06.811420371 +0200 -@@ -48,11 +48,6 @@ +--- 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 @@ #include #endif @@ -94,7 +94,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa /* Wrapper around is_selinux_enabled() to log its return value once only */ int sshd_selinux_enabled(void) -@@ -222,7 +217,8 @@ get_user_context(const char *sename, con +@@ -223,7 +218,8 @@ get_user_context(const char *sename, con } static void @@ -104,7 +104,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa { *role = NULL; *level = NULL; -@@ -240,8 +236,8 @@ ssh_selinux_get_role_level(char **role, +@@ -241,8 +237,8 @@ ssh_selinux_get_role_level(char **role, /* Return the default security context for the given username */ static int @@ -115,7 +115,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa { char *sename, *lvl; char *role; -@@ -249,7 +245,7 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -250,7 +246,7 @@ sshd_selinux_getctxbyname(char *pwname, int r = 0; context_t con = NULL; @@ -124,7 +124,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa #ifdef HAVE_GETSEUSERBYNAME if ((r=getseuserbyname(pwname, &sename, &lvl)) != 0) { -@@ -271,7 +267,7 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -272,7 +268,7 @@ sshd_selinux_getctxbyname(char *pwname, if (r == 0) { /* If launched from xinetd, we must use current level */ @@ -133,7 +133,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa security_context_t sshdsc=NULL; if (getcon_raw(&sshdsc) < 0) -@@ -332,7 +328,8 @@ sshd_selinux_getctxbyname(char *pwname, +@@ -333,7 +329,8 @@ sshd_selinux_getctxbyname(char *pwname, /* Setup environment variables for pam_selinux */ static int @@ -143,7 +143,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa { const char *reqlvl; char *role; -@@ -341,11 +338,11 @@ sshd_selinux_setup_variables(int(*set_it +@@ -342,11 +339,11 @@ sshd_selinux_setup_variables(int(*set_it debug3("%s: setting execution context", __func__); @@ -157,7 +157,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa use_current = "1"; } else { use_current = ""; -@@ -361,9 +358,10 @@ sshd_selinux_setup_variables(int(*set_it +@@ -362,9 +359,10 @@ sshd_selinux_setup_variables(int(*set_it } static int @@ -170,7 +170,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa } static int -@@ -373,25 +371,28 @@ do_setenv(char *name, const char *value) +@@ -374,25 +372,28 @@ do_setenv(char *name, const char *value) } int @@ -204,7 +204,7 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa switch (security_getenforce()) { case -1: fatal("%s: security_getenforce() failed", __func__); -@@ -409,7 +410,7 @@ sshd_selinux_setup_exec_context(char *pw +@@ -410,7 +411,7 @@ sshd_selinux_setup_exec_context(char *pw debug3("%s: setting execution context", __func__); @@ -214,9 +214,9 @@ diff -up openssh/openbsd-compat/port-linux-sshd.c.refactor openssh/openbsd-compa r = setexeccon(user_ctx); if (r < 0) { diff -up openssh/platform.c.refactor openssh/platform.c ---- openssh/platform.c.refactor 2017-09-27 13:10:19.574830708 +0200 -+++ openssh/platform.c 2017-09-27 13:11:45.475303050 +0200 -@@ -33,6 +33,9 @@ +--- 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 @@ extern int use_privsep; extern ServerOptions options; @@ -226,7 +226,7 @@ diff -up openssh/platform.c.refactor openssh/platform.c void platform_pre_listen(void) -@@ -184,7 +187,9 @@ platform_setusercontext_post_groups(stru +@@ -183,7 +186,9 @@ platform_setusercontext_post_groups(stru } #endif /* HAVE_SETPCRED */ #ifdef WITH_SELINUX @@ -238,9 +238,27 @@ diff -up openssh/platform.c.refactor openssh/platform.c } diff -up openssh/sshd.c.refactor openssh/sshd.c ---- openssh/sshd.c.refactor 2017-09-27 13:10:19.674831257 +0200 -+++ openssh/sshd.c 2017-09-27 13:12:01.635391909 +0200 -@@ -2135,7 +2135,9 @@ main(int ac, char **av) +--- openssh/sshd.c.refactor 2019-04-04 13:19:12.275822068 +0200 ++++ openssh/sshd.c 2019-04-04 13:19:51.270195262 +0200 +@@ -158,7 +158,7 @@ int debug_flag = 0; + static int test_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; +@@ -2192,7 +2192,9 @@ main(int ac, char **av) } #endif #ifdef WITH_SELINUX diff --git a/openssh-7.6p1-pkcs11-ecdsa.patch b/openssh-7.6p1-pkcs11-ecdsa.patch deleted file mode 100644 index 2e73d45dc5c5262521e3e68c511215a38d3ccaf0..0000000000000000000000000000000000000000 --- a/openssh-7.6p1-pkcs11-ecdsa.patch +++ /dev/null @@ -1,801 +0,0 @@ -diff -up openssh-7.6p1/ssh-pkcs11-client.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11-client.c ---- openssh-7.6p1/ssh-pkcs11-client.c.pkcs11-ecdsa 2018-02-16 13:25:59.426469253 +0100 -+++ openssh-7.6p1/ssh-pkcs11-client.c 2018-02-16 13:25:59.428469265 +0100 -@@ -31,6 +31,15 @@ - #include - - #include -+#ifdef OPENSSL_HAS_ECC -+#include -+#if ((defined(LIBRESSL_VERSION_NUMBER) && \ -+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \ -+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \ -+ (OPENSSL_VERSION_NUMBER >= 0x00010100L) -+#define ENABLE_PKCS11_ECDSA 1 -+#endif -+#endif - - #include "pathnames.h" - #include "xmalloc.h" -@@ -139,9 +147,9 @@ pkcs11_rsa_private_encrypt(int flen, con - return (ret); - } - --/* redirect the private key encrypt operation to the ssh-pkcs11-helper */ -+/* redirect the RSA private key encrypt operation to the ssh-pkcs11-helper */ - static int --wrap_key(RSA *rsa) -+wrap_rsa_key(RSA *rsa) - { - static RSA_METHOD helper_rsa; - -@@ -152,6 +160,88 @@ wrap_key(RSA *rsa) - return (0); - } - -+#ifdef ENABLE_PKCS11_ECDSA -+static ECDSA_SIG * -+pkcs11_ecdsa_private_sign(const unsigned char *from, int flen, -+ const BIGNUM *inv, const BIGNUM *rp, EC_KEY * ecdsa) -+{ -+ struct sshkey *key = NULL; -+ u_char *blob, *signature = NULL; -+ size_t blen, slen = 0; -+ struct sshbuf *msg = NULL; -+ ECDSA_SIG *ret = NULL; -+ BIGNUM *r = NULL, *s = NULL; -+ int rv; -+ -+ if ((key = sshkey_new(KEY_ECDSA)) == NULL) -+ fatal("%s: sshkey_new failed", __func__); -+ key->ecdsa = ecdsa; -+ key->ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa); -+ if (sshkey_to_blob(key, &blob, &blen) == 0) -+ goto out; -+ if ((msg = sshbuf_new()) == NULL) -+ fatal("%s: sshbuf_new failed", __func__); -+ if ((rv = sshbuf_put_u8(msg, SSH2_AGENTC_SIGN_REQUEST)) != 0 || -+ (rv = sshbuf_put_string(msg, blob, blen)) != 0 || -+ (rv = sshbuf_put_string(msg, from, flen)) != 0 || -+ (rv = sshbuf_put_u32(msg, 0)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(rv)); -+ free(blob); -+ send_msg(msg); -+ sshbuf_reset(msg); -+ -+ if (recv_msg(msg) == SSH2_AGENT_SIGN_RESPONSE) { -+ if ((rv = sshbuf_get_string(msg, &signature, &slen)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(rv)); -+ if (slen <= (size_t)ECDSA_size(ecdsa)) { -+ int nlen = slen / 2; -+ ret = ECDSA_SIG_new(); -+ r = BN_new(); -+ s = BN_new(); -+ BN_bin2bn(&signature[0], nlen, r); -+ BN_bin2bn(&signature[nlen], nlen, s); -+ ECDSA_SIG_set0(ret, r, s); -+ } -+ free(signature); -+ } -+out: -+ sshkey_free(key); -+ sshbuf_free(msg); -+ return (ret); -+} -+ -+/* redirect the ECDSA private key encrypt operation to the ssh-pkcs11-helper */ -+static int -+wrap_ecdsa_key(EC_KEY *ecdsa) { -+#if (OPENSSL_VERSION_NUMBER >= 0x00010100L) -+ static EC_KEY_METHOD *helper_ecdsa = NULL; -+ if (helper_ecdsa == NULL) { -+ const EC_KEY_METHOD *def = EC_KEY_get_default_method(); -+ helper_ecdsa = EC_KEY_METHOD_new(def); -+ EC_KEY_METHOD_set_sign(helper_ecdsa, NULL, NULL, pkcs11_ecdsa_private_sign); -+ } -+ EC_KEY_set_method(ecdsa, helper_ecdsa); -+#else -+ static ECDSA_METHOD *helper_ecdsa = NULL; -+ if(helper_ecdsa == NULL) { -+ const ECDSA_METHOD *def = ECDSA_get_default_method(); -+# ifdef ECDSA_F_ECDSA_METHOD_NEW -+ helper_ecdsa = ECDSA_METHOD_new((ECDSA_METHOD *)def); -+ ECDSA_METHOD_set_name(helper_ecdsa, "ssh-pkcs11-helper-ecdsa"); -+ ECDSA_METHOD_set_sign(helper_ecdsa, pkcs11_ecdsa_private_sign); -+# else -+ helper_ecdsa = xcalloc(1, sizeof(*helper_ecdsa)); -+ memcpy(helper_ecdsa, def, sizeof(*helper_ecdsa)); -+ helper_ecdsa->name = "ssh-pkcs11-helper-ecdsa"; -+ helper_ecdsa->ecdsa_do_sign = pkcs11_ecdsa_private_sign; -+# endif -+ } -+ ECDSA_set_method(ecdsa, helper_ecdsa); -+#endif -+ return (0); -+} -+#endif -+ - static int - pkcs11_start_helper(void) - { -@@ -212,7 +281,15 @@ pkcs11_add_provider(char *name, char *pi - __func__, ssh_err(r)); - if ((r = sshkey_from_blob(blob, blen, &k)) != 0) - fatal("%s: bad key: %s", __func__, ssh_err(r)); -- wrap_key(k->rsa); -+ if(k->type == KEY_RSA) { -+ wrap_rsa_key(k->rsa); -+#ifdef ENABLE_PKCS11_ECDSA -+ } else if(k->type == KEY_ECDSA) { -+ wrap_ecdsa_key(k->ecdsa); -+#endif /* ENABLE_PKCS11_ECDSA */ -+ } else { -+ /* Unsupported type */ -+ } - (*keysp)[i] = k; - free(blob); - } -diff -up openssh-7.6p1/ssh-pkcs11.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11.c ---- openssh-7.6p1/ssh-pkcs11.c.pkcs11-ecdsa 2018-02-16 13:25:59.427469259 +0100 -+++ openssh-7.6p1/ssh-pkcs11.c 2018-02-16 13:44:51.270554797 +0100 -@@ -32,6 +32,16 @@ - #include "openbsd-compat/sys-queue.h" - - #include -+#include -+#ifdef OPENSSL_HAS_ECC -+#include -+#if ((defined(LIBRESSL_VERSION_NUMBER) && \ -+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \ -+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \ -+ (OPENSSL_VERSION_NUMBER >= 0x00010100L) -+#define ENABLE_PKCS11_ECDSA 1 -+#endif -+#endif - - #define CRYPTOKI_COMPAT - #include "pkcs11.h" -@@ -67,6 +76,7 @@ TAILQ_HEAD(, pkcs11_provider) pkcs11_pro - struct pkcs11_key { - struct pkcs11_provider *provider; - CK_ULONG slotidx; -+ CK_ULONG key_type; - int (*orig_finish)(RSA *rsa); - RSA_METHOD rsa_method; - char *keyid; -@@ -75,6 +85,9 @@ struct pkcs11_key { - }; - - int pkcs11_interactive = 0; -+#ifdef ENABLE_PKCS11_ECDSA -+static int pkcs11_key_idx = -1; -+#endif /* ENABLE_PKCS11_ECDSA */ - - /* - * This can't be in the ssh-pkcs11-uri, becase we can not depend on -@@ -289,6 +302,40 @@ pkcs11_find(struct pkcs11_provider *p, C - return (ret); - } - -+int pkcs11_login(struct pkcs11_key *k11, CK_FUNCTION_LIST *f, struct pkcs11_slotinfo *si) { -+ char *pin = NULL, prompt[1024]; -+ CK_RV rv; -+ if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { -+ if (!pkcs11_interactive) { -+ error("need pin entry%s", (si->token.flags & -+ CKF_PROTECTED_AUTHENTICATION_PATH) ? -+ " on reader keypad" : ""); -+ return (-1); -+ } -+ if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) -+ verbose("Deferring PIN entry to reader keypad."); -+ else { -+ snprintf(prompt, sizeof(prompt), -+ "Enter PIN for '%s': ", si->token.label); -+ pin = read_passphrase(prompt, RP_ALLOW_EOF); -+ if (pin == NULL) -+ return (-1); /* bail out */ -+ } -+ rv = f->C_Login(si->session, CKU_USER, (u_char *)pin, -+ (pin != NULL) ? strlen(pin) : 0); -+ if (pin != NULL) { -+ explicit_bzero(pin, strlen(pin)); -+ free(pin); -+ } -+ if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { -+ error("C_Login failed: %lu", rv); -+ return (-1); -+ } -+ si->logged_in = 1; -+ } -+ return 0; -+} -+ - /* openssl callback doing the actual signing operation */ - static int - pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, -@@ -310,7 +357,6 @@ pkcs11_rsa_private_encrypt(int flen, con - {CKA_ID, NULL, 0}, - {CKA_SIGN, NULL, sizeof(true_val) } - }; -- char *pin = NULL, prompt[1024]; - int rval = -1; - - key_filter[0].pValue = &private_key_class; -@@ -326,33 +372,8 @@ pkcs11_rsa_private_encrypt(int flen, con - } - f = k11->provider->module->function_list; - si = &k11->provider->module->slotinfo[k11->slotidx]; -- if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { -- if (!pkcs11_interactive) { -- error("need pin entry%s", (si->token.flags & -- CKF_PROTECTED_AUTHENTICATION_PATH) ? -- " on reader keypad" : ""); -- return (-1); -- } -- if (si->token.flags & CKF_PROTECTED_AUTHENTICATION_PATH) -- verbose("Deferring PIN entry to reader keypad."); -- else { -- snprintf(prompt, sizeof(prompt), -- "Enter PIN for '%s': ", si->token.label); -- pin = read_passphrase(prompt, RP_ALLOW_EOF); -- if (pin == NULL) -- return (-1); /* bail out */ -- } -- rv = f->C_Login(si->session, CKU_USER, (u_char *)pin, -- (pin != NULL) ? strlen(pin) : 0); -- if (pin != NULL) { -- explicit_bzero(pin, strlen(pin)); -- free(pin); -- } -- if (rv != CKR_OK && rv != CKR_USER_ALREADY_LOGGED_IN) { -- error("C_Login failed: %lu", rv); -- return (-1); -- } -- si->logged_in = 1; -+ if(pkcs11_login(k11, f, si)) { -+ return (-1); - } - key_filter[1].pValue = k11->keyid; - key_filter[1].ulValueLen = k11->keyid_len; -@@ -390,6 +411,7 @@ pkcs11_rsa_wrap(struct pkcs11_provider * - const RSA_METHOD *def = RSA_get_default_method(); - - k11 = xcalloc(1, sizeof(*k11)); -+ k11->key_type = CKK_RSA; - k11->provider = provider; - provider->refcount++; /* provider referenced by RSA key */ - k11->slotidx = slotidx; -@@ -415,6 +437,184 @@ pkcs11_rsa_wrap(struct pkcs11_provider * - return (0); - } - -+#ifdef ENABLE_PKCS11_ECDSA -+static ECDSA_SIG *pkcs11_ecdsa_sign(const unsigned char *dgst, int dgst_len, -+ const BIGNUM *inv, const BIGNUM *rp, -+ EC_KEY *ecdsa) { -+ struct pkcs11_key *k11; -+ struct pkcs11_slotinfo *si; -+ CK_FUNCTION_LIST *f; -+ CK_OBJECT_HANDLE obj; -+ CK_ULONG tlen = 0; -+ CK_RV rv; -+ CK_OBJECT_CLASS private_key_class = CKO_PRIVATE_KEY; -+ CK_BBOOL true_val = CK_TRUE; -+ CK_MECHANISM mech = { -+ CKM_ECDSA, NULL_PTR, 0 -+ }; -+ CK_ATTRIBUTE key_filter[] = { -+ {CKA_CLASS, NULL, sizeof(private_key_class) }, -+ {CKA_ID, NULL, 0}, -+ {CKA_SIGN, NULL, sizeof(true_val) } -+ }; -+ ECDSA_SIG *rval = NULL; -+ key_filter[0].pValue = &private_key_class; -+ key_filter[2].pValue = &true_val; -+ -+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L) -+ if ((k11 = (struct pkcs11_key *)EC_KEY_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) { -+ error("EC_KEY_get_ex_data failed for ecdsa %p", ecdsa); -+ #else -+ if ((k11 = (struct pkcs11_key *)ECDSA_get_ex_data(ecdsa, pkcs11_key_idx)) == NULL) { -+ error("ECDSA_get_ex_data failed for ecdsa %p", ecdsa); -+ #endif -+ return NULL; -+ } -+ if (!k11->provider || !k11->provider->valid) { -+ error("no pkcs11 (valid) provider for ecdsa %p", ecdsa); -+ return NULL; -+ } -+ f = k11->provider->module->function_list; -+ si = &k11->provider->module->slotinfo[k11->slotidx]; -+ if(pkcs11_login(k11, f, si)) { -+ return NULL; -+ } -+ key_filter[1].pValue = k11->keyid; -+ key_filter[1].ulValueLen = k11->keyid_len; -+ /* try to find object w/CKA_SIGN first, retry w/o */ -+ if (pkcs11_find(k11->provider, k11->slotidx, key_filter, 3, &obj) < 0 && -+ pkcs11_find(k11->provider, k11->slotidx, key_filter, 2, &obj) < 0) { -+ error("cannot find private key"); -+ } else if ((rv = f->C_SignInit(si->session, &mech, obj)) != CKR_OK) { -+ error("C_SignInit failed: %lu", rv); -+ } else { -+ CK_BYTE_PTR buf = NULL; -+ BIGNUM *r = NULL, *s = NULL; -+ int nlen; -+ /* Make a call to C_Sign to find out the size of the signature */ -+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, NULL, &tlen); -+ if (rv != CKR_OK) { -+ error("C_Sign failed: %lu", rv); -+ return NULL; -+ } -+ if ((buf = xmalloc(tlen)) == NULL) { -+ error("failure to allocate signature buffer"); -+ return NULL; -+ } -+ rv = f->C_Sign(si->session, (CK_BYTE *)dgst, dgst_len, buf, &tlen); -+ if (rv != CKR_OK) { -+ error("C_Sign failed: %lu", rv); -+ } -+ -+ if ((rval = ECDSA_SIG_new()) == NULL || -+ (r = BN_new()) == NULL || -+ (s = BN_new()) == NULL) { -+ error("failure to allocate ECDSA signature"); -+ } else { -+ /* -+ * ECDSA signature is 2 large integers of same size returned -+ * concatenated by PKCS#11, we separate them to create an -+ * ECDSA_SIG for OpenSSL. -+ */ -+ nlen = tlen / 2; -+ BN_bin2bn(&buf[0], nlen, r); -+ BN_bin2bn(&buf[nlen], nlen, s); -+ ECDSA_SIG_set0(rval, r, s); -+ } -+ free(buf); -+ } -+ return (rval); -+} -+ -+#if (OPENSSL_VERSION_NUMBER >= 0x00010100L) -+static EC_KEY_METHOD *get_pkcs11_ecdsa_method(void) { -+ static EC_KEY_METHOD *pkcs11_ecdsa_method = NULL; -+ if(pkcs11_key_idx == -1) { -+ pkcs11_key_idx = EC_KEY_get_ex_new_index(0, NULL, NULL, NULL, 0); -+ } -+ if (pkcs11_ecdsa_method == NULL) { -+ const EC_KEY_METHOD *def = EC_KEY_get_default_method(); -+ pkcs11_ecdsa_method = EC_KEY_METHOD_new(def); -+ EC_KEY_METHOD_set_sign(pkcs11_ecdsa_method, NULL, NULL, pkcs11_ecdsa_sign); -+ } -+#else -+static ECDSA_METHOD *get_pkcs11_ecdsa_method(void) { -+ static ECDSA_METHOD *pkcs11_ecdsa_method = NULL; -+ if(pkcs11_key_idx == -1) { -+ pkcs11_key_idx = ECDSA_get_ex_new_index(0, NULL, NULL, NULL, 0); -+ } -+ if(pkcs11_ecdsa_method == NULL) { -+ const ECDSA_METHOD *def = ECDSA_get_default_method(); -+ #ifdef ECDSA_F_ECDSA_METHOD_NEW -+ pkcs11_ecdsa_method = ECDSA_METHOD_new((ECDSA_METHOD *)def); -+ ECDSA_METHOD_set_name(pkcs11_ecdsa_method, "pkcs11"); -+ ECDSA_METHOD_set_sign(pkcs11_ecdsa_method, pkcs11_ecdsa_sign); -+ #else -+ pkcs11_ecdsa_method = xcalloc(1, sizeof(*pkcs11_ecdsa_method)); -+ memcpy(pkcs11_ecdsa_method, def, sizeof(*pkcs11_ecdsa_method)); -+ pkcs11_ecdsa_method->name = "pkcs11"; -+ pkcs11_ecdsa_method->ecdsa_do_sign = pkcs11_ecdsa_sign; -+ #endif -+ } -+#endif -+ return pkcs11_ecdsa_method; -+} -+ -+static int -+pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, -+ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ecdsa) -+{ -+ struct pkcs11_key *k11; -+ k11 = xcalloc(1, sizeof(*k11)); -+ k11->key_type = CKK_EC; -+ k11->provider = provider; -+ provider->refcount++; /* provider referenced by ECDSA key */ -+ k11->slotidx = slotidx; -+ /* identify key object on smartcard */ -+ k11->keyid_len = keyid_attrib->ulValueLen; -+ if (k11->keyid_len > 0) { -+ k11->keyid = xmalloc(k11->keyid_len); -+ memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); -+ } -+ if (label_attrib->ulValueLen > 0 ) { -+ k11->label = xmalloc(label_attrib->ulValueLen+1); -+ memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); -+ k11->label[label_attrib->ulValueLen] = 0; -+ } -+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L) -+ EC_KEY_set_method(ecdsa, get_pkcs11_ecdsa_method()); -+ EC_KEY_set_ex_data(ecdsa, pkcs11_key_idx, k11); -+ #else -+ ECDSA_set_method(ecdsa, get_pkcs11_ecdsa_method()); -+ ECDSA_set_ex_data(ecdsa, pkcs11_key_idx, k11); -+ #endif -+ return (0); -+} -+#endif /* ENABLE_PKCS11_ECDSA */ -+ -+int pkcs11_del_key(struct sshkey *key) { -+#ifdef ENABLE_PKCS11_ECDSA -+ if(key->type == KEY_ECDSA) { -+ struct pkcs11_key *k11 = (struct pkcs11_key *) -+ #if (OPENSSL_VERSION_NUMBER >= 0x00010100L) -+ EC_KEY_get_ex_data(key->ecdsa, pkcs11_key_idx); -+ #else -+ ECDSA_get_ex_data(key->ecdsa, pkcs11_key_idx); -+ #endif -+ if (k11 == NULL) { -+ error("EC_KEY_get_ex_data failed for ecdsa %p", key->ecdsa); -+ } else { -+ if (k11->provider) -+ pkcs11_provider_unref(k11->provider); -+ free(k11->keyid); -+ free(k11); -+ } -+ } -+#endif /* ENABLE_PKCS11_ECDSA */ -+ sshkey_free(key); -+ return (0); -+} -+ - /* remove trailing spaces */ - static void - rmspace(u_char *buf, size_t len) -@@ -482,11 +646,13 @@ static int - pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, - struct sshkey ***keysp, int *nkeys, struct pkcs11_uri *uri) - { -- size_t filter_size = 1; -+ size_t filter_size = 2; -+ CK_KEY_TYPE pubkey_type = CKK_RSA; - CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; - CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; - CK_ATTRIBUTE pubkey_filter[] = { - { CKA_CLASS, NULL, sizeof(pubkey_class) }, -+ { CKA_KEY_TYPE, NULL, sizeof(pubkey_type) }, - { CKA_ID, NULL, 0 }, - { CKA_LABEL, NULL, 0 } - }; -@@ -507,29 +673,60 @@ pkcs11_fetch_keys(struct pkcs11_provider - { CKA_SUBJECT, NULL, 0 }, - { CKA_VALUE, NULL, 0 } - }; -+#ifdef ENABLE_PKCS11_ECDSA -+ CK_KEY_TYPE ecdsa_type = CKK_EC; -+ CK_ATTRIBUTE ecdsa_filter[] = { -+ { CKA_CLASS, NULL, sizeof(pubkey_class) }, -+ { CKA_KEY_TYPE, NULL, sizeof(ecdsa_type) }, -+ { CKA_ID, NULL, 0 }, -+ { CKA_LABEL, NULL, 0 } -+ }; -+ CK_ATTRIBUTE ecdsa_attribs[] = { -+ { CKA_ID, NULL, 0 }, -+ { CKA_LABEL, NULL, 0 }, -+ { CKA_EC_PARAMS, NULL, 0 }, -+ { CKA_EC_POINT, NULL, 0 } -+ }; -+ ecdsa_filter[0].pValue = &pubkey_class; -+ ecdsa_filter[1].pValue = &ecdsa_type; -+#endif /* ENABLE_PKCS11_ECDSA */ - pubkey_filter[0].pValue = &pubkey_class; -+ pubkey_filter[1].pValue = &pubkey_type; - cert_filter[0].pValue = &cert_class; - - if (uri->id != NULL) { - pubkey_filter[filter_size].pValue = uri->id; - pubkey_filter[filter_size].ulValueLen = uri->id_len; -- cert_filter[filter_size].pValue = uri->id; -- cert_filter[filter_size].ulValueLen = uri->id_len; -+#ifdef ENABLE_PKCS11_ECDSA -+ ecdsa_filter[filter_size].pValue = uri->id; -+ ecdsa_filter[filter_size].ulValueLen = uri->id_len; -+#endif /* ENABLE_PKCS11_ECDSA */ -+ cert_filter[filter_size-1].pValue = uri->id; -+ cert_filter[filter_size-1].ulValueLen = uri->id_len; - filter_size++; - } - if (uri->object != NULL) { - pubkey_filter[filter_size].pValue = uri->object; - pubkey_filter[filter_size].ulValueLen = strlen(uri->object); - pubkey_filter[filter_size].type = CKA_LABEL; -- cert_filter[filter_size].pValue = uri->object; -- cert_filter[filter_size].ulValueLen = strlen(uri->object); -- cert_filter[filter_size].type = CKA_LABEL; -+#ifdef ENABLE_PKCS11_ECDSA -+ ecdsa_filter[filter_size].pValue = uri->object; -+ ecdsa_filter[filter_size].ulValueLen = strlen(uri->object); -+ ecdsa_filter[filter_size].type = CKA_LABEL; -+#endif /* ENABLE_PKCS11_ECDSA */ -+ cert_filter[filter_size-1].pValue = uri->object; -+ cert_filter[filter_size-1].ulValueLen = strlen(uri->object); -+ cert_filter[filter_size-1].type = CKA_LABEL; - filter_size++; - } - - if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, filter_size, - pubkey_attribs, keysp, nkeys) < 0 || -- pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size, -+#ifdef ENABLE_PKCS11_ECDSA -+ pkcs11_fetch_keys_filter(p, slotidx, ecdsa_filter, filter_size, -+ ecdsa_attribs, keysp, nkeys) < 0|| -+#endif /* ENABLE_PKCS11_ECDSA */ -+ pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size - 1, - cert_attribs, keysp, nkeys) < 0) - return (-1); - return (0); -@@ -553,6 +746,11 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - { - struct sshkey *key; - RSA *rsa; -+#ifdef ENABLE_PKCS11_ECDSA -+ EC_KEY *ecdsa; -+#else -+ void *ecdsa; -+#endif /* ENABLE_PKCS11_ECDSA */ - X509 *x509; - EVP_PKEY *evp = NULL; - int i; -@@ -608,6 +806,9 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - * or ID, label, subject and value for certificates. - */ - rsa = NULL; -+#ifdef ENABLE_PKCS11_ECDSA -+ ecdsa = NULL; -+#endif /* ENABLE_PKCS11_ECDSA */ - if ((rv = f->C_GetAttributeValue(session, obj, attribs, nattribs)) - != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); -@@ -620,6 +821,45 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - rsa->e = BN_bin2bn(attribs[3].pValue, - attribs[3].ulValueLen, NULL); - } -+#ifdef ENABLE_PKCS11_ECDSA -+ } else if (attribs[2].type == CKA_EC_PARAMS ) { -+ if ((ecdsa = EC_KEY_new()) == NULL) { -+ error("EC_KEY_new failed"); -+ } else { -+ const unsigned char *ptr1 = attribs[2].pValue; -+ const unsigned char *ptr2 = attribs[3].pValue; -+ CK_ULONG len1 = attribs[2].ulValueLen; -+ CK_ULONG len2 = attribs[3].ulValueLen; -+ ASN1_OCTET_STRING *point = NULL; -+ -+ /* -+ * CKA_EC_PARAMS contains the curve parameters of the key -+ * either referenced as an OID or directly with all values. -+ * CKA_EC_POINT contains the point (public key) on the curve. -+ * The point is should be returned inside a DER-encoded -+ * ASN.1 OCTET STRING value (but some implementation). -+ */ -+ if ((point = d2i_ASN1_OCTET_STRING(NULL, &ptr2, len2))) { -+ /* Pointing to OCTET STRING content */ -+ ptr2 = point->data; -+ len2 = point->length; -+ } else { -+ /* No OCTET STRING */ -+ ptr2 = attribs[3].pValue; -+ } -+ -+ if((d2i_ECParameters(&ecdsa, &ptr1, len1) == NULL) || -+ (o2i_ECPublicKey(&ecdsa, &ptr2, len2) == NULL)) { -+ EC_KEY_free(ecdsa); -+ ecdsa = NULL; -+ error("EC public key parsing failed"); -+ } -+ -+ if(point) { -+ ASN1_OCTET_STRING_free(point); -+ } -+ } -+#endif /* ENABLE_PKCS11_ECDSA */ - } else { - cp = attribs[3].pValue; - if ((x509 = X509_new()) == NULL) { -@@ -639,13 +879,28 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - X509_free(x509); - EVP_PKEY_free(evp); - } -- if (rsa && rsa->n && rsa->e && -- pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) { -- if ((key = sshkey_new(KEY_UNSPEC)) == NULL) -- fatal("sshkey_new failed"); -- key->rsa = rsa; -- key->type = KEY_RSA; -- key->flags |= SSHKEY_FLAG_EXT; -+ key = NULL; -+ if (rsa || ecdsa) { -+ if (rsa && rsa->n && rsa->e && -+ pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) { -+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL) -+ fatal("sshkey_new failed"); -+ key->rsa = rsa; -+ key->type = KEY_RSA; -+ key->flags |= SSHKEY_FLAG_EXT; -+#ifdef ENABLE_PKCS11_ECDSA -+ } else if(ecdsa && pkcs11_ecdsa_wrap(p, slotidx, &attribs[0], &attribs[1], ecdsa) == 0) { -+ if ((key = sshkey_new(KEY_UNSPEC)) == NULL) -+ fatal("sshkey_new failed"); -+ key->ecdsa = ecdsa; -+ key->ecdsa_nid = sshkey_ecdsa_key_to_nid(ecdsa); -+ key->type = KEY_ECDSA; -+ key->flags |= SSHKEY_FLAG_EXT; -+#endif /* ENABLE_PKCS11_ECDSA */ -+ } -+ } -+ -+ if(key) { - if (pkcs11_key_included(keysp, nkeys, key)) { - sshkey_free(key); - } else { -@@ -658,6 +913,10 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - } - } else if (rsa) { - RSA_free(rsa); -+#ifdef ENABLE_PKCS11_ECDSA -+ } else if (ecdsa) { -+ EC_KEY_free(ecdsa); -+#endif /* ENABLE_PKCS11_ECDSA */ - } - for (i = 0; i < nattribs; i++) - free(attribs[i].pValue); -diff -up openssh-7.6p1/ssh-pkcs11-helper.c.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11-helper.c ---- openssh-7.6p1/ssh-pkcs11-helper.c.pkcs11-ecdsa 2017-10-02 21:34:26.000000000 +0200 -+++ openssh-7.6p1/ssh-pkcs11-helper.c 2018-02-16 13:25:59.428469265 +0100 -@@ -24,6 +24,17 @@ - - #include "openbsd-compat/sys-queue.h" - -+#include -+#ifdef OPENSSL_HAS_ECC -+#include -+#if ((defined(LIBRESSL_VERSION_NUMBER) && \ -+ (LIBRESSL_VERSION_NUMBER >= 0x20010002L))) || \ -+ (defined(ECDSA_F_ECDSA_METHOD_NEW)) || \ -+ (OPENSSL_VERSION_NUMBER >= 0x00010100L) -+#define ENABLE_PKCS11_ECDSA 1 -+#endif -+#endif -+ - #include - #include - #include -@@ -80,7 +90,7 @@ del_keys_by_name(char *name) - if (!strcmp(ki->providername, name)) { - TAILQ_REMOVE(&pkcs11_keylist, ki, next); - free(ki->providername); -- sshkey_free(ki->key); -+ pkcs11_del_key(ki->key); - free(ki); - } - } -@@ -164,6 +174,20 @@ process_del(void) - sshbuf_free(msg); - } - -+#ifdef ENABLE_PKCS11_ECDSA -+static u_int EC_KEY_order_size(EC_KEY *key) -+{ -+ const EC_GROUP *group = EC_KEY_get0_group(key); -+ BIGNUM *order = BN_new(); -+ u_int nbytes = 0; -+ if ((group != NULL) && (order != NULL) && EC_GROUP_get_order(group, order, NULL)) { -+ nbytes = BN_num_bytes(order); -+ } -+ BN_clear_free(order); -+ return nbytes; -+} -+#endif /* ENABLE_PKCS11_ECDSA */ -+ - static void - process_sign(void) - { -@@ -180,14 +204,38 @@ process_sign(void) - else { - if ((found = lookup_key(key)) != NULL) { - #ifdef WITH_OPENSSL -- int ret; -- -- slen = RSA_size(key->rsa); -- signature = xmalloc(slen); -- if ((ret = RSA_private_encrypt(dlen, data, signature, -- found->rsa, RSA_PKCS1_PADDING)) != -1) { -- slen = ret; -- ok = 0; -+ if(found->type == KEY_RSA) { -+ int ret; -+ slen = RSA_size(key->rsa); -+ signature = xmalloc(slen); -+ if ((ret = RSA_private_encrypt(dlen, data, signature, -+ found->rsa, RSA_PKCS1_PADDING)) != -1) { -+ slen = ret; -+ ok = 0; -+ } -+#ifdef ENABLE_PKCS11_ECDSA -+ } else if(found->type == KEY_ECDSA) { -+ ECDSA_SIG *sig; -+ const BIGNUM *r = NULL, *s = NULL; -+ if ((sig = ECDSA_do_sign(data, dlen, found->ecdsa)) != NULL) { -+ /* PKCS11 2.3.1 recommends both r and s to have the order size for -+ backward compatiblity */ -+ ECDSA_SIG_get0(sig, &r, &s); -+ u_int o_len = EC_KEY_order_size(found->ecdsa); -+ u_int r_len = BN_num_bytes(r); -+ u_int s_len = BN_num_bytes(s); -+ if (o_len > 0 && r_len <= o_len && s_len <= o_len) { -+ signature = xcalloc(2, o_len); -+ BN_bn2bin(r, signature + o_len - r_len); -+ BN_bn2bin(s, signature + (2 * o_len) - s_len); -+ slen = 2 * o_len; -+ ok = 0; -+ } -+ ECDSA_SIG_free(sig); -+ } -+#endif /* ENABLE_PKCS11_ECDSA */ -+ } else { -+ /* Unsupported type */ - } - #endif /* WITH_OPENSSL */ - } -diff -up openssh-7.6p1/ssh-pkcs11.h.pkcs11-ecdsa openssh-7.6p1/ssh-pkcs11.h ---- openssh-7.6p1/ssh-pkcs11.h.pkcs11-ecdsa 2018-02-16 13:25:59.429469272 +0100 -+++ openssh-7.6p1/ssh-pkcs11.h 2018-02-16 13:45:29.623800048 +0100 -@@ -20,6 +20,7 @@ - int pkcs11_init(int); - void pkcs11_terminate(void); - int pkcs11_add_provider(char *, char *, struct sshkey ***); -+int pkcs11_del_key(struct sshkey *); - int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***); - int pkcs11_del_provider(char *); - int pkcs11_uri_write(const struct sshkey *, FILE *); - - - -diff -up openssh-7.6p1/ssh-pkcs11.c.old openssh-7.6p1/ssh-pkcs11.c ---- openssh-7.6p1/ssh-pkcs11.c.old 2018-02-16 16:43:08.861520255 +0100 -+++ openssh-7.6p1/ssh-pkcs11.c 2018-02-16 16:56:35.312601451 +0100 -@@ -917,13 +917,28 @@ pkcs11_fetch_keys_filter(struct pkcs11_p - } else if (d2i_X509(&x509, &cp, attribs[3].ulValueLen) - == NULL) { - error("d2i_X509 failed"); -- } else if ((evp = X509_get_pubkey(x509)) == NULL || -- evp->type != EVP_PKEY_RSA || -- evp->pkey.rsa == NULL) { -- debug("X509_get_pubkey failed or no rsa"); -- } else if ((rsa = RSAPublicKey_dup(evp->pkey.rsa)) -- == NULL) { -- error("RSAPublicKey_dup"); -+ } else if ((evp = X509_get_pubkey(x509)) == NULL) { -+ debug("X509_get_pubkey failed"); -+ } else { -+ switch (evp->type) { -+ case EVP_PKEY_RSA: -+ if (evp->pkey.rsa == NULL) -+ debug("Missing RSA key"); -+ else if ((rsa = RSAPublicKey_dup( -+ evp->pkey.rsa)) == NULL) -+ error("RSAPublicKey_dup failed"); -+ break; -+ case EVP_PKEY_EC: -+ if (evp->pkey.ecdsa == NULL) -+ debug("Missing ECDSA key"); -+ else if ((ecdsa = EC_KEY_dup( -+ evp->pkey.ecdsa)) == NULL) -+ error("EC_KEY_dup failed"); -+ break; -+ default: -+ debug("not a RSA or ECDSA key"); -+ break; -+ } - } - X509_free(x509); - EVP_PKEY_free(evp); diff --git a/openssh-7.7p1-fips.patch b/openssh-7.7p1-fips.patch index 084c903467e84c52f12e50fe56ba4d4e90fa4858..bb69efec6a804112893bff1288b3a8fcb22c8850 100644 --- a/openssh-7.7p1-fips.patch +++ b/openssh-7.7p1-fips.patch @@ -1,70 +1,6 @@ -diff -up openssh-7.7p1/cipher.c.fips openssh-7.7p1/cipher.c ---- openssh-7.7p1/cipher.c.fips 2018-08-08 10:08:40.814719906 +0200 -+++ openssh-7.7p1/cipher.c 2018-08-08 10:08:40.821719965 +0200 -@@ -39,6 +39,8 @@ - - #include - -+#include -+ - #include - #include - #include -@@ -90,6 +92,33 @@ static const struct sshcipher ciphers[] - { NULL, 0, 0, 0, 0, 0, NULL } - }; - -+static const struct sshcipher fips_ciphers[] = { -+#ifdef WITH_OPENSSL -+ { "3des-cbc", 8, 24, 0, 0, CFLAG_CBC, EVP_des_ede3_cbc }, -+ { "aes128-cbc", 16, 16, 0, 0, CFLAG_CBC, EVP_aes_128_cbc }, -+ { "aes192-cbc", 16, 24, 0, 0, CFLAG_CBC, EVP_aes_192_cbc }, -+ { "aes256-cbc", 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, -+ { "rijndael-cbc@lysator.liu.se", -+ 16, 32, 0, 0, CFLAG_CBC, EVP_aes_256_cbc }, -+ { "aes128-ctr", 16, 16, 0, 0, 0, EVP_aes_128_ctr }, -+ { "aes192-ctr", 16, 24, 0, 0, 0, EVP_aes_192_ctr }, -+ { "aes256-ctr", 16, 32, 0, 0, 0, EVP_aes_256_ctr }, -+# ifdef OPENSSL_HAVE_EVPGCM -+ { "aes128-gcm@openssh.com", -+ 16, 16, 12, 16, 0, EVP_aes_128_gcm }, -+ { "aes256-gcm@openssh.com", -+ 16, 32, 12, 16, 0, EVP_aes_256_gcm }, -+# endif /* OPENSSL_HAVE_EVPGCM */ -+#else -+ { "aes128-ctr", 16, 16, 0, 0, CFLAG_AESCTR, NULL }, -+ { "aes192-ctr", 16, 24, 0, 0, CFLAG_AESCTR, NULL }, -+ { "aes256-ctr", 16, 32, 0, 0, CFLAG_AESCTR, NULL }, -+#endif -+ { "none", 8, 0, 0, 0, CFLAG_NONE, NULL }, -+ -+ { NULL, 0, 0, 0, 0, 0, NULL } -+}; -+ - /*--*/ - - /* Returns a comma-separated list of supported ciphers. */ -@@ -100,7 +129,7 @@ cipher_alg_list(char sep, int auth_only) - size_t nlen, rlen = 0; - const struct sshcipher *c; - -- for (c = ciphers; c->name != NULL; c++) { -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) { - if ((c->flags & CFLAG_INTERNAL) != 0) - continue; - if (auth_only && c->auth_len == 0) -@@ -172,7 +201,7 @@ const struct sshcipher * - cipher_by_name(const char *name) - { - const struct sshcipher *c; -- for (c = ciphers; c->name != NULL; c++) -+ for (c = FIPS_mode() ? fips_ciphers : ciphers; c->name != NULL; c++) - if (strcmp(c->name, name) == 0) - return c; - return NULL; -diff -up openssh-7.7p1/cipher-ctr.c.fips openssh-7.7p1/cipher-ctr.c ---- openssh-7.7p1/cipher-ctr.c.fips 2018-08-08 10:08:40.709719021 +0200 -+++ openssh-7.7p1/cipher-ctr.c 2018-08-08 10:08:40.821719965 +0200 +diff -up openssh-8.0p1/cipher-ctr.c.fips openssh-8.0p1/cipher-ctr.c +--- openssh-8.0p1/cipher-ctr.c.fips 2019-07-23 14:55:45.326525641 +0200 ++++ openssh-8.0p1/cipher-ctr.c 2019-07-23 14:55:45.401526401 +0200 @@ -179,7 +179,8 @@ evp_aes_128_ctr(void) aes_ctr.do_cipher = ssh_aes_ctr; #ifndef SSH_OLD_EVP @@ -75,100 +11,76 @@ diff -up openssh-7.7p1/cipher-ctr.c.fips openssh-7.7p1/cipher-ctr.c #endif return (&aes_ctr); } -diff -up openssh-7.7p1/clientloop.c.fips openssh-7.7p1/clientloop.c ---- openssh-7.7p1/clientloop.c.fips 2018-08-08 10:08:40.769719527 +0200 -+++ openssh-7.7p1/clientloop.c 2018-08-08 10:08:40.822719973 +0200 -@@ -1978,7 +1978,8 @@ key_accepted_by_hostkeyalgs(const struct - { - const char *ktype = sshkey_ssh_name(key); - const char *hostkeyalgs = options.hostkeyalgorithms != NULL ? -- options.hostkeyalgorithms : KEX_DEFAULT_PK_ALG; -+ options.hostkeyalgorithms : (FIPS_mode() ? -+ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG); - - if (key == NULL || key->type == KEY_UNSPEC) - return 0; -diff -up openssh-7.7p1/dh.h.fips openssh-7.7p1/dh.h ---- openssh-7.7p1/dh.h.fips 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/dh.h 2018-08-08 10:08:40.822719973 +0200 -@@ -51,6 +51,7 @@ u_int dh_estimate(int); - * Miniumum increased in light of DH precomputation attacks. - */ - #define DH_GRP_MIN 2048 -+#define DH_GRP_MIN_FIPS 2048 - #define DH_GRP_MAX 8192 +diff -up openssh-8.0p1/dh.c.fips openssh-8.0p1/dh.c +--- openssh-8.0p1/dh.c.fips 2019-04-18 00:52:57.000000000 +0200 ++++ openssh-8.0p1/dh.c 2019-07-23 14:55:45.401526401 +0200 +@@ -152,6 +152,12 @@ choose_dh(int min, int wantbits, int max + int best, bestcount, which, linenum; + struct dhgroup dhg; - /* -diff -up openssh-7.7p1/entropy.c.fips openssh-7.7p1/entropy.c ---- openssh-7.7p1/entropy.c.fips 2018-08-08 10:08:40.698718928 +0200 -+++ openssh-7.7p1/entropy.c 2018-08-08 10:08:40.822719973 +0200 -@@ -217,6 +217,9 @@ seed_rng(void) - fatal("OpenSSL version mismatch. Built against %lx, you " - "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay()); - -+ /* clean the PRNG status when exiting the program */ -+ atexit(RAND_cleanup); ++ if (FIPS_mode()) { ++ logit("Using arbitrary primes is not allowed in FIPS mode." ++ " Falling back to known groups."); ++ return (dh_new_group_fallback(max)); ++ } + - #ifndef OPENSSL_PRNG_ONLY - if (RAND_status() == 1) { - debug3("RNG is ready, skipping seeding"); -diff -up openssh-7.7p1/kex.c.fips openssh-7.7p1/kex.c ---- openssh-7.7p1/kex.c.fips 2018-08-08 10:08:40.815719915 +0200 -+++ openssh-7.7p1/kex.c 2018-08-08 10:11:24.109081924 +0200 -@@ -35,6 +35,7 @@ - #ifdef WITH_OPENSSL - #include - #include -+#include - #endif - - #include "ssh2.h" -@@ -122,6 +123,26 @@ static const struct kexalg kexalgs[] = { - { NULL, -1, -1, -1}, - }; + if ((f = fopen(_PATH_DH_MODULI, "r")) == NULL) { + logit("WARNING: could not open %s (%s), using fixed modulus", + _PATH_DH_MODULI, strerror(errno)); +@@ -489,4 +495,38 @@ dh_estimate(int bits) + return 8192; + } -+static const struct kexalg kexalgs_fips[] = { -+ { KEX_DH14_SHA256, KEX_DH_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, -+ { KEX_DH16_SHA512, KEX_DH_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, -+ { KEX_DH18_SHA512, KEX_DH_GRP18_SHA512, 0, SSH_DIGEST_SHA512 }, -+#ifdef HAVE_EVP_SHA256 -+ { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, -+#endif -+#ifdef OPENSSL_HAS_ECC -+ { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, -+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, -+ { KEX_ECDH_SHA2_NISTP384, KEX_ECDH_SHA2, NID_secp384r1, -+ SSH_DIGEST_SHA384 }, -+# ifdef OPENSSL_HAS_NISTP521 -+ { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, -+ SSH_DIGEST_SHA512 }, -+# endif -+#endif -+ { NULL, -1, -1, -1}, -+}; ++/* ++ * Compares the received DH parameters with known-good groups, ++ * which might be either from group14, group16 or group18. ++ */ ++int ++dh_is_known_group(const DH *dh) ++{ ++ const BIGNUM *p, *g; ++ const BIGNUM *known_p, *known_g; ++ DH *known = NULL; ++ int bits = 0, rv = 0; + - char * - kex_alg_list(char sep) - { -@@ -129,7 +150,7 @@ kex_alg_list(char sep) - size_t nlen, rlen = 0; - const struct kexalg *k; - -- for (k = kexalgs; k->name != NULL; k++) { -+ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) { - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(k->name); -@@ -149,7 +170,7 @@ kex_alg_by_name(const char *name) - { - const struct kexalg *k; - -- for (k = kexalgs; k->name != NULL; k++) { -+ for (k = (FIPS_mode() ? kexalgs_fips : kexalgs); k->name != NULL; k++) { - if (strcmp(k->name, name) == 0) - return k; - #ifdef GSSAPI -@@ -175,7 +196,10 @@ kex_names_valid(const char *names) ++ DH_get0_pqg(dh, &p, NULL, &g); ++ bits = BN_num_bits(p); ++ ++ if (bits <= 3072) { ++ known = dh_new_group14(); ++ } else if (bits <= 6144) { ++ known = dh_new_group16(); ++ } else { ++ known = dh_new_group18(); ++ } ++ ++ DH_get0_pqg(known, &known_p, NULL, &known_g); ++ ++ if (BN_cmp(g, known_g) == 0 && ++ BN_cmp(p, known_p) == 0) { ++ rv = 1; ++ } ++ ++ DH_free(known); ++ return rv; ++} ++ + #endif /* WITH_OPENSSL */ +diff -up openssh-8.0p1/dh.h.fips openssh-8.0p1/dh.h +--- openssh-8.0p1/dh.h.fips 2019-04-18 00:52:57.000000000 +0200 ++++ openssh-8.0p1/dh.h 2019-07-23 14:55:45.401526401 +0200 +@@ -43,6 +43,7 @@ DH *dh_new_group_fallback(int); + + int dh_gen_key(DH *, int); + int dh_pub_is_valid(const DH *, const BIGNUM *); ++int dh_is_known_group(const DH *); + + u_int dh_estimate(int); + +diff -up openssh-8.0p1/kex.c.fips openssh-8.0p1/kex.c +--- openssh-8.0p1/kex.c.fips 2019-07-23 14:55:45.395526340 +0200 ++++ openssh-8.0p1/kex.c 2019-07-23 14:55:45.402526411 +0200 +@@ -199,7 +199,10 @@ kex_names_valid(const char *names) for ((p = strsep(&cp, ",")); p && *p != '\0'; (p = strsep(&cp, ","))) { if (kex_alg_by_name(p) == NULL) { @@ -180,238 +92,108 @@ diff -up openssh-7.7p1/kex.c.fips openssh-7.7p1/kex.c free(s); return 0; } -diff -up openssh-7.7p1/kexgexc.c.fips openssh-7.7p1/kexgexc.c ---- openssh-7.7p1/kexgexc.c.fips 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/kexgexc.c 2018-08-08 10:08:40.822719973 +0200 +diff -up openssh-8.0p1/kexgexc.c.fips openssh-8.0p1/kexgexc.c +--- openssh-8.0p1/kexgexc.c.fips 2019-04-18 00:52:57.000000000 +0200 ++++ openssh-8.0p1/kexgexc.c 2019-07-23 14:55:45.402526411 +0200 @@ -28,6 +28,7 @@ #ifdef WITH_OPENSSL -+#include ++#include #include #include -@@ -63,7 +64,7 @@ kexgex_client(struct ssh *ssh) - - nbits = dh_estimate(kex->dh_need * 8); - -- kex->min = DH_GRP_MIN; -+ kex->min = FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN; - kex->max = DH_GRP_MAX; - kex->nbits = nbits; - if (datafellows & SSH_BUG_DHGEX_LARGE) -diff -up openssh-7.7p1/kexgexs.c.fips openssh-7.7p1/kexgexs.c ---- openssh-7.7p1/kexgexs.c.fips 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/kexgexs.c 2018-08-08 10:08:40.823719982 +0200 -@@ -82,9 +82,9 @@ input_kex_dh_gex_request(int type, u_int - kex->nbits = nbits; - kex->min = min; - kex->max = max; -- min = MAXIMUM(DH_GRP_MIN, min); -+ min = MAXIMUM(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, min); - max = MINIMUM(DH_GRP_MAX, max); -- nbits = MAXIMUM(DH_GRP_MIN, nbits); -+ nbits = MAXIMUM(FIPS_mode() ? DH_GRP_MIN_FIPS : DH_GRP_MIN, nbits); - nbits = MINIMUM(DH_GRP_MAX, nbits); - - if (kex->max < kex->min || kex->nbits < kex->min || -diff -up openssh-7.7p1/mac.c.fips openssh-7.7p1/mac.c ---- openssh-7.7p1/mac.c.fips 2018-08-08 10:08:40.815719915 +0200 -+++ openssh-7.7p1/mac.c 2018-08-08 10:11:56.915352642 +0200 -@@ -27,6 +27,8 @@ - - #include - -+#include -+ - #include - #include - -@@ -54,7 +56,7 @@ struct macalg { - int etm; /* Encrypt-then-MAC */ - }; - --static const struct macalg macs[] = { -+static const struct macalg all_macs[] = { - /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ - { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, - { "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 }, -@@ -82,6 +84,24 @@ static const struct macalg macs[] = { - { NULL, 0, 0, 0, 0, 0, 0 } - }; - -+static const struct macalg fips_macs[] = { -+ /* Encrypt-and-MAC (encrypt-and-authenticate) variants */ -+ { "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, -+#ifdef HAVE_EVP_SHA256 -+ { "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 }, -+ { "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, -+#endif -+ -+ /* Encrypt-then-MAC variants */ -+ { "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 }, -+#ifdef HAVE_EVP_SHA256 -+ { "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 }, -+ { "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 }, -+#endif -+ -+ { NULL, 0, 0, 0, 0, 0, 0 } -+}; -+ - /* Returns a list of supported MACs separated by the specified char. */ - char * - mac_alg_list(char sep) -@@ -90,7 +110,7 @@ mac_alg_list(char sep) - size_t nlen, rlen = 0; - const struct macalg *m; - -- for (m = macs; m->name != NULL; m++) { -+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { - if (ret != NULL) - ret[rlen++] = sep; - nlen = strlen(m->name); -@@ -129,7 +149,7 @@ mac_setup(struct sshmac *mac, char *name - { - const struct macalg *m; - -- for (m = macs; m->name != NULL; m++) { -+ for (m = FIPS_mode() ? fips_macs : all_macs; m->name != NULL; m++) { - if (strcmp(name, m->name) != 0) - continue; - if (mac != NULL) -diff -up openssh-7.7p1/Makefile.in.fips openssh-7.7p1/Makefile.in ---- openssh-7.7p1/Makefile.in.fips 2018-08-08 10:08:40.815719915 +0200 -+++ openssh-7.7p1/Makefile.in 2018-08-08 10:08:40.823719982 +0200 -@@ -179,25 +179,25 @@ libssh.a: $(LIBSSH_OBJS) - $(RANLIB) $@ - - ssh$(EXEEXT): $(LIBCOMPAT) libssh.a $(SSHOBJS) -- $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHLIBS) $(LIBS) $(GSSLIBS) -+ $(LD) -o $@ $(SSHOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHLIBS) $(LIBS) $(GSSLIBS) - - sshd$(EXEEXT): libssh.a $(LIBCOMPAT) $(SSHDOBJS) -- $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) -+ $(LD) -o $@ $(SSHDOBJS) $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(SSHDLIBS) $(LIBS) $(GSSLIBS) $(K5LIBS) - - scp$(EXEEXT): $(LIBCOMPAT) libssh.a scp.o progressmeter.o - $(LD) -o $@ scp.o progressmeter.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) - - ssh-add$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-add.o -- $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-add.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o -- $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-agent.o ssh-pkcs11-client.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o -- $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o -- $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -+ $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat -lfipscheck $(LIBS) - - ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o - $(LD) -o $@ ssh-pkcs11-helper.o ssh-pkcs11.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) -@@ -215,7 +215,7 @@ ssh-cavs$(EXEEXT): $(LIBCOMPAT) libssh.a - $(LD) -o $@ ssh-cavs.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) - - ssh-keyscan$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keyscan.o -- $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh $(LIBS) -+ $(LD) -o $@ ssh-keyscan.o $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lfipscheck $(LIBS) +@@ -113,6 +114,10 @@ input_kex_dh_gex_group(int type, u_int32 + r = SSH_ERR_ALLOC_FAIL; + goto out; + } ++ if (FIPS_mode() && dh_is_known_group(kex->dh) == 0) { ++ r = SSH_ERR_INVALID_ARGUMENT; ++ goto out; ++ } + p = g = NULL; /* belong to kex->dh now */ - sftp-server$(EXEEXT): $(LIBCOMPAT) libssh.a sftp.o sftp-common.o sftp-server.o sftp-server-main.o - $(LD) -o $@ sftp-server.o sftp-common.o sftp-server-main.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) -diff -up openssh-7.7p1/myproposal.h.fips openssh-7.7p1/myproposal.h ---- openssh-7.7p1/myproposal.h.fips 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/myproposal.h 2018-08-08 10:08:40.823719982 +0200 -@@ -114,6 +114,14 @@ + /* generate and send 'e', client DH public key */ +diff -up openssh-8.0p1/myproposal.h.fips openssh-8.0p1/myproposal.h +--- openssh-8.0p1/myproposal.h.fips 2019-04-18 00:52:57.000000000 +0200 ++++ openssh-8.0p1/myproposal.h 2019-07-23 14:55:45.402526411 +0200 +@@ -111,6 +111,20 @@ "rsa-sha2-256," \ "ssh-rsa" +#define KEX_FIPS_PK_ALG \ -+ HOSTKEY_ECDSA_CERT_METHODS \ ++ "ecdsa-sha2-nistp256-cert-v01@openssh.com," \ ++ "ecdsa-sha2-nistp384-cert-v01@openssh.com," \ ++ "ecdsa-sha2-nistp521-cert-v01@openssh.com," \ ++ "rsa-sha2-512-cert-v01@openssh.com," \ ++ "rsa-sha2-256-cert-v01@openssh.com," \ + "ssh-rsa-cert-v01@openssh.com," \ -+ HOSTKEY_ECDSA_METHODS \ ++ "ecdsa-sha2-nistp256," \ ++ "ecdsa-sha2-nistp384," \ ++ "ecdsa-sha2-nistp521," \ + "rsa-sha2-512," \ + "rsa-sha2-256," \ + "ssh-rsa" + - /* the actual algorithms */ - - #define KEX_SERVER_ENCRYPT \ -@@ -137,6 +145,38 @@ + #define KEX_SERVER_ENCRYPT \ + "chacha20-poly1305@openssh.com," \ + "aes128-ctr,aes192-ctr,aes256-ctr," \ +@@ -134,6 +142,27 @@ #define KEX_CLIENT_MAC KEX_SERVER_MAC +#define KEX_FIPS_ENCRYPT \ + "aes128-ctr,aes192-ctr,aes256-ctr," \ + "aes128-cbc,3des-cbc," \ -+ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se" \ -+ AESGCM_CIPHER_MODES -+#ifdef HAVE_EVP_SHA256 -+# define KEX_DEFAULT_KEX_FIPS \ -+ KEX_ECDH_METHODS \ -+ KEX_SHA2_METHODS \ ++ "aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se," \ ++ "aes128-gcm@openssh.com,aes256-gcm@openssh.com" ++#define KEX_DEFAULT_KEX_FIPS \ ++ "ecdh-sha2-nistp256," \ ++ "ecdh-sha2-nistp384," \ ++ "ecdh-sha2-nistp521," \ ++ "diffie-hellman-group-exchange-sha256," \ ++ "diffie-hellman-group16-sha512," \ ++ "diffie-hellman-group18-sha512," \ + "diffie-hellman-group14-sha256" -+# define KEX_FIPS_MAC \ ++#define KEX_FIPS_MAC \ + "hmac-sha1," \ + "hmac-sha2-256," \ + "hmac-sha2-512," \ + "hmac-sha1-etm@openssh.com," \ + "hmac-sha2-256-etm@openssh.com," \ + "hmac-sha2-512-etm@openssh.com" -+#else -+# ifdef OPENSSL_HAS_NISTP521 -+# define KEX_DEFAULT_KEX_FIPS \ -+ "ecdh-sha2-nistp256," \ -+ "ecdh-sha2-nistp384," \ -+ "ecdh-sha2-nistp521" -+# else -+# define KEX_DEFAULT_KEX_FIPS \ -+ "ecdh-sha2-nistp256," \ -+ "ecdh-sha2-nistp384" -+# endif -+#define KEX_FIPS_MAC \ -+ "hmac-sha1" -+#endif + - #else /* WITH_OPENSSL */ - - #define KEX_SERVER_KEX \ -diff -up openssh-7.7p1/readconf.c.fips openssh-7.7p1/readconf.c ---- openssh-7.7p1/readconf.c.fips 2018-08-08 10:08:40.769719527 +0200 -+++ openssh-7.7p1/readconf.c 2018-08-08 10:08:40.824719990 +0200 -@@ -2081,17 +2081,18 @@ fill_default_options(Options * options) - all_mac = mac_alg_list(','); - all_kex = kex_alg_list(','); + /* Not a KEX value, but here so all the algorithm defaults are together */ + #define SSH_ALLOWED_CA_SIGALGS \ + "ecdsa-sha2-nistp256," \ +diff -up openssh-8.0p1/readconf.c.fips openssh-8.0p1/readconf.c +--- openssh-8.0p1/readconf.c.fips 2019-07-23 14:55:45.334525723 +0200 ++++ openssh-8.0p1/readconf.c 2019-07-23 14:55:45.402526411 +0200 +@@ -2179,11 +2179,16 @@ fill_default_options(Options * options) all_key = sshkey_alg_list(0, 0, 1, ','); --#define ASSEMBLE(what, defaults, all) \ -+#define ASSEMBLE(what, defaults, fips_defaults, all) \ + all_sig = sshkey_alg_list(0, 1, 1, ','); + /* remove unsupported algos from default lists */ +- def_cipher = match_filter_whitelist(KEX_CLIENT_ENCRYPT, all_cipher); +- def_mac = match_filter_whitelist(KEX_CLIENT_MAC, all_mac); +- def_kex = match_filter_whitelist(KEX_CLIENT_KEX, all_kex); +- def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key); +- def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig); ++ def_cipher = match_filter_whitelist((FIPS_mode() ? ++ KEX_FIPS_ENCRYPT : KEX_CLIENT_ENCRYPT), all_cipher); ++ def_mac = match_filter_whitelist((FIPS_mode() ? ++ KEX_FIPS_MAC : KEX_CLIENT_MAC), all_mac); ++ def_kex = match_filter_whitelist((FIPS_mode() ? ++ KEX_DEFAULT_KEX_FIPS : KEX_CLIENT_KEX), all_kex); ++ def_key = match_filter_whitelist((FIPS_mode() ? ++ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), all_key); ++ def_sig = match_filter_whitelist((FIPS_mode() ? ++ KEX_FIPS_PK_ALG : SSH_ALLOWED_CA_SIGALGS), all_sig); + #define ASSEMBLE(what, defaults, all) \ do { \ if ((r = kex_assemble_names(&options->what, \ -- defaults, all)) != 0) \ -+ (FIPS_mode() ? fips_defaults : defaults), \ -+ all)) != 0) \ - fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \ - } while (0) -- ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher); -- ASSEMBLE(macs, KEX_SERVER_MAC, all_mac); -- ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex); -- ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key); -- ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key); -+ ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher); -+ ASSEMBLE(macs, KEX_SERVER_MAC, KEX_FIPS_MAC, all_mac); -+ ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, KEX_DEFAULT_KEX_FIPS, all_kex); -+ ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); -+ ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); - #undef ASSEMBLE - free(all_cipher); - free(all_mac); -diff -up openssh-7.7p1/sandbox-seccomp-filter.c.fips openssh-7.7p1/sandbox-seccomp-filter.c ---- openssh-7.7p1/sandbox-seccomp-filter.c.fips 2018-08-08 10:08:40.794719737 +0200 -+++ openssh-7.7p1/sandbox-seccomp-filter.c 2018-08-08 10:08:40.824719990 +0200 +diff -up openssh-8.0p1/sandbox-seccomp-filter.c.fips openssh-8.0p1/sandbox-seccomp-filter.c +--- openssh-8.0p1/sandbox-seccomp-filter.c.fips 2019-07-23 14:55:45.373526117 +0200 ++++ openssh-8.0p1/sandbox-seccomp-filter.c 2019-07-23 14:55:45.402526411 +0200 @@ -137,6 +137,9 @@ static const struct sock_filter preauth_ #ifdef __NR_open SC_DENY(__NR_open, EACCES), @@ -422,168 +204,140 @@ diff -up openssh-7.7p1/sandbox-seccomp-filter.c.fips openssh-7.7p1/sandbox-secco #ifdef __NR_openat SC_DENY(__NR_openat, EACCES), #endif -diff -up openssh-7.7p1/servconf.c.fips openssh-7.7p1/servconf.c ---- openssh-7.7p1/servconf.c.fips 2018-08-08 10:08:40.778719603 +0200 -+++ openssh-7.7p1/servconf.c 2018-08-08 10:08:40.824719990 +0200 -@@ -196,17 +196,18 @@ option_clear_or_none(const char *o) - all_mac = mac_alg_list(','); - all_kex = kex_alg_list(','); +diff -up openssh-8.0p1/servconf.c.fips openssh-8.0p1/servconf.c +--- openssh-8.0p1/servconf.c.fips 2019-07-23 14:55:45.361525996 +0200 ++++ openssh-8.0p1/servconf.c 2019-07-23 14:55:45.403526421 +0200 +@@ -208,11 +208,16 @@ assemble_algorithms(ServerOptions *o) all_key = sshkey_alg_list(0, 0, 1, ','); --#define ASSEMBLE(what, defaults, all) \ -+#define ASSEMBLE(what, defaults, fips_defaults, all) \ + all_sig = sshkey_alg_list(0, 1, 1, ','); + /* remove unsupported algos from default lists */ +- def_cipher = match_filter_whitelist(KEX_SERVER_ENCRYPT, all_cipher); +- def_mac = match_filter_whitelist(KEX_SERVER_MAC, all_mac); +- def_kex = match_filter_whitelist(KEX_SERVER_KEX, all_kex); +- def_key = match_filter_whitelist(KEX_DEFAULT_PK_ALG, all_key); +- def_sig = match_filter_whitelist(SSH_ALLOWED_CA_SIGALGS, all_sig); ++ def_cipher = match_filter_whitelist((FIPS_mode() ? ++ KEX_FIPS_ENCRYPT : KEX_SERVER_ENCRYPT), all_cipher); ++ def_mac = match_filter_whitelist((FIPS_mode() ? ++ KEX_FIPS_MAC : KEX_SERVER_MAC), all_mac); ++ def_kex = match_filter_whitelist((FIPS_mode() ? ++ KEX_DEFAULT_KEX_FIPS : KEX_SERVER_KEX), all_kex); ++ def_key = match_filter_whitelist((FIPS_mode() ? ++ KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), all_key); ++ def_sig = match_filter_whitelist((FIPS_mode() ? ++ KEX_FIPS_PK_ALG : SSH_ALLOWED_CA_SIGALGS), all_sig); + #define ASSEMBLE(what, defaults, all) \ do { \ -- if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ -+ if ((r = kex_assemble_names(&o->what, (FIPS_mode() \ -+ ? fips_defaults : defaults), all)) != 0) \ - fatal("%s: %s: %s", __func__, #what, ssh_err(r)); \ - } while (0) -- ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, all_cipher); -- ASSEMBLE(macs, KEX_SERVER_MAC, all_mac); -- ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, all_kex); -- ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, all_key); -- ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, all_key); -- ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, all_key); -+ ASSEMBLE(ciphers, KEX_SERVER_ENCRYPT, KEX_FIPS_ENCRYPT, all_cipher); -+ ASSEMBLE(macs, KEX_SERVER_MAC, KEX_FIPS_MAC, all_mac); -+ ASSEMBLE(kex_algorithms, KEX_SERVER_KEX, KEX_DEFAULT_KEX_FIPS, all_kex); -+ ASSEMBLE(hostkeyalgorithms, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); -+ ASSEMBLE(hostbased_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); -+ ASSEMBLE(pubkey_key_types, KEX_DEFAULT_PK_ALG, KEX_FIPS_PK_ALG, all_key); - #undef ASSEMBLE - free(all_cipher); - free(all_mac); -diff -up openssh-7.7p1/ssh.c.fips openssh-7.7p1/ssh.c ---- openssh-7.7p1/ssh.c.fips 2018-08-08 10:08:40.811719881 +0200 -+++ openssh-7.7p1/ssh.c 2018-08-08 10:08:40.825719999 +0200 -@@ -76,6 +76,8 @@ + if ((r = kex_assemble_names(&o->what, defaults, all)) != 0) \ +diff -up openssh-8.0p1/ssh.c.fips openssh-8.0p1/ssh.c +--- openssh-8.0p1/ssh.c.fips 2019-07-23 14:55:45.378526168 +0200 ++++ openssh-8.0p1/ssh.c 2019-07-23 14:55:45.403526421 +0200 +@@ -76,6 +76,7 @@ #include #include #endif -+#include -+#include ++#include #include "openbsd-compat/openssl-compat.h" #include "openbsd-compat/sys-queue.h" -@@ -579,6 +581,14 @@ main(int ac, char **av) - sanitise_stdfd(); - - __progname = ssh_get_progname(av[0]); -+ SSLeay_add_all_algorithms(); -+ if (access("/etc/system-fips", F_OK) == 0) -+ if (! FIPSCHECK_verify(NULL, NULL)){ -+ if (FIPS_mode()) -+ fatal("FIPS integrity verification test failed."); -+ else -+ logit("FIPS integrity verification test failed."); -+ } - - #ifndef HAVE_SETPROCTITLE - /* Prepare for later setproctitle emulation */ -@@ -1045,7 +1055,6 @@ main(int ac, char **av) - host_arg = xstrdup(host); - - #ifdef WITH_OPENSSL -- OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - #endif - -@@ -1268,6 +1277,10 @@ main(int ac, char **av) - - seed_rng(); - +@@ -614,6 +626,10 @@ main(int ac, char **av) + dump_client_config(&options, host); + exit(0); + } ++ + if (FIPS_mode()) { -+ logit("FIPS mode initialized"); ++ debug("FIPS mode initialized"); + } -+ - if (options.user == NULL) - options.user = xstrdup(pw->pw_name); -diff -up openssh-7.7p1/sshconnect2.c.fips openssh-7.7p1/sshconnect2.c ---- openssh-7.7p1/sshconnect2.c.fips 2018-08-08 10:08:40.786719670 +0200 -+++ openssh-7.7p1/sshconnect2.c 2018-08-08 10:08:40.825719999 +0200 + /* Expand SecurityKeyProvider if it refers to an environment variable */ + if (options.sk_provider != NULL && *options.sk_provider == '$' && +diff -up openssh-8.0p1/sshconnect2.c.fips openssh-8.0p1/sshconnect2.c +--- openssh-8.0p1/sshconnect2.c.fips 2019-07-23 14:55:45.336525743 +0200 ++++ openssh-8.0p1/sshconnect2.c 2019-07-23 14:55:45.403526421 +0200 @@ -44,6 +44,8 @@ #include #endif -+#include ++#include + #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" -@@ -235,7 +237,8 @@ order_hostkeyalgs(char *host, struct soc - for (i = 0; i < options.num_system_hostfiles; i++) - load_hostkeys(hostkeys, hostname, options.system_hostfiles[i]); +@@ -198,36 +203,41 @@ ssh_kex2(struct ssh *ssh, char *host, st -- oavail = avail = xstrdup(KEX_DEFAULT_PK_ALG); -+ oavail = avail = xstrdup((FIPS_mode() -+ ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG)); - maxlen = strlen(avail) + 1; - first = xmalloc(maxlen); - last = xmalloc(maxlen); -@@ -290,21 +293,26 @@ ssh_kex2(char *host, struct sockaddr *ho - - #ifdef GSSAPI + #if defined(GSSAPI) && defined(WITH_OPENSSL) if (options.gss_keyex) { -- /* Add the GSSAPI mechanisms currently supported on this +- /* Add the GSSAPI mechanisms currently supported on this - * client to the key exchange algorithm proposal */ -- orig = options.kex_algorithms; +- orig = myproposal[PROPOSAL_KEX_ALGS]; - -- if (options.gss_trust_dns) -- gss_host = (char *)get_canonical_hostname(active_state, 1); -- else -- gss_host = host; +- if (options.gss_server_identity) { +- gss_host = xstrdup(options.gss_server_identity); +- } else if (options.gss_trust_dns) { +- gss_host = remote_hostname(ssh); +- /* Fall back to specified host if we are using proxy command +- * and can not use DNS on that socket */ +- if (strcmp(gss_host, "UNKNOWN") == 0) { +- free(gss_host); +- gss_host = xstrdup(host); +- } +- } else { +- gss_host = xstrdup(host); +- } - - gss = ssh_gssapi_client_mechanisms(gss_host, - options.gss_client_identity, options.gss_kex_algorithms); - if (gss) { - debug("Offering GSSAPI proposal: %s", gss); -- xasprintf(&options.kex_algorithms, +- 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); + 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 = options.kex_algorithms; ++ orig = myproposal[PROPOSAL_KEX_ALGS]; + -+ if (options.gss_trust_dns) -+ gss_host = (char *)get_canonical_hostname(active_state, 1); -+ else -+ gss_host = host; ++ if (options.gss_server_identity) { ++ gss_host = xstrdup(options.gss_server_identity); ++ } else if (options.gss_trust_dns) { ++ gss_host = remote_hostname(ssh); ++ /* Fall back to specified host if we are using proxy command ++ * and can not use DNS on that socket */ ++ if (strcmp(gss_host, "UNKNOWN") == 0) { ++ free(gss_host); ++ gss_host = xstrdup(host); ++ } ++ } else { ++ gss_host = xstrdup(host); ++ } + + gss = ssh_gssapi_client_mechanisms(gss_host, + options.gss_client_identity, options.gss_kex_algorithms); + if (gss) { + debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&options.kex_algorithms, ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], + "%s,%s", gss, orig); ++ ++ /* If we've got GSSAPI algorithms, then we also support the ++ * 'null' hostkey, as a last resort */ ++ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "%s,null", orig); + } } } #endif -@@ -322,14 +330,16 @@ ssh_kex2(char *host, struct sockaddr *ho - if (options.hostkeyalgorithms != NULL) { - all_key = sshkey_alg_list(0, 0, 1, ','); - if (kex_assemble_names(&options.hostkeyalgorithms, -- KEX_DEFAULT_PK_ALG, all_key) != 0) -+ (FIPS_mode() ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG), -+ all_key) != 0) - fatal("%s: kex_assemble_namelist", __func__); - free(all_key); - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - compat_pkalg_proposal(options.hostkeyalgorithms); - } else { - /* Enforce default */ -- options.hostkeyalgorithms = xstrdup(KEX_DEFAULT_PK_ALG); -+ options.hostkeyalgorithms = xstrdup((FIPS_mode() -+ ? KEX_FIPS_PK_ALG : KEX_DEFAULT_PK_ALG)); - /* Prefer algorithms that we already have keys for */ - myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = - compat_pkalg_proposal( -diff -up openssh-7.7p1/sshd.c.fips openssh-7.7p1/sshd.c ---- openssh-7.7p1/sshd.c.fips 2018-08-08 10:08:40.818719940 +0200 -+++ openssh-7.7p1/sshd.c 2018-08-08 10:08:40.826720007 +0200 +diff -up openssh-8.0p1/sshd.c.fips openssh-8.0p1/sshd.c +--- openssh-8.0p1/sshd.c.fips 2019-07-23 14:55:45.398526371 +0200 ++++ openssh-8.0p1/sshd.c 2019-07-23 14:55:45.403526421 +0200 @@ -66,6 +66,7 @@ #include #include @@ -592,55 +346,34 @@ diff -up openssh-7.7p1/sshd.c.fips openssh-7.7p1/sshd.c #include #include #include -@@ -77,6 +78,8 @@ +@@ -77,6 +78,7 @@ #include #include #include -+#include -+#include ++#include #include "openbsd-compat/openssl-compat.h" #endif -@@ -1534,6 +1537,18 @@ main(int ac, char **av) +@@ -1529,6 +1532,7 @@ main(int ac, char **av) #endif __progname = ssh_get_progname(av[0]); -+ SSLeay_add_all_algorithms(); -+ if (access("/etc/system-fips", F_OK) == 0) -+ if (! FIPSCHECK_verify(NULL, NULL)) { -+ openlog(__progname, LOG_PID, LOG_AUTHPRIV); -+ if (FIPS_mode()) { -+ syslog(LOG_CRIT, "FIPS integrity verification test failed."); -+ cleanup_exit(255); -+ } -+ else -+ syslog(LOG_INFO, "FIPS integrity verification test failed."); -+ closelog(); -+ } ++ OpenSSL_add_all_algorithms(); /* Save argv. Duplicate so setproctitle emulation doesn't clobber it */ saved_argc = ac; rexec_argc = ac; -@@ -1675,7 +1690,7 @@ main(int ac, char **av) - else - closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); - --#ifdef WITH_OPENSSL -+#if 0 /* FIPS */ - OpenSSL_add_all_algorithms(); - #endif - -@@ -1979,6 +1994,10 @@ main(int ac, char **av) +@@ -1992,6 +2007,10 @@ main(int ac, char **av) /* Reinitialize the log (because of the fork above). */ log_init(__progname, options.log_level, options.log_facility, log_stderr); + if (FIPS_mode()) { -+ logit("FIPS mode initialized"); ++ debug("FIPS mode initialized"); + } + /* Chdir to the root directory so that the current disk can be unmounted if desired. */ if (chdir("/") == -1) -@@ -2359,10 +2378,14 @@ do_ssh2_kex(void) +@@ -2382,10 +2401,14 @@ do_ssh2_kex(struct ssh *ssh) if (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]) == 0) orig = NULL; @@ -659,26 +392,26 @@ diff -up openssh-7.7p1/sshd.c.fips openssh-7.7p1/sshd.c if (gss && orig) xasprintf(&newstr, "%s,%s", gss, orig); -diff -up openssh-7.7p1/sshkey.c.fips openssh-7.7p1/sshkey.c ---- openssh-7.7p1/sshkey.c.fips 2018-08-08 10:08:40.818719940 +0200 -+++ openssh-7.7p1/sshkey.c 2018-08-08 10:08:40.826720007 +0200 +diff -up openssh-8.0p1/sshkey.c.fips openssh-8.0p1/sshkey.c +--- openssh-8.0p1/sshkey.c.fips 2019-07-23 14:55:45.398526371 +0200 ++++ openssh-8.0p1/sshkey.c 2019-07-23 14:55:45.404526431 +0200 @@ -34,6 +34,7 @@ #include #include #include -+#include ++#include #endif #include "crypto_api.h" @@ -57,6 +58,7 @@ + #define SSHKEY_INTERNAL #include "sshkey.h" - #include "sshkey-xmss.h" #include "match.h" +#include "log.h" + #include "ssh-sk.h" - #include "xmss_fast.h" - -@@ -1526,6 +1528,8 @@ rsa_generate_private_key(u_int bits, RSA + #ifdef WITH_XMSS +@@ -1591,6 +1593,8 @@ rsa_generate_private_key(u_int bits, RSA } if (!BN_set_word(f4, RSA_F4) || !RSA_generate_key_ex(private, bits, f4, NULL)) { @@ -687,13 +420,13 @@ diff -up openssh-7.7p1/sshkey.c.fips openssh-7.7p1/sshkey.c ret = SSH_ERR_LIBCRYPTO_ERROR; goto out; } -diff -up openssh-7.7p1/ssh-keygen.c.fips openssh-7.7p1/ssh-keygen.c ---- openssh-7.7p1/ssh-keygen.c.fips 2018-08-08 10:08:40.801719797 +0200 -+++ openssh-7.7p1/ssh-keygen.c 2018-08-08 10:08:40.827720016 +0200 -@@ -229,6 +229,12 @@ type_bits_valid(int type, const char *na - OPENSSL_DSA_MAX_MODULUS_BITS : OPENSSL_RSA_MAX_MODULUS_BITS; - if (*bitsp > maxbits) - fatal("key bits exceeds maximum %d", maxbits); +diff -up openssh-8.0p1/ssh-keygen.c.fips openssh-8.0p1/ssh-keygen.c +--- openssh-8.0p1/ssh-keygen.c.fips 2019-07-23 14:55:45.391526300 +0200 ++++ openssh-8.0p1/ssh-keygen.c 2019-07-23 14:57:54.118830056 +0200 +@@ -199,6 +199,12 @@ type_bits_valid(int type, const char *na + #endif + } + #ifdef WITH_OPENSSL + if (FIPS_mode()) { + if (type == KEY_DSA) + fatal("DSA keys are not allowed in FIPS mode"); @@ -703,3 +436,22 @@ diff -up openssh-7.7p1/ssh-keygen.c.fips openssh-7.7p1/ssh-keygen.c switch (type) { case KEY_DSA: if (*bitsp != 1024) +@@ -1029,9 +1035,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); ++ ++ /* Skip the keys that are not supported in FIPS mode */ ++ if (FIPS_mode() && (type == KEY_DSA || type == KEY_ED25519)) { ++ logit("Skipping %s key in FIPS mode", ++ key_types[i].key_type_display); ++ goto next; ++ } ++ + printf("%s ", key_types[i].key_type_display); + fflush(stdout); +- type = sshkey_type_from_name(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 --git a/openssh-7.7p1-gssapi-new-unique.patch b/openssh-7.7p1-gssapi-new-unique.patch index 7acc58ac23c1fab267a204354de19cc08ec59edd..506c79ac88ac743f1282c0d27c02a8d25ddff225 100644 --- a/openssh-7.7p1-gssapi-new-unique.patch +++ b/openssh-7.7p1-gssapi-new-unique.patch @@ -84,7 +84,7 @@ index a5a81ed2..63f877f2 100644 + /* There is at least one other ccache in collection + * we can switch to */ + krb5_cc_switch(ctx, ccache); -+ } else { ++ } else if (authctxt->krb5_ccname != NULL) { + /* Clean up the collection too */ + strncpy(krb5_ccname, authctxt->krb5_ccname, sizeof(krb5_ccname) - 10); + krb5_ccname_dir_start = strchr(krb5_ccname, ':') + 1; @@ -113,29 +113,12 @@ index a5a81ed2..63f877f2 100644 if (authctxt->krb5_user) { krb5_free_principal(authctxt->krb5_ctx, authctxt->krb5_user); authctxt->krb5_user = NULL; -@@ -237,36 +287,186 @@ krb5_cleanup_proc(Authctxt *authctxt) +@@ -237,36 +281,188 @@ krb5_cleanup_proc(Authctxt *authctxt) } } -#ifndef HEIMDAL --krb5_error_code --ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { -- int tmpfd, ret, oerrno; -- char ccname[40]; -- mode_t old_umask; - -- ret = snprintf(ccname, sizeof(ccname), -- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); -- if (ret < 0 || (size_t)ret >= sizeof(ccname)) -- return ENOMEM; -- -- old_umask = umask(0177); -- tmpfd = mkstemp(ccname + strlen("FILE:")); -- oerrno = errno; -- umask(old_umask); -- if (tmpfd == -1) { -- logit("mkstemp(): %.100s", strerror(oerrno)); -- return oerrno; ++ +#if !defined(HEIMDAL) +int +ssh_asprintf_append(char **dsc, const char *fmt, ...) { @@ -195,14 +178,13 @@ index a5a81ed2..63f877f2 100644 + continue; + } else { + p_o = strchr(p_n, '}') + 1; -+ p_o = '\0'; ++ *p_o = '\0'; + debug("%s: unsupported token %s in %s", __func__, p_n, template); + /* unknown token, fallback to the default */ + goto cleanup; + } - } - -- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { ++ } ++ + if (ssh_asprintf_append(&r, "%s", p_o) == -1) + goto cleanup; + @@ -216,7 +198,10 @@ index a5a81ed2..63f877f2 100644 + return -1; +} + -+krb5_error_code + krb5_error_code +-ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { +- int tmpfd, ret, oerrno; +- char ccname[40]; +ssh_krb5_get_cctemplate(krb5_context ctx, char **ccname) { + profile_t p; + int ret = 0; @@ -241,14 +226,27 @@ index a5a81ed2..63f877f2 100644 +ssh_krb5_cc_new_unique(krb5_context ctx, krb5_ccache *ccache, int *need_environment) { + int tmpfd, ret, oerrno, type_len; + char *ccname = NULL; -+ mode_t old_umask; + mode_t old_umask; + char *type = NULL, *colon = NULL; -+ + +- ret = snprintf(ccname, sizeof(ccname), +- "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); +- if (ret < 0 || (size_t)ret >= sizeof(ccname)) +- return ENOMEM; +- +- old_umask = umask(0177); +- tmpfd = mkstemp(ccname + strlen("FILE:")); +- oerrno = errno; +- umask(old_umask); +- if (tmpfd == -1) { +- logit("mkstemp(): %.100s", strerror(oerrno)); +- return oerrno; +- } + debug3("%s: called", __func__); + if (need_environment) + *need_environment = 0; + ret = ssh_krb5_get_cctemplate(ctx, &ccname); -+ if (ret || !ccname || options.kerberos_unique_ticket) { ++ if (ret || !ccname || options.kerberos_unique_ccache) { + /* Otherwise, go with the old method */ + if (ccname) + free(ccname); @@ -258,7 +256,8 @@ index a5a81ed2..63f877f2 100644 + "FILE:/tmp/krb5cc_%d_XXXXXXXXXX", geteuid()); + if (ret < 0) + return ENOMEM; -+ + +- if (fchmod(tmpfd,S_IRUSR | S_IWUSR) == -1) { + old_umask = umask(0177); + tmpfd = mkstemp(ccname + strlen("FILE:")); oerrno = errno; @@ -307,6 +306,7 @@ index a5a81ed2..63f877f2 100644 + if (krb5_cc_support_switch(ctx, type)) { + debug3("%s: calling cc_new_unique(%s)", __func__, ccname); + ret = krb5_cc_new_unique(ctx, type, NULL, ccache); ++ free(type); + if (ret) + return ret; + @@ -317,6 +317,7 @@ index a5a81ed2..63f877f2 100644 + * it is already unique from above or the type does not support + * collections + */ ++ free(type); + debug3("%s: calling cc_resolve(%s)", __func__, ccname); + return (krb5_cc_resolve(ctx, ccname, ccache)); + } @@ -335,19 +336,19 @@ index 29491df9..fdab5040 100644 #endif struct sshbuf *loginmsg; -@@ -243,6 +244,6 @@ int sys_auth_passwd(struct ssh *, const char *); +@@ -238,7 +239,7 @@ int sys_auth_passwd(struct ssh *, const char *); + int sys_auth_passwd(struct ssh *, const char *); #if defined(KRB5) && !defined(HEIMDAL) - #include -krb5_error_code ssh_krb5_cc_gen(krb5_context, krb5_ccache *); +krb5_error_code ssh_krb5_cc_new_unique(krb5_context, krb5_ccache *, int *); #endif - #endif -diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c -index 795992d9..0623a107 100644 ---- a/gss-serv-krb5.c -+++ b/gss-serv-krb5.c -@@ -114,7 +114,7 @@ ssh_gssapi_krb5_userok(ssh_gssapi_client *client, char *name) + + #endif /* AUTH_H */ +diff -up openssh-7.9p1/gss-serv-krb5.c.ccache_name openssh-7.9p1/gss-serv-krb5.c +--- openssh-7.9p1/gss-serv-krb5.c.ccache_name 2019-03-01 15:17:42.708611802 +0100 ++++ openssh-7.9p1/gss-serv-krb5.c 2019-03-01 15:17:42.713611844 +0100 +@@ -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 */ @@ -356,12 +357,9 @@ index 795992d9..0623a107 100644 ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) { krb5_ccache ccache; -@@ -121,16 +121,17 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - krb5_error_code problem; - krb5_principal princ; +@@ -276,14 +276,15 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl OM_uint32 maj_status, min_status; -- const char *new_ccname, *new_cctype; -+ int len; + const char *new_ccname, *new_cctype; const char *errmsg; + int set_env = 0; @@ -377,7 +375,7 @@ index 795992d9..0623a107 100644 #ifdef HEIMDAL # ifdef HAVE_KRB5_CC_NEW_UNIQUE -@@ -144,14 +145,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) +@@ -297,14 +298,14 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl krb5_get_err_text(krb_context, problem)); # endif krb5_free_error_message(krb_context, errmsg); @@ -396,7 +394,7 @@ index 795992d9..0623a107 100644 } #endif /* #ifdef HEIMDAL */ -@@ -160,7 +161,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) +@@ -313,7 +314,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl errmsg = krb5_get_error_message(krb_context, problem); logit("krb5_parse_name(): %.100s", errmsg); krb5_free_error_message(krb_context, errmsg); @@ -405,7 +403,7 @@ index 795992d9..0623a107 100644 } if ((problem = krb5_cc_initialize(krb_context, ccache, princ))) { -@@ -169,7 +170,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) +@@ -322,7 +323,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl krb5_free_error_message(krb_context, errmsg); krb5_free_principal(krb_context, princ); krb5_cc_destroy(krb_context, ccache); @@ -414,7 +412,7 @@ index 795992d9..0623a107 100644 } krb5_free_principal(krb_context, princ); -@@ -178,37 +179,27 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) +@@ -331,32 +332,21 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl client->creds, ccache))) { logit("gss_krb5_copy_ccache() failed"); krb5_cc_destroy(krb_context, ccache); @@ -422,30 +420,29 @@ index 795992d9..0623a107 100644 + return 0; } -- new_cctype = krb5_cc_get_type(krb_context, ccache); -- new_ccname = krb5_cc_get_name(krb_context, ccache); + new_cctype = krb5_cc_get_type(krb_context, ccache); + new_ccname = krb5_cc_get_name(krb_context, ccache); - - client->store.envvar = "KRB5CCNAME"; -#ifdef USE_CCAPI - xasprintf(&client->store.envval, "API:%s", new_ccname); +- client->store.filename = NULL; -#else - if (new_ccname[0] == ':') - new_ccname++; -- xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); + xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); - if (strcmp(new_cctype, "DIR") == 0) { - char *p; - p = strrchr(client->store.envval, '/'); - if (p) - *p = '\0'; -- } --#endif ++ + if (set_env) { -+ const char *filename = krb5_cc_get_name(krb_context, ccache); + client->store.envvar = "KRB5CCNAME"; -+ len = strlen(filename) + 6; -+ client->store.envval = xmalloc(len); -+ snprintf(client->store.envval, len, "FILE:%s", filename); -+ } + } + if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) + client->store.filename = xstrdup(new_ccname); +-#endif #ifdef USE_PAM - if (options.use_pam) @@ -453,7 +450,7 @@ index 795992d9..0623a107 100644 do_pam_putenv(client->store.envvar, client->store.envval); #endif - krb5_cc_close(krb_context, ccache); +@@ -361,7 +355,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl client->store.data = krb_context; @@ -483,16 +480,26 @@ index 6cae720e..16e55cbc 100644 + return 0; } - /* This allows GSSAPI methods to do things to the childs environment based -diff --git a/servconf.c b/servconf.c -index cb578658..a6e01df2 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -122,6 +122,7 @@ initialize_server_options(ServerOptions *options) + /* This allows GSSAPI methods to do things to the child's environment based +@@ -498,9 +500,7 @@ ssh_gssapi_rekey_creds() { + char *envstr; + #endif + +- if (gssapi_client.store.filename == NULL && +- gssapi_client.store.envval == NULL && +- gssapi_client.store.envvar == NULL) ++ if (gssapi_client.store.envval == NULL) + return; + + ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); +diff -up openssh-7.9p1/servconf.c.ccache_name openssh-7.9p1/servconf.c +--- openssh-7.9p1/servconf.c.ccache_name 2019-03-01 15:17:42.704611768 +0100 ++++ openssh-7.9p1/servconf.c 2019-03-01 15:17:42.713611844 +0100 +@@ -123,6 +123,7 @@ initialize_server_options(ServerOptions options->kerberos_or_local_passwd = -1; options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; -+ options->kerberos_unique_ticket = -1; ++ options->kerberos_unique_ccache = -1; options->gss_authentication=-1; options->gss_keyex = -1; options->gss_cleanup_creds = -1; @@ -500,8 +507,8 @@ index cb578658..a6e01df2 100644 options->kerberos_ticket_cleanup = 1; if (options->kerberos_get_afs_token == -1) options->kerberos_get_afs_token = 0; -+ if (options->kerberos_unique_ticket == -1) -+ options->kerberos_unique_ticket = 0; ++ if (options->kerberos_unique_ccache == -1) ++ options->kerberos_unique_ccache = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; if (options->gss_keyex == -1) @@ -510,7 +517,7 @@ index cb578658..a6e01df2 100644 sRhostsRSAAuthentication, sRSAAuthentication, sKerberosAuthentication, sKerberosOrLocalPasswd, sKerberosTicketCleanup, - sKerberosGetAFSToken, sChallengeResponseAuthentication, -+ sKerberosGetAFSToken, sKerberosUniqueTicket, ++ sKerberosGetAFSToken, sKerberosUniqueCCache, + sChallengeResponseAuthentication, sPasswordAuthentication, sKbdInteractiveAuthentication, sListenAddress, sAddressFamily, @@ -519,13 +526,13 @@ index cb578658..a6e01df2 100644 #else { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, #endif -+ { "kerberosuniqueticket", sKerberosUniqueTicket, SSHCFG_GLOBAL }, ++ { "kerberosuniqueccache", sKerberosUniqueCCache, SSHCFG_GLOBAL }, #else { "kerberosauthentication", sUnsupported, SSHCFG_ALL }, { "kerberosorlocalpasswd", sUnsupported, SSHCFG_GLOBAL }, { "kerberosticketcleanup", sUnsupported, SSHCFG_GLOBAL }, { "kerberosgetafstoken", sUnsupported, SSHCFG_GLOBAL }, -+ { "kerberosuniqueticket", sUnsupported, SSHCFG_GLOBAL }, ++ { "kerberosuniqueccache", sUnsupported, SSHCFG_GLOBAL }, #endif { "kerberostgtpassing", sUnsupported, SSHCFG_GLOBAL }, { "afstokenpassing", sUnsupported, SSHCFG_GLOBAL }, @@ -533,8 +540,8 @@ index cb578658..a6e01df2 100644 intptr = &options->kerberos_get_afs_token; goto parse_flag; -+ case sKerberosUniqueTicket: -+ intptr = &options->kerberos_unique_ticket; ++ case sKerberosUniqueCCache: ++ intptr = &options->kerberos_unique_ccache; + goto parse_flag; + case sGssAuthentication: @@ -544,7 +551,7 @@ index cb578658..a6e01df2 100644 # ifdef USE_AFS dump_cfg_fmtint(sKerberosGetAFSToken, o->kerberos_get_afs_token); # endif -+ dump_cfg_fmtint(sKerberosUniqueTicket, o->kerberos_unique_ticket); ++ dump_cfg_fmtint(sKerberosUniqueCCache, o->kerberos_unique_ccache); #endif #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); @@ -556,7 +563,7 @@ index db8362c6..4fa42d64 100644 * file on logout. */ int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ -+ int kerberos_unique_ticket; /* If true, the aquired ticket will ++ int kerberos_unique_ccache; /* If true, the acquired ticket will + * be stored in per-session ccache */ int gss_authentication; /* If true, permit GSSAPI authentication */ int gss_keyex; /* If true, permit GSSAPI key exchange */ @@ -567,7 +574,7 @@ index 85df6a27..480a5ead 100644 +++ b/session.c @@ -1033,7 +1033,8 @@ do_setup_env(struct ssh *ssh, Session *s, const char *shell) /* Allow any GSSAPI methods that we've used to alter - * the childs environment as they see fit + * the child's environment as they see fit */ - ssh_gssapi_do_child(&env, &envsize); + if (s->authctxt->krb5_set_env) @@ -588,14 +595,6 @@ diff --git a/ssh-gss.h b/ssh-gss.h index 6593e422..245178af 100644 --- a/ssh-gss.h +++ b/ssh-gss.h -@@ -62,7 +62,6 @@ - #define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" - - typedef struct { -- char *filename; - char *envvar; - char *envval; - struct passwd *owner; @@ -83,7 +82,7 @@ typedef struct ssh_gssapi_mech_struct { int (*dochild) (ssh_gssapi_client *); int (*userok) (ssh_gssapi_client *, char *); @@ -631,16 +630,18 @@ diff --git a/sshd_config.5 b/sshd_config.5 index c0683d4a..2349f477 100644 --- a/sshd_config.5 +++ b/sshd_config.5 -@@ -860,6 +860,12 @@ Specifies whether to automatically destroy the user's ticket cache +@@ -860,6 +860,14 @@ Specifies whether to automatically destroy the user's ticket cache file on logout. The default is .Cm yes . -+.It Cm KerberosUniqueTicket -+Specifies whether to store the aquired tickets in the per-session credential -+cache or whether to use per-user credential cache, which might overwrite -+tickets aquired in different sessions of the same user. -+The default is -+.Cm no . ++.It Cm KerberosUniqueCCache ++Specifies whether to store the acquired tickets in the per-session credential ++cache under /tmp/ or whether to use per-user credential cache as configured in ++.Pa /etc/krb5.conf . ++The default value ++.Cm no ++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. diff --git a/openssh-7.7p1.patch b/openssh-7.7p1.patch index 99a44112c82ce09cc3f8232a2d0114ac69bed38d..0bf26bda2b4c3d13b2f38a4cc49ffc6bf911b8a5 100644 --- a/openssh-7.7p1.patch +++ b/openssh-7.7p1.patch @@ -1,7 +1,7 @@ -diff -up openssh-7.7p1/ssh_config.redhat openssh-7.7p1/ssh_config ---- openssh-7.7p1/ssh_config.redhat 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/ssh_config 2018-07-03 10:44:06.522245125 +0200 -@@ -44,3 +44,7 @@ +diff -up openssh/ssh_config.redhat openssh/ssh_config +--- openssh/ssh_config.redhat 2020-02-11 23:28:35.000000000 +0100 ++++ openssh/ssh_config 2020-02-13 18:13:39.180641839 +0100 +@@ -43,3 +43,7 @@ # VisualHostKey no # ProxyCommand ssh -q -W %h:%p gateway.example.com # RekeyLimit 1G 1h @@ -9,18 +9,16 @@ diff -up openssh-7.7p1/ssh_config.redhat openssh-7.7p1/ssh_config +# To modify the system-wide ssh configuration, create a *.conf file under +# /etc/ssh/ssh_config.d/ which will be automatically included below +Include /etc/ssh/ssh_config.d/*.conf -diff -up openssh-7.7p1/ssh_config_redhat.redhat openssh-7.7p1/ssh_config_redhat ---- openssh-7.7p1/ssh_config_redhat.redhat 2018-07-03 10:44:06.522245125 +0200 -+++ openssh-7.7p1/ssh_config_redhat 2018-07-03 10:44:06.522245125 +0200 -@@ -0,0 +1,20 @@ -+# Follow system-wide Crypto Policy, if defined: -+Include /etc/crypto-policies/back-ends/openssh.config +diff -up openssh/ssh_config_redhat.redhat openssh/ssh_config_redhat +--- openssh/ssh_config_redhat.redhat 2020-02-13 18:13:39.180641839 +0100 ++++ openssh/ssh_config_redhat 2020-02-13 18:13:39.180641839 +0100 +@@ -0,0 +1,21 @@ ++# The options here are in the "Match final block" to be applied as the last ++# options and could be potentially overwritten by the user configuration ++Match final all ++ # Follow system-wide Crypto Policy, if defined: ++ Include /etc/crypto-policies/back-ends/openssh.config + -+# Uncomment this if you want to use .local domain -+# Host *.local -+# CheckHostIP no -+ -+Host * + GSSAPIAuthentication yes + +# If this option is set to yes then remote X11 clients will have full access @@ -33,10 +31,13 @@ diff -up openssh-7.7p1/ssh_config_redhat.redhat openssh-7.7p1/ssh_config_redhat + SendEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT + SendEnv LC_IDENTIFICATION LC_ALL LANGUAGE + SendEnv XMODIFIERS -diff -up openssh-7.7p1/sshd_config.0.redhat openssh-7.7p1/sshd_config.0 ---- openssh-7.7p1/sshd_config.0.redhat 2018-04-02 07:39:27.000000000 +0200 -+++ openssh-7.7p1/sshd_config.0 2018-07-03 10:44:06.523245133 +0200 -@@ -872,9 +872,9 @@ DESCRIPTION ++ ++# Uncomment this if you want to use .local domain ++# Host *.local +diff -up openssh/sshd_config.0.redhat openssh/sshd_config.0 +--- openssh/sshd_config.0.redhat 2020-02-12 14:30:04.000000000 +0100 ++++ openssh/sshd_config.0 2020-02-13 18:13:39.181641855 +0100 +@@ -970,9 +970,9 @@ DESCRIPTION SyslogFacility Gives the facility code that is used when logging messages from @@ -49,10 +50,10 @@ diff -up openssh-7.7p1/sshd_config.0.redhat openssh-7.7p1/sshd_config.0 TCPKeepAlive Specifies whether the system should send TCP keepalive messages -diff -up openssh-7.7p1/sshd_config.5.redhat openssh-7.7p1/sshd_config.5 ---- openssh-7.7p1/sshd_config.5.redhat 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/sshd_config.5 2018-07-03 10:44:06.523245133 +0200 -@@ -1461,7 +1461,7 @@ By default no subsystems are defined. +diff -up openssh/sshd_config.5.redhat openssh/sshd_config.5 +--- openssh/sshd_config.5.redhat 2020-02-11 23:28:35.000000000 +0100 ++++ openssh/sshd_config.5 2020-02-13 18:13:39.181641855 +0100 +@@ -1614,7 +1614,7 @@ By default no subsystems are defined. .It Cm SyslogFacility Gives the facility code that is used when logging messages from .Xr sshd 8 . @@ -61,10 +62,10 @@ diff -up openssh-7.7p1/sshd_config.5.redhat openssh-7.7p1/sshd_config.5 LOCAL3, LOCAL4, LOCAL5, LOCAL6, LOCAL7. The default is AUTH. .It Cm TCPKeepAlive -diff -up openssh-7.7p1/sshd_config.redhat openssh-7.7p1/sshd_config ---- openssh-7.7p1/sshd_config.redhat 2018-04-02 07:38:28.000000000 +0200 -+++ openssh-7.7p1/sshd_config 2018-07-03 10:45:16.950782466 +0200 -@@ -10,20 +10,34 @@ +diff -up openssh/sshd_config.redhat openssh/sshd_config +--- openssh/sshd_config.redhat 2020-02-11 23:28:35.000000000 +0100 ++++ openssh/sshd_config 2020-02-13 18:20:16.349913681 +0100 +@@ -10,6 +10,10 @@ # possible, but leave them commented. Uncommented options override the # default value. @@ -75,18 +76,18 @@ diff -up openssh-7.7p1/sshd_config.redhat openssh-7.7p1/sshd_config #Port 22 #AddressFamily any #ListenAddress 0.0.0.0 - #ListenAddress :: - --#HostKey /etc/ssh/ssh_host_rsa_key --#HostKey /etc/ssh/ssh_host_ecdsa_key --#HostKey /etc/ssh/ssh_host_ed25519_key -+HostKey /etc/ssh/ssh_host_rsa_key -+HostKey /etc/ssh/ssh_host_ecdsa_key -+HostKey /etc/ssh/ssh_host_ed25519_key - - # Ciphers and keying - #RekeyLimit default none - +@@ -114,3 +118,7 @@ Subsystem sftp /usr/libexec/sftp-server + # AllowTcpForwarding no + # PermitTTY no + # ForceCommand cvs server ++ ++# To modify the system-wide ssh configuration, create a *.conf file under ++# /etc/ssh/sshd_config.d/ which will be automatically included below ++Include /etc/ssh/sshd_config.d/*.conf +diff -up openssh/sshd_config_redhat.redhat openssh/sshd_config_redhat +--- openssh/sshd_config_redhat.redhat 2020-02-13 18:14:02.268006439 +0100 ++++ openssh/sshd_config_redhat 2020-02-13 18:19:20.765035947 +0100 +@@ -0,0 +1,31 @@ +# System-wide Crypto policy: +# This system is following system-wide crypto policy. The changes to +# Ciphers, MACs, KexAlgoritms and GSSAPIKexAlgorithsm will not have any @@ -96,69 +97,25 @@ diff -up openssh-7.7p1/sshd_config.redhat openssh-7.7p1/sshd_config +# variable in /etc/sysconfig/sshd to overwrite the policy. +# For more information, see manual page for update-crypto-policies(8). + - # Logging - #SyslogFacility AUTH +SyslogFacility AUTHPRIV - #LogLevel INFO - - # Authentication: -@@ -56,9 +70,11 @@ AuthorizedKeysFile .ssh/authorized_keys - # To disable tunneled clear text passwords, change to no here! - #PasswordAuthentication yes - #PermitEmptyPasswords no ++ +PasswordAuthentication yes - - # Change to no to disable s/key passwords - #ChallengeResponseAuthentication yes +ChallengeResponseAuthentication no - - # Kerberos options - #KerberosAuthentication no -@@ -67,8 +83,8 @@ AuthorizedKeysFile .ssh/authorized_keys - #KerberosGetAFSToken no - - # GSSAPI options --#GSSAPIAuthentication no --#GSSAPICleanupCredentials yes ++ +GSSAPIAuthentication yes +GSSAPICleanupCredentials no - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -@@ -79,16 +95,20 @@ AuthorizedKeysFile .ssh/authorized_keys - # If you just want the PAM account and session checks to run without - # PAM authentication, then enable this but set PasswordAuthentication - # and ChallengeResponseAuthentication to 'no'. --#UsePAM no ++ +UsePAM yes - - #AllowAgentForwarding yes - #AllowTcpForwarding yes - #GatewayPorts no --#X11Forwarding no ++ +X11Forwarding yes - #X11DisplayOffset 10 - #X11UseLocalhost yes - #PermitTTY yes --#PrintMotd yes + -+# It is recommended to use pam_motd in /etc/pam.d/ssh instead of PrintMotd, ++# It is recommended to use pam_motd in /etc/pam.d/sshd instead of PrintMotd, +# as it is more configurable and versatile than the built-in version. +PrintMotd no + - #PrintLastLog yes - #TCPKeepAlive yes - #PermitUserEnvironment no -@@ -106,6 +126,12 @@ AuthorizedKeysFile .ssh/authorized_keys - # no default banner path - #Banner none - +# Accept locale-related environment variables +AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES +AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT +AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE +AcceptEnv XMODIFIERS + - # override default of no subsystems - Subsystem sftp /usr/libexec/sftp-server - diff --git a/openssh-7.8p1-UsePAM-warning.patch b/openssh-7.8p1-UsePAM-warning.patch index da3936154e26220dfc5dd708216cfc7abf975cfb..d4c53db5c857c658ce2d41c29948f8f65e20c006 100644 --- a/openssh-7.8p1-UsePAM-warning.patch +++ b/openssh-7.8p1-UsePAM-warning.patch @@ -3,15 +3,15 @@ diff --git a/sshd.c b/sshd.c +++ b/sshd.c @@ -1701,6 +1701,10 @@ main(int ac, char **av) parse_server_config(&options, rexeced_flag ? "rexec" : config_file_name, - cfg, NULL); + cfg, &includes, NULL); + /* 'UsePAM no' is not supported in Fedora */ + if (! options.use_pam) + logit("WARNING: 'UsePAM no' is not supported in Fedora and may cause several problems."); + - seed_rng(); - /* Fill in default values for those options not explicitly set. */ + fill_default_server_options(&options); + diff --git a/sshd_config b/sshd_config --- a/sshd_config +++ b/sshd_config @@ -21,6 +21,6 @@ diff --git a/sshd_config b/sshd_config # and ChallengeResponseAuthentication to 'no'. +# WARNING: 'UsePAM no' is not supported in Fedora and may cause several +# problems. - UsePAM yes + #UsePAM no #AllowAgentForwarding yes diff --git a/openssh-7.8p1-ip-port-config-parser.patch b/openssh-7.8p1-ip-port-config-parser.patch deleted file mode 100644 index 6ca0cf50c507f7209bfcf0c243706ccc19d18a18..0000000000000000000000000000000000000000 --- a/openssh-7.8p1-ip-port-config-parser.patch +++ /dev/null @@ -1,72 +0,0 @@ -diff -up openssh/misc.c.config openssh/misc.c ---- openssh/misc.c.config 2018-08-22 13:58:54.922807799 +0200 -+++ openssh/misc.c 2018-08-22 13:58:55.000808428 +0200 -@@ -485,7 +485,7 @@ put_host_port(const char *host, u_short - * The delimiter char, if present, is stored in delim. - * If this is the last field, *cp is set to NULL. - */ --static char * -+char * - hpdelim2(char **cp, char *delim) - { - char *s, *old; -diff -up openssh/misc.h.config openssh/misc.h ---- openssh/misc.h.config 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/misc.h 2018-08-22 13:58:55.001808436 +0200 -@@ -54,6 +54,7 @@ int set_rdomain(int, const char *); - int a2port(const char *); - int a2tun(const char *, int *); - char *put_host_port(const char *, u_short); -+char *hpdelim2(char **, char *); - char *hpdelim(char **); - char *cleanhostname(char *); - char *colon(char *); -diff -up openssh/servconf.c.config openssh/servconf.c ---- openssh/servconf.c.config 2018-08-22 13:58:54.989808340 +0200 -+++ openssh/servconf.c 2018-08-22 14:18:49.235443937 +0200 -@@ -886,7 +886,7 @@ process_permitopen_list(struct ssh *ssh, - { - u_int i; - int port; -- char *host, *arg, *oarg; -+ char *host, *arg, *oarg, ch; - int where = opcode == sPermitOpen ? FORWARD_LOCAL : FORWARD_REMOTE; - const char *what = lookup_opcode_name(opcode); - -@@ -904,8 +904,8 @@ process_permitopen_list(struct ssh *ssh, - /* Otherwise treat it as a list of permitted host:port */ - for (i = 0; i < num_opens; i++) { - oarg = arg = xstrdup(opens[i]); -- host = hpdelim(&arg); -- if (host == NULL) -+ host = hpdelim2(&arg, &ch); -+ if (host == NULL || ch == '/') - fatal("%s: missing host in %s", __func__, what); - host = cleanhostname(host); - if (arg == NULL || ((port = permitopen_port(arg)) < 0)) -@@ -1323,8 +1323,10 @@ process_server_config_line(ServerOptions - port = 0; - p = arg; - } else { -- p = hpdelim(&arg); -- if (p == NULL) -+ char ch; -+ arg2 = NULL; -+ p = hpdelim2(&arg, &ch); -+ if (p == NULL || ch == '/') - fatal("%s line %d: bad address:port usage", - filename, linenum); - p = cleanhostname(p); -@@ -1965,9 +1967,10 @@ process_server_config_line(ServerOptions - */ - xasprintf(&arg2, "*:%s", arg); - } else { -+ char ch; - arg2 = xstrdup(arg); -- p = hpdelim(&arg); -- if (p == NULL) { -+ p = hpdelim2(&arg, &ch); -+ if (p == NULL || ch == '/') { - fatal("%s line %d: missing host in %s", - filename, linenum, - lookup_opcode_name(opcode)); diff --git a/openssh-7.8p1-role-mls.patch b/openssh-7.8p1-role-mls.patch index 4c58d714c6d9f670410e93ad280da35d0961636d..fb7ce7c71770e394caa30522b2d446f161ecb5e0 100644 --- a/openssh-7.8p1-role-mls.patch +++ b/openssh-7.8p1-role-mls.patch @@ -4,11 +4,11 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c @@ -256,6 +256,9 @@ input_userauth_request(int type, u_int32 Authctxt *authctxt = ssh->authctxt; Authmethod *m = NULL; - char *user, *service, *method, *style = NULL; + char *user = NULL, *service = NULL, *method = NULL, *style = NULL; +#ifdef WITH_SELINUX + char *role = NULL; +#endif - int authenticated = 0; + int r, authenticated = 0; double tstart = monotime_double(); @@ -268,6 +271,11 @@ input_userauth_request(int type, u_int32 @@ -37,9 +37,9 @@ diff -up openssh/auth2.c.role-mls openssh/auth2.c + mm_inform_authrole(role); +#endif + } - userauth_banner(); + userauth_banner(ssh); if (auth2_setup_methods_lists(authctxt) != 0) - packet_disconnect("no authentication methods enabled"); + ssh_packet_disconnect(ssh, 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 @@ -57,7 +57,7 @@ diff -up openssh/auth2-gss.c.role-mls openssh/auth2-gss.c mic.length = len; - ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, +#ifdef WITH_SELINUX -+ if (authctxt->role && (strlen(authctxt->role) > 0)) ++ if (authctxt->role && authctxt->role[0] != 0) + xasprintf(&micuser, "%s/%s", authctxt->user, authctxt->role); + else +#endif @@ -141,7 +141,7 @@ diff -up openssh/auth-pam.c.role-mls openssh/auth-pam.c +do_pam_putenv(char *name, const char *value) { int ret = 1; - #ifdef HAVE_PAM_PUTENV + char *compound; diff -up openssh/auth-pam.h.role-mls openssh/auth-pam.h --- openssh/auth-pam.h.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/auth-pam.h 2018-08-22 11:14:56.817430932 +0200 @@ -197,15 +197,15 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c --- openssh/monitor.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/monitor.c 2018-08-22 11:19:56.006844867 +0200 @@ -115,6 +115,9 @@ int mm_answer_sign(int, struct sshbuf *) - int mm_answer_pwnamallow(int, struct sshbuf *); - int mm_answer_auth2_read_banner(int, struct sshbuf *); - int mm_answer_authserv(int, struct sshbuf *); + int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *); + int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *); + int mm_answer_authserv(struct ssh *, int, struct sshbuf *); +#ifdef WITH_SELINUX -+int mm_answer_authrole(int, struct sshbuf *); ++int mm_answer_authrole(struct ssh *, int, struct sshbuf *); +#endif - int mm_answer_authpassword(int, struct sshbuf *); - int mm_answer_bsdauthquery(int, struct sshbuf *); - int mm_answer_bsdauthrespond(int, struct sshbuf *); + int mm_answer_authpassword(struct ssh *, int, struct sshbuf *); + int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *); + int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *); @@ -189,6 +192,9 @@ struct mon_table mon_dispatch_proto20[] {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, @@ -227,12 +227,12 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c #ifdef USE_PAM @@ -842,6 +851,26 @@ mm_answer_authserv(int sock, struct sshb - return (0); + return found; } +#ifdef WITH_SELINUX +int -+mm_answer_authrole(int sock, struct sshbuf *m) ++mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m) +{ + int r; + monitor_permit_authentications(1); @@ -251,7 +251,7 @@ diff -up openssh/monitor.c.role-mls openssh/monitor.c +#endif + int - mm_answer_authpassword(int sock, struct sshbuf *m) + mm_answer_authpassword(struct ssh *ssh, int sock, struct sshbuf *m) { @@ -1218,7 +1247,7 @@ monitor_valid_userblob(u_char *data, u_i { @@ -338,13 +338,13 @@ diff -up openssh/monitor_wrap.h.role-mls openssh/monitor_wrap.h --- openssh/monitor_wrap.h.role-mls 2018-08-22 11:14:56.818430941 +0200 +++ openssh/monitor_wrap.h 2018-08-22 11:22:10.439929513 +0200 @@ -44,6 +44,9 @@ DH *mm_choose_dh(int, int, int); - int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t, - const char *, u_int compat); + int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *, + const u_char *, size_t, const char *, const char *, u_int compat); void mm_inform_authserv(char *, char *); +#ifdef WITH_SELINUX +void mm_inform_authrole(char *); +#endif - struct passwd *mm_getpwnamallow(const char *); + struct passwd *mm_getpwnamallow(struct ssh *, const char *); char *mm_auth2_read_banner(void); int mm_auth_password(struct ssh *, char *); diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Makefile.in @@ -359,7 +359,7 @@ diff -up openssh/openbsd-compat/Makefile.in.role-mls openssh/openbsd-compat/Make + port-linux-sshd.o .c.o: - $(CC) $(CFLAGS) $(CPPFLAGS) -c $< + $(CC) $(CFLAGS_NOPIE) $(PICFLAG) $(CPPFLAGS) -c $< diff -up openssh/openbsd-compat/port-linux.c.role-mls openssh/openbsd-compat/port-linux.c --- openssh/openbsd-compat/port-linux.c.role-mls 2018-08-20 07:57:29.000000000 +0200 +++ openssh/openbsd-compat/port-linux.c 2018-08-22 11:14:56.819430949 +0200 diff --git a/openssh-7.8p1.tar.gz b/openssh-7.8p1.tar.gz deleted file mode 100644 index 6bb08be1db0d9c28516e0d5d9d2d26d8f0e052c2..0000000000000000000000000000000000000000 Binary files a/openssh-7.8p1.tar.gz and /dev/null differ diff --git a/openssh-7.8p1.tar.gz.asc b/openssh-7.8p1.tar.gz.asc deleted file mode 100644 index 91665f5528e3104b1f3d0d507d4728fc0189253c..0000000000000000000000000000000000000000 --- a/openssh-7.8p1.tar.gz.asc +++ /dev/null @@ -1,14 +0,0 @@ ------BEGIN PGP SIGNATURE----- - -iQHDBAABCgAdFiEEWcIRjtIG2SfmZ+vj0+X1a22SDTAFAlt+Xa8ACgkQ0+X1a22S -DTAJPwx9HIW/obxNJYTU7M8trpalBekdl1SqUjxdDwInIsKTLSOpJCsnynBai/3c -SuvZkBwcKwZZFe+xCvRQDHkf/YYLT+d7slUQolb0OJmzFKbvu6xwuv7q12ag9hQj -/8BUfdYRKb63uemfKuVAHfcnUm9WlwSbif+Au/j1yg/MlETY47ezYA9/q75wignx -3g38JVHVgKDenDd8o9/hgjeQpEHKNdCQo71nN2h3MYRlh4xrR9ENZj7y8x65Kp1j -WoZEhlvjYkka4deSGwj2MIAJnzsc39uppEoEjkB7F9SUo4O7CxbWFein70Ct7Xbs -VDWXQibnJGHKatHIecaPLUYexGWO1XYNZErDhY7fPw0ChfMGbz3+0eDfDJqGY49r -Lo6wzsrgv2kDJMqwciT/D/Zb3ocHnCrq1Isnz/Ug2lW58LMk7Y1HisPteZFQ/pkC -xKeO+K1RkaRUSCrB5iToqF+7i8eRNVROYmkKLgKcMrC0WYEjnbEoFdr4bktAS9QM -BS6aIsh2cyg2H0FjDKmYvcKOUf0IgA== -=ZiYm ------END PGP SIGNATURE----- diff --git a/openssh-7.9p1-ssh-copy-id.patch b/openssh-7.9p1-ssh-copy-id.patch new file mode 100644 index 0000000000000000000000000000000000000000..d47880a197843b1fc7ab803af7e3851c94c88c44 --- /dev/null +++ b/openssh-7.9p1-ssh-copy-id.patch @@ -0,0 +1,31 @@ +diff -up openssh-7.9p1/contrib/ssh-copy-id.ssh-copy-id openssh-7.9p1/contrib/ssh-copy-id +--- openssh-7.9p1/contrib/ssh-copy-id.ssh-copy-id 2018-10-17 02:01:20.000000000 +0200 ++++ openssh-7.9p1/contrib/ssh-copy-id 2019-01-23 20:49:30.513393667 +0100 +@@ -112,7 +112,8 @@ do + usage + } + +- OPT= OPTARG= ++ OPT= ++ OPTARG= + # implement something like getopt to avoid Solaris pain + case "$1" in + -i?*|-o?*|-p?*) +@@ -261,7 +262,7 @@ populate_new_ids() { + fi + if [ -z "$NEW_IDS" ] ; then + printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n' "$0" >&2 +- printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' "$0" >&2 ++ printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' >&2 + exit 0 + fi + printf '%s: INFO: %d key(s) remain to be installed -- if you are prompted now it is to install the new keys\n' "$0" "$(printf '%s\n' "$NEW_IDS" | wc -l)" >&2 +@@ -296,7 +297,7 @@ case "$REMOTE_VERSION" in + # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX; + # 'cd' to be at $HOME; add a newline if it's missing; and all on one line, because tcsh. + [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \ +- ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys ; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ ++ ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && { [ -z "'`tail -1c .ssh/authorized_keys 2>/dev/null`'" ] || echo >> .ssh/authorized_keys || exit 1; } && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ + || exit 1 + ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) + ;; diff --git a/openssh-8.0p1-crypto-policies.patch b/openssh-8.0p1-crypto-policies.patch new file mode 100644 index 0000000000000000000000000000000000000000..b23599d0be5725d47bd22ee38f4f229fbaf5eb05 --- /dev/null +++ b/openssh-8.0p1-crypto-policies.patch @@ -0,0 +1,494 @@ +diff -up openssh-8.2p1/ssh_config.5.crypto-policies openssh-8.2p1/ssh_config.5 +--- openssh-8.2p1/ssh_config.5.crypto-policies 2020-03-26 14:40:44.546775605 +0100 ++++ openssh-8.2p1/ssh_config.5 2020-03-26 14:52:20.700649727 +0100 +@@ -359,17 +359,17 @@ or + .Qq *.c.example.com + domains. + .It Cm CASignatureAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies which algorithms are allowed for signing of certificates + by certificate authorities (CAs). +-The default is: +-.Bd -literal -offset indent +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa +-.Ed +-.Pp + .Xr ssh 1 + will not accept host certificates signed using algorithms other than those + specified. ++.Pp + .It Cm CertificateFile + Specifies a file from which the user's certificate is read. + A corresponding private key must be provided separately in order +@@ -424,20 +424,25 @@ If the option is set to + .Cm no , + the check will not be executed. + .It Cm Ciphers ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the ciphers allowed and their order of preference. + Multiple ciphers must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified ciphers will be appended to the default set ++character, then the specified ciphers will be appended to the built-in default set + instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified ciphers (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified ciphers will be placed at the head of the +-default set. ++built-in default set. + .Pp + The supported ciphers are: + .Bd -literal -offset indent +@@ -453,13 +458,6 @@ aes256-gcm@openssh.com + chacha20-poly1305@openssh.com + .Ed + .Pp +-The default is: +-.Bd -literal -offset indent +-chacha20-poly1305@openssh.com, +-aes128-ctr,aes192-ctr,aes256-ctr, +-aes128-gcm@openssh.com,aes256-gcm@openssh.com +-.Ed +-.Pp + The list of available ciphers may also be obtained using + .Qq ssh -Q cipher . + .It Cm ClearAllForwardings +@@ -812,6 +810,11 @@ command line will be passed untouched to + The default is + .Dq no . + .It Cm GSSAPIKexAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + The list of key exchange algorithms that are offered for GSSAPI + key exchange. Possible values are + .Bd -literal -offset 3n +@@ -824,10 +827,8 @@ gss-nistp256-sha256-, + gss-curve25519-sha256- + .Ed + .Pp +-The default is +-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, +-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . + This option only applies to connections using GSSAPI. ++.Pp + .It Cm HashKnownHosts + Indicates that + .Xr ssh 1 +@@ -1149,29 +1150,25 @@ it may be zero or more of: + and + .Cm pam . + .It Cm KexAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the available KEX (Key Exchange) algorithms. + Multiple algorithms must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified methods will be appended to the default set ++character, then the specified methods will be appended to the built-in default set + instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified methods (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in 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 +-default set. +-The default is: +-.Bd -literal -offset indent +-curve25519-sha256,curve25519-sha256@libssh.org, +-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, +-diffie-hellman-group-exchange-sha256, +-diffie-hellman-group16-sha512, +-diffie-hellman-group18-sha512, +-diffie-hellman-group14-sha256 +-.Ed ++built-in default set. + .Pp + The list of available key exchange algorithms may also be obtained using + .Qq ssh -Q kex . +@@ -1231,37 +1228,33 @@ The default is INFO. + DEBUG and DEBUG1 are equivalent. + DEBUG2 and DEBUG3 each specify higher levels of verbose output. + .It Cm MACs ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the MAC (message authentication code) algorithms + in order of preference. + The MAC algorithm is used for data integrity protection. + Multiple algorithms must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified algorithms will be appended to the default set ++character, then the specified algorithms will be appended to the built-in default set + instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified algorithms (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified algorithms will be placed at the head of the +-default set. ++built-in default set. + .Pp + The algorithms that contain + .Qq -etm + calculate the MAC after encryption (encrypt-then-mac). + These are considered safer and their use recommended. + .Pp +-The default is: +-.Bd -literal -offset indent +-umac-64-etm@openssh.com,umac-128-etm@openssh.com, +-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, +-hmac-sha1-etm@openssh.com, +-umac-64@openssh.com,umac-128@openssh.com, +-hmac-sha2-256,hmac-sha2-512,hmac-sha1 +-.Ed +-.Pp + The list of available MAC algorithms may also be obtained using + .Qq ssh -Q mac . + .It Cm NoHostAuthenticationForLocalhost +@@ -1394,36 +1387,25 @@ instead of continuing to execute and pas + The default is + .Cm no . + .It Cm PubkeyAcceptedKeyTypes ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the key types that will be used for public key authentication + as a comma-separated list of patterns. + If the specified list begins with a + .Sq + +-character, then the key types after it will be appended to the default ++character, then the key types after it will be appended to the built-in default + instead of replacing it. + If the specified list begins with a + .Sq - + character, then the specified key types (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified key types will be placed at the head of the +-default set. +-The default for this option is: +-.Bd -literal -offset 3n +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ssh-ed25519-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-rsa-cert-v01@openssh.com, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ecdsa-sha2-nistp256@openssh.com, +-ssh-ed25519,sk-ssh-ed25519@openssh.com, +-rsa-sha2-512,rsa-sha2-256,ssh-rsa +-.Ed ++built-in default set. + .Pp + The list of available key types may also be obtained using + .Qq ssh -Q PubkeyAcceptedKeyTypes . +diff -up openssh-8.2p1/sshd_config.5.crypto-policies openssh-8.2p1/sshd_config.5 +--- openssh-8.2p1/sshd_config.5.crypto-policies 2020-03-26 14:40:44.530775355 +0100 ++++ openssh-8.2p1/sshd_config.5 2020-03-26 14:48:56.732468099 +0100 +@@ -375,16 +375,16 @@ If the argument is + then no banner is displayed. + By default, no banner is displayed. + .It Cm CASignatureAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies which algorithms are allowed for signing of certificates + by certificate authorities (CAs). +-The default is: +-.Bd -literal -offset indent +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-ssh-ed25519,rsa-sha2-512,rsa-sha2-256,ssh-rsa +-.Ed +-.Pp + Certificates signed using other algorithms will not be accepted for + public key or host-based authentication. ++.Pp + .It Cm ChallengeResponseAuthentication + Specifies whether challenge-response authentication is allowed (e.g. via + PAM or through authentication styles supported in +@@ -446,20 +446,25 @@ The default is + indicating not to + .Xr chroot 2 . + .It Cm Ciphers ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the ciphers allowed. + Multiple ciphers must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified ciphers will be appended to the default set ++character, then the specified ciphers will be appended to the built-in default set + instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified ciphers (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified ciphers will be placed at the head of the +-default set. ++built-in default set. + .Pp + The supported ciphers are: + .Pp +@@ -486,13 +491,6 @@ aes256-gcm@openssh.com + chacha20-poly1305@openssh.com + .El + .Pp +-The default is: +-.Bd -literal -offset indent +-chacha20-poly1305@openssh.com, +-aes128-ctr,aes192-ctr,aes256-ctr, +-aes128-gcm@openssh.com,aes256-gcm@openssh.com +-.Ed +-.Pp + The list of available ciphers may also be obtained using + .Qq ssh -Q cipher . + .It Cm ClientAliveCountMax +@@ -681,22 +679,24 @@ For this to work + .Cm GSSAPIKeyExchange + needs to be enabled in the server and also used by the client. + .It Cm GSSAPIKexAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + The list of key exchange algorithms that are accepted by GSSAPI + key exchange. Possible values are + .Bd -literal -offset 3n +-gss-gex-sha1-, +-gss-group1-sha1-, +-gss-group14-sha1-, +-gss-group14-sha256-, +-gss-group16-sha512-, +-gss-nistp256-sha256-, ++gss-gex-sha1- ++gss-group1-sha1- ++gss-group14-sha1- ++gss-group14-sha256- ++gss-group16-sha512- ++gss-nistp256-sha256- + gss-curve25519-sha256- + .Ed +-.Pp +-The default is +-.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, +-gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . + This option only applies to connections using GSSAPI. ++.Pp + .It Cm HostbasedAcceptedKeyTypes + Specifies the key types that will be accepted for hostbased authentication + as a list of comma-separated patterns. +@@ -793,25 +793,13 @@ is specified, the location of the socket + .Ev SSH_AUTH_SOCK + environment variable. + .It Cm HostKeyAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the host key algorithms + that the server offers. +-The default for this option is: +-.Bd -literal -offset 3n +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ssh-ed25519-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-rsa-cert-v01@openssh.com, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ecdsa-sha2-nistp256@openssh.com, +-ssh-ed25519,sk-ssh-ed25519@openssh.com, +-rsa-sha2-512,rsa-sha2-256,ssh-rsa +-.Ed +-.Pp + The list of available key types may also be obtained using + .Qq ssh -Q HostKeyAlgorithms . + .It Cm IgnoreRhosts +@@ -943,20 +931,25 @@ Specifies whether to look at .k5login fi + The default is + .Cm yes . + .It Cm KexAlgorithms ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.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 + .Sq + +-character, then the specified methods will be appended to the default set ++character, then the specified methods will be appended to the built-in default set + instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified methods (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in 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 +-default set. ++built-in default set. + The supported algorithms are: + .Pp + .Bl -item -compact -offset indent +@@ -988,15 +981,6 @@ ecdh-sha2-nistp521 + sntrup4591761x25519-sha512@tinyssh.org + .El + .Pp +-The default is: +-.Bd -literal -offset indent +-curve25519-sha256,curve25519-sha256@libssh.org, +-ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, +-diffie-hellman-group-exchange-sha256, +-diffie-hellman-group16-sha512,diffie-hellman-group18-sha512, +-diffie-hellman-group14-sha256 +-.Ed +-.Pp + The list of available key exchange algorithms may also be obtained using + .Qq ssh -Q KexAlgorithms . + .It Cm ListenAddress +@@ -1065,21 +1049,26 @@ DEBUG and DEBUG1 are equivalent. + DEBUG2 and DEBUG3 each specify higher levels of debugging output. + Logging with a DEBUG level violates the privacy of users and is not recommended. + .It Cm MACs ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the available MAC (message authentication code) algorithms. + The MAC algorithm is used for data integrity protection. + Multiple algorithms must be comma-separated. + If the specified list begins with a + .Sq + +-character, then the specified algorithms will be appended to the default set ++character, then the specified algorithms will be appended to the built-in default set + instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified algorithms (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified algorithms will be placed at the head of the +-default set. ++built-in default set. + .Pp + The algorithms that contain + .Qq -etm +@@ -1122,15 +1111,6 @@ umac-64-etm@openssh.com + umac-128-etm@openssh.com + .El + .Pp +-The default is: +-.Bd -literal -offset indent +-umac-64-etm@openssh.com,umac-128-etm@openssh.com, +-hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, +-hmac-sha1-etm@openssh.com, +-umac-64@openssh.com,umac-128@openssh.com, +-hmac-sha2-256,hmac-sha2-512,hmac-sha1 +-.Ed +-.Pp + The list of available MAC algorithms may also be obtained using + .Qq ssh -Q mac . + .It Cm Match +@@ -1480,36 +1460,25 @@ or equivalent.) + The default is + .Cm yes . + .It Cm PubkeyAcceptedKeyTypes ++The default is handled system-wide by ++.Xr crypto-policies 7 . ++To see the defaults and how to modify this default, see manual page ++.Xr update-crypto-policies 8 . ++.Pp + Specifies the key types that will be accepted for public key authentication + as a list of comma-separated patterns. + Alternately if the specified list begins with a + .Sq + +-character, then the specified key types will be appended to the default set ++character, then the specified key types will be appended to the built-in default set + instead of replacing them. + If the specified list begins with a + .Sq - + character, then the specified key types (including wildcards) will be removed +-from the default set instead of replacing them. ++from the built-in default set instead of replacing them. + If the specified list begins with a + .Sq ^ + character, then the specified key types will be placed at the head of the +-default set. +-The default for this option is: +-.Bd -literal -offset 3n +-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ecdsa-sha2-nistp384-cert-v01@openssh.com, +-ecdsa-sha2-nistp521-cert-v01@openssh.com, +-sk-ecdsa-sha2-nistp256-cert-v01@openssh.com, +-ssh-ed25519-cert-v01@openssh.com, +-sk-ssh-ed25519-cert-v01@openssh.com, +-rsa-sha2-512-cert-v01@openssh.com, +-rsa-sha2-256-cert-v01@openssh.com, +-ssh-rsa-cert-v01@openssh.com, +-ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521, +-sk-ecdsa-sha2-nistp256@openssh.com, +-ssh-ed25519,sk-ssh-ed25519@openssh.com, +-rsa-sha2-512,rsa-sha2-256,ssh-rsa +-.Ed ++built-in default set. + .Pp + The list of available key types may also be obtained using + .Qq ssh -Q PubkeyAcceptedKeyTypes . diff --git a/openssh-7.8p1-gsskex.patch b/openssh-8.0p1-gssapi-keyex.patch similarity index 45% rename from openssh-7.8p1-gsskex.patch rename to openssh-8.0p1-gssapi-keyex.patch index 6a350c7ff5697ba5018511b3ac390ef6182e1174..770e99ecb630298e38a5a8e808b93f404aa6aab5 100644 --- a/openssh-7.8p1-gsskex.patch +++ b/openssh-8.0p1-gssapi-keyex.patch @@ -1,69 +1,191 @@ -diff -up openssh/auth2.c.gsskex openssh/auth2.c ---- openssh/auth2.c.gsskex 2018-08-22 11:47:33.260216045 +0200 -+++ openssh/auth2.c 2018-08-22 11:47:33.307216424 +0200 -@@ -74,6 +74,7 @@ extern Authmethod method_passwd; - extern Authmethod method_kbdint; - extern Authmethod method_hostbased; - #ifdef GSSAPI -+extern Authmethod method_gsskeyex; - extern Authmethod method_gssapi; - #endif +diff --git a/Makefile.in b/Makefile.in +index e7549470..b68c1710 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -109,6 +109,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ + kexgexc.o kexgexs.o \ + sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \ ++ kexgssc.o \ + sftp-realpath.o platform-pledge.o platform-tracing.o platform-misc.o \ + sshbuf-io.o -@@ -81,6 +82,7 @@ Authmethod *authmethods[] = { - &method_none, - &method_pubkey, - #ifdef GSSAPI -+ &method_gsskeyex, - &method_gssapi, - #endif - &method_passwd, -diff -up openssh/auth2-gss.c.gsskex openssh/auth2-gss.c ---- openssh/auth2-gss.c.gsskex 2018-08-22 11:47:33.260216045 +0200 -+++ openssh/auth2-gss.c 2018-08-22 13:00:48.722680124 +0200 -@@ -31,6 +31,7 @@ - #include +@@ -125,7 +126,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ + auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ + auth2-none.o auth2-passwd.o auth2-pubkey.o \ + monitor.o monitor_wrap.o auth-krb5.o \ +- auth2-gss.o gss-serv.o gss-serv-krb5.o \ ++ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \ + loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ + sftp-server.o sftp-common.o \ + sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ +diff --git a/auth.c b/auth.c +index 086b8ebb..687c57b4 100644 +--- a/auth.c ++++ b/auth.c +@@ -400,7 +400,8 @@ auth_root_allowed(struct ssh *ssh, const char *method) + case PERMIT_NO_PASSWD: + if (strcmp(method, "publickey") == 0 || + strcmp(method, "hostbased") == 0 || +- strcmp(method, "gssapi-with-mic") == 0) ++ strcmp(method, "gssapi-with-mic") == 0 || ++ strcmp(method, "gssapi-keyex") == 0) + return 1; + break; + case PERMIT_FORCED_ONLY: +@@ -724,99 +725,6 @@ fakepw(void) + return (&fake); + } - #include -+#include +-/* +- * Returns the remote DNS hostname as a string. The returned string must not +- * be freed. NB. this will usually trigger a DNS query the first time it is +- * called. +- * This function does additional checks on the hostname to mitigate some +- * attacks on legacy rhosts-style authentication. +- * XXX is RhostsRSAAuthentication vulnerable to these? +- * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?) +- */ +- +-static char * +-remote_hostname(struct ssh *ssh) +-{ +- struct sockaddr_storage from; +- socklen_t fromlen; +- struct addrinfo hints, *ai, *aitop; +- char name[NI_MAXHOST], ntop2[NI_MAXHOST]; +- const char *ntop = ssh_remote_ipaddr(ssh); +- +- /* Get IP address of client. */ +- fromlen = sizeof(from); +- memset(&from, 0, sizeof(from)); +- if (getpeername(ssh_packet_get_connection_in(ssh), +- (struct sockaddr *)&from, &fromlen) == -1) { +- debug("getpeername failed: %.100s", strerror(errno)); +- return xstrdup(ntop); +- } +- +- ipv64_normalise_mapped(&from, &fromlen); +- if (from.ss_family == AF_INET6) +- fromlen = sizeof(struct sockaddr_in6); +- +- debug3("Trying to reverse map address %.100s.", ntop); +- /* Map the IP address to a host name. */ +- if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), +- NULL, 0, NI_NAMEREQD) != 0) { +- /* Host name not found. Use ip address. */ +- return xstrdup(ntop); +- } +- +- /* +- * if reverse lookup result looks like a numeric hostname, +- * someone is trying to trick us by PTR record like following: +- * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 +- */ +- memset(&hints, 0, sizeof(hints)); +- hints.ai_socktype = SOCK_DGRAM; /*dummy*/ +- hints.ai_flags = AI_NUMERICHOST; +- if (getaddrinfo(name, NULL, &hints, &ai) == 0) { +- logit("Nasty PTR record \"%s\" is set up for %s, ignoring", +- name, ntop); +- freeaddrinfo(ai); +- return xstrdup(ntop); +- } +- +- /* Names are stored in lowercase. */ +- lowercase(name); +- +- /* +- * Map it back to an IP address and check that the given +- * address actually is an address of this host. This is +- * necessary because anyone with access to a name server can +- * define arbitrary names for an IP address. Mapping from +- * name to IP address can be trusted better (but can still be +- * fooled if the intruder has access to the name server of +- * the domain). +- */ +- memset(&hints, 0, sizeof(hints)); +- hints.ai_family = from.ss_family; +- hints.ai_socktype = SOCK_STREAM; +- if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { +- logit("reverse mapping checking getaddrinfo for %.700s " +- "[%s] failed.", name, ntop); +- return xstrdup(ntop); +- } +- /* Look for the address from the list of addresses. */ +- for (ai = aitop; ai; ai = ai->ai_next) { +- if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, +- sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && +- (strcmp(ntop, ntop2) == 0)) +- break; +- } +- freeaddrinfo(aitop); +- /* If we reached the end of the list, the address was not there. */ +- if (ai == NULL) { +- /* Address not found for the host name. */ +- logit("Address %.100s maps to %.600s, but this does not " +- "map back to the address.", ntop, name); +- return xstrdup(ntop); +- } +- return xstrdup(name); +-} +- + /* + * Return the canonical name of the host in the other side of the current + * connection. The host name is cached, so it is efficient to call this +diff --git a/auth2-gss.c b/auth2-gss.c +index 9351e042..d6446c0c 100644 +--- a/auth2-gss.c ++++ b/auth2-gss.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: auth2-gss.c,v 1.29 2018/07/31 03:10:27 djm Exp $ */ - #include "xmalloc.h" - #include "sshkey.h" -@@ -54,6 +55,44 @@ static int input_gssapi_mic(int type, u_ + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -54,6 +54,48 @@ static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh); static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh); static int input_gssapi_errtok(int, u_int32_t, struct ssh *); -+/* ++/* + * The 'gssapi_keyex' userauth mechanism. + */ +static int +userauth_gsskeyex(struct ssh *ssh) +{ + Authctxt *authctxt = ssh->authctxt; -+ int authenticated = 0; ++ int r, authenticated = 0; + struct sshbuf *b = NULL; + gss_buffer_desc mic, gssbuf; -+ u_int len; ++ u_char *p; ++ size_t len; + -+ mic.value = packet_get_string(&len); -+ mic.length = len; -+ -+ packet_check_eom(); ++ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("%s: %s", __func__, ssh_err(r)); + + if ((b = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + ++ mic.value = p; ++ mic.length = len; ++ + ssh_gssapi_buildmic(b, authctxt->user, authctxt->service, + "gssapi-keyex"); + -+ gssbuf.value = sshbuf_mutable_ptr(b); ++ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) ++ fatal("%s: sshbuf_mutable_ptr failed", __func__); + gssbuf.length = sshbuf_len(b); + + /* gss_kex_context is NULL with privsep, so we can't check it here */ -+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, ++ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, + &gssbuf, &mic)))) + authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw)); -+ ++ authctxt->pw, 1)); ++ + sshbuf_free(b); + free(mic.value); + @@ -73,27 +195,27 @@ diff -up openssh/auth2-gss.c.gsskex openssh/auth2-gss.c /* * We only support those mechanisms that we know about (ie ones that we know * how to check local user kuserok and the like) -@@ -260,7 +296,8 @@ input_gssapi_exchange_complete(int type, +@@ -260,7 +302,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) if ((r = sshpkt_get_end(ssh)) != 0) fatal("%s: %s", __func__, ssh_err(r)); - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); + authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, -+ authctxt->pw)); ++ authctxt->pw, 1)); if ((!use_privsep || mm_is_monitor()) && (displayname = ssh_gssapi_displayname()) != NULL) -@@ -313,7 +350,8 @@ input_gssapi_mic(int type, u_int32_t ple +@@ -306,7 +349,8 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) gssbuf.length = sshbuf_len(b); if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) - authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); -+ authenticated = -+ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); ++ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, ++ authctxt->pw, 0)); else logit("GSSAPI MIC check failed"); -@@ -335,6 +373,12 @@ input_gssapi_mic(int type, u_int32_t ple +@@ -326,6 +370,12 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) return 0; } @@ -106,20 +228,148 @@ diff -up openssh/auth2-gss.c.gsskex openssh/auth2-gss.c Authmethod method_gssapi = { "gssapi-with-mic", userauth_gssapi, -diff -up openssh/auth.c.gsskex openssh/auth.c ---- openssh/auth.c.gsskex 2018-08-22 11:47:33.274216158 +0200 -+++ openssh/auth.c 2018-08-22 11:47:33.308216432 +0200 -@@ -395,6 +395,7 @@ auth_root_allowed(struct ssh *ssh, const - case PERMIT_NO_PASSWD: - if (strcmp(method, "publickey") == 0 || - strcmp(method, "hostbased") == 0 || -+ strcmp(method, "gssapi-keyex") == 0 || - strcmp(method, "gssapi-with-mic") == 0) - return 1; - break; -diff -up openssh/clientloop.c.gsskex openssh/clientloop.c ---- openssh/clientloop.c.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/clientloop.c 2018-08-22 11:47:33.309216441 +0200 +diff --git a/auth2.c b/auth2.c +index 0e776224..1c217268 100644 +--- a/auth2.c ++++ b/auth2.c +@@ -73,6 +73,7 @@ extern Authmethod method_passwd; + extern Authmethod method_kbdint; + extern Authmethod method_hostbased; + #ifdef GSSAPI ++extern Authmethod method_gsskeyex; + extern Authmethod method_gssapi; + #endif + +@@ -80,6 +81,7 @@ Authmethod *authmethods[] = { + &method_none, + &method_pubkey, + #ifdef GSSAPI ++ &method_gsskeyex, + &method_gssapi, + #endif + &method_passwd, +diff --git a/canohost.c b/canohost.c +index abea9c6e..8e81b519 100644 +--- a/canohost.c ++++ b/canohost.c +@@ -35,6 +35,99 @@ + #include "canohost.h" + #include "misc.h" + ++/* ++ * Returns the remote DNS hostname as a string. The returned string must not ++ * be freed. NB. this will usually trigger a DNS query the first time it is ++ * called. ++ * This function does additional checks on the hostname to mitigate some ++ * attacks on legacy rhosts-style authentication. ++ * XXX is RhostsRSAAuthentication vulnerable to these? ++ * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?) ++ */ ++ ++char * ++remote_hostname(struct ssh *ssh) ++{ ++ struct sockaddr_storage from; ++ socklen_t fromlen; ++ struct addrinfo hints, *ai, *aitop; ++ char name[NI_MAXHOST], ntop2[NI_MAXHOST]; ++ const char *ntop = ssh_remote_ipaddr(ssh); ++ ++ /* Get IP address of client. */ ++ fromlen = sizeof(from); ++ memset(&from, 0, sizeof(from)); ++ if (getpeername(ssh_packet_get_connection_in(ssh), ++ (struct sockaddr *)&from, &fromlen) == -1) { ++ debug("getpeername failed: %.100s", strerror(errno)); ++ return xstrdup(ntop); ++ } ++ ++ ipv64_normalise_mapped(&from, &fromlen); ++ if (from.ss_family == AF_INET6) ++ fromlen = sizeof(struct sockaddr_in6); ++ ++ debug3("Trying to reverse map address %.100s.", ntop); ++ /* Map the IP address to a host name. */ ++ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), ++ NULL, 0, NI_NAMEREQD) != 0) { ++ /* Host name not found. Use ip address. */ ++ return xstrdup(ntop); ++ } ++ ++ /* ++ * if reverse lookup result looks like a numeric hostname, ++ * someone is trying to trick us by PTR record like following: ++ * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 ++ */ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_socktype = SOCK_DGRAM; /*dummy*/ ++ hints.ai_flags = AI_NUMERICHOST; ++ if (getaddrinfo(name, NULL, &hints, &ai) == 0) { ++ logit("Nasty PTR record \"%s\" is set up for %s, ignoring", ++ name, ntop); ++ freeaddrinfo(ai); ++ return xstrdup(ntop); ++ } ++ ++ /* Names are stored in lowercase. */ ++ lowercase(name); ++ ++ /* ++ * Map it back to an IP address and check that the given ++ * address actually is an address of this host. This is ++ * necessary because anyone with access to a name server can ++ * define arbitrary names for an IP address. Mapping from ++ * name to IP address can be trusted better (but can still be ++ * fooled if the intruder has access to the name server of ++ * the domain). ++ */ ++ memset(&hints, 0, sizeof(hints)); ++ hints.ai_family = from.ss_family; ++ hints.ai_socktype = SOCK_STREAM; ++ if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { ++ logit("reverse mapping checking getaddrinfo for %.700s " ++ "[%s] failed.", name, ntop); ++ return xstrdup(ntop); ++ } ++ /* Look for the address from the list of addresses. */ ++ for (ai = aitop; ai; ai = ai->ai_next) { ++ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, ++ sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && ++ (strcmp(ntop, ntop2) == 0)) ++ break; ++ } ++ freeaddrinfo(aitop); ++ /* If we reached the end of the list, the address was not there. */ ++ if (ai == NULL) { ++ /* Address not found for the host name. */ ++ logit("Address %.100s maps to %.600s, but this does not " ++ "map back to the address.", ntop, name); ++ return xstrdup(ntop); ++ } ++ return xstrdup(name); ++} ++ + void + ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) + { +diff --git a/canohost.h b/canohost.h +index 26d62855..0cadc9f1 100644 +--- a/canohost.h ++++ b/canohost.h +@@ -15,6 +15,9 @@ + #ifndef _CANOHOST_H + #define _CANOHOST_H + ++struct ssh; ++ ++char *remote_hostname(struct ssh *); + char *get_peer_ipaddr(int); + int get_peer_port(int); + char *get_local_ipaddr(int); +diff --git a/clientloop.c b/clientloop.c +index ebd0dbca..1bdac6a4 100644 +--- a/clientloop.c ++++ b/clientloop.c @@ -112,6 +112,10 @@ #include "ssherr.h" #include "hostfile.h" @@ -131,7 +381,7 @@ diff -up openssh/clientloop.c.gsskex openssh/clientloop.c /* import options */ extern Options options; -@@ -1357,9 +1361,18 @@ client_loop(struct ssh *ssh, int have_pt +@@ -1379,9 +1383,18 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, break; /* Do channel operations unless rekeying in progress. */ @@ -149,59 +399,65 @@ diff -up openssh/clientloop.c.gsskex openssh/clientloop.c + } + /* Buffer input from the connection. */ - client_process_net_input(readset); + client_process_net_input(ssh, readset); -diff -up openssh/configure.ac.gsskex openssh/configure.ac ---- openssh/configure.ac.gsskex 2018-08-22 11:47:33.296216335 +0200 -+++ openssh/configure.ac 2018-08-22 11:47:33.309216441 +0200 -@@ -673,6 +673,30 @@ main() { if (NSVersionOfRunTimeLibrary(" +diff --git a/configure.ac b/configure.ac +index b689db4b..efafb6bd 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -674,6 +674,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) [Use tunnel device compatibility to OpenBSD]) AC_DEFINE([SSH_TUN_PREPEND_AF], [1], [Prepend the address family to IP tunnel traffic]) -+ AC_MSG_CHECKING(if we have the Security Authorization Session API) ++ AC_MSG_CHECKING([if we have the Security Authorization Session API]) + AC_TRY_COMPILE([#include ], + [SessionCreate(0, 0);], + [ac_cv_use_security_session_api="yes" -+ AC_DEFINE(USE_SECURITY_SESSION_API, 1, ++ AC_DEFINE([USE_SECURITY_SESSION_API], [1], + [platform has the Security Authorization Session API]) + LIBS="$LIBS -framework Security" -+ AC_MSG_RESULT(yes)], ++ AC_MSG_RESULT([yes])], + [ac_cv_use_security_session_api="no" -+ AC_MSG_RESULT(no)]) -+ AC_MSG_CHECKING(if we have an in-memory credentials cache) ++ AC_MSG_RESULT([no])]) ++ AC_MSG_CHECKING([if we have an in-memory credentials cache]) + AC_TRY_COMPILE( + [#include ], + [cc_context_t c; + (void) cc_initialize (&c, 0, NULL, NULL);], -+ [AC_DEFINE(USE_CCAPI, 1, ++ [AC_DEFINE([USE_CCAPI], [1], + [platform uses an in-memory credentials cache]) + LIBS="$LIBS -framework Security" -+ AC_MSG_RESULT(yes) ++ AC_MSG_RESULT([yes]) + if test "x$ac_cv_use_security_session_api" = "xno"; then -+ AC_MSG_ERROR(*** Need a security framework to use the credentials cache API ***) ++ AC_MSG_ERROR([*** Need a security framework to use the credentials cache API ***]) + fi], -+ [AC_MSG_RESULT(no)] ++ [AC_MSG_RESULT([no])] + ) m4_pattern_allow([AU_IPv]) AC_CHECK_DECL([AU_IPv4], [], AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) -diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c ---- openssh/gss-genr.c.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/gss-genr.c 2018-08-22 13:18:47.444383602 +0200 -@@ -35,18 +35,177 @@ - #include - #include - #include -+#include - - #include "xmalloc.h" - #include "ssherr.h" +diff --git a/gss-genr.c b/gss-genr.c +index d56257b4..763a63ff 100644 +--- a/gss-genr.c ++++ b/gss-genr.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-genr.c,v 1.26 2018/07/10 09:13:30 djm Exp $ */ + + /* +- * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -41,12 +41,36 @@ #include "sshbuf.h" #include "log.h" #include "ssh2.h" +#include "cipher.h" +#include "sshkey.h" +#include "kex.h" ++#include "digest.h" ++#include "packet.h" #include "ssh-gss.h" @@ -222,10 +478,32 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + +static ssh_gss_kex_mapping *gss_enc2oid = NULL; + -+int -+ssh_gssapi_oid_table_ok() { ++int ++ssh_gssapi_oid_table_ok(void) { + return (gss_enc2oid != NULL); +} ++ + /* sshbuf_get for gss_buffer_desc */ + int + ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) +@@ -62,6 +86,162 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) + return 0; + } + ++/* sshpkt_get of gss_buffer_desc */ ++int ++ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *ssh, gss_buffer_desc *g) ++{ ++ int r; ++ u_char *p; ++ size_t len; ++ ++ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0) ++ return r; ++ g->value = p; ++ g->length = len; ++ return 0; ++} + +/* + * Return a list of the gss-group1-sha1 mechanisms supported by this program @@ -235,28 +513,30 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + */ + +char * -+ssh_gssapi_client_mechanisms(const char *host, const char *client) { -+ gss_OID_set gss_supported; ++ssh_gssapi_client_mechanisms(const char *host, const char *client, ++ const char *kex) { ++ gss_OID_set gss_supported = NULL; + OM_uint32 min_status; + + if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) + return NULL; + -+ return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, -+ host, client)); ++ return ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, ++ host, client, kex); +} + +char * +ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, -+ const char *host, const char *client) { -+ struct sshbuf *buf; ++ const char *host, const char *client, const char *kex) { ++ struct sshbuf *buf = NULL; + size_t i; -+ int oidpos, enclen, r; ++ int r = SSH_ERR_ALLOC_FAIL; ++ int oidpos, enclen; + char *mechs, *encoded; -+ u_char digest[EVP_MAX_MD_SIZE]; ++ u_char digest[SSH_DIGEST_MAX_LENGTH]; + char deroid[2]; -+ const EVP_MD *evp_md = EVP_md5(); -+ EVP_MD_CTX md; ++ struct ssh_digest_ctx *md = NULL; ++ char *s, *cp, *p; + + if (gss_enc2oid != NULL) { + for (i = 0; gss_enc2oid[i].encoded != NULL; i++) @@ -271,6 +551,7 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + fatal("%s: sshbuf_new failed", __func__); + + oidpos = 0; ++ s = cp = xstrdup(kex); + for (i = 0; i < gss_supported->count; i++) { + if (gss_supported->elements[i].length < 128 && + (*check)(NULL, &(gss_supported->elements[i]), host, client)) { @@ -278,47 +559,48 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + deroid[0] = SSH_GSS_OIDTYPE; + deroid[1] = gss_supported->elements[i].length; + -+ EVP_DigestInit(&md, evp_md); -+ EVP_DigestUpdate(&md, deroid, 2); -+ EVP_DigestUpdate(&md, -+ gss_supported->elements[i].elements, -+ gss_supported->elements[i].length); -+ EVP_DigestFinal(&md, digest, NULL); -+ -+ encoded = xmalloc(EVP_MD_size(evp_md) * 2); -+ enclen = __b64_ntop(digest, EVP_MD_size(evp_md), -+ encoded, EVP_MD_size(evp_md) * 2); -+ -+ if (oidpos != 0) -+ if ((r = sshbuf_put_u8(buf, ',')) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ -+ if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID, -+ sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 || -+ (r = sshbuf_put(buf, encoded, enclen)) != 0 || -+ (r = sshbuf_put_u8(buf, ',')) != 0 || -+ (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID, -+ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 || -+ (r = sshbuf_put(buf, encoded, enclen)) != 0 || -+ (r = sshbuf_put_u8(buf, ',')) != 0 || -+ (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID, -+ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 || -+ (r = sshbuf_put(buf, encoded, enclen)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ 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) ++ fatal("%s: digest failed: %s", __func__, ++ ssh_err(r)); ++ ssh_digest_free(md); ++ md = NULL; ++ ++ encoded = xmalloc(ssh_digest_bytes(SSH_DIGEST_MD5) ++ * 2); ++ enclen = __b64_ntop(digest, ++ ssh_digest_bytes(SSH_DIGEST_MD5), encoded, ++ ssh_digest_bytes(SSH_DIGEST_MD5) * 2); ++ ++ cp = strncpy(s, kex, strlen(kex)); ++ for ((p = strsep(&cp, ",")); p && *p != '\0'; ++ (p = strsep(&cp, ","))) { ++ if (sshbuf_len(buf) != 0 && ++ (r = sshbuf_put_u8(buf, ',')) != 0) ++ fatal("%s: sshbuf_put_u8 error: %s", ++ __func__, ssh_err(r)); ++ if ((r = sshbuf_put(buf, p, strlen(p))) != 0 || ++ (r = sshbuf_put(buf, encoded, enclen)) != 0) ++ fatal("%s: sshbuf_put error: %s", ++ __func__, ssh_err(r)); ++ } + + gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); + gss_enc2oid[oidpos].encoded = encoded; + oidpos++; + } + } ++ free(s); + gss_enc2oid[oidpos].oid = NULL; + gss_enc2oid[oidpos].encoded = NULL; + -+ if ((r = sshbuf_put_u8(buf, '\0')) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ if ((mechs = sshbuf_dup_string(buf)) == NULL) ++ fatal("%s: sshbuf_dup_string failed", __func__); + -+ mechs = xmalloc(sshbuf_len(buf)); -+ sshbuf_get(buf, mechs, sshbuf_len(buf)); + sshbuf_free(buf); + + if (strlen(mechs) == 0) { @@ -332,27 +614,28 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c +gss_OID +ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { + int i = 0; -+ -+ switch (kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; -+ break; -+ case KEX_GSS_GRP14_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1; -+ break; -+ case KEX_GSS_GEX_SHA1: -+ if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID)) -+ return GSS_C_NO_OID; -+ name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1; ++ ++#define SKIP_KEX_NAME(type) \ ++ case type: \ ++ if (strlen(name) < sizeof(type##_ID)) \ ++ return GSS_C_NO_OID; \ ++ name += sizeof(type##_ID) - 1; \ + break; ++ ++ switch (kex_type) { ++ SKIP_KEX_NAME(KEX_GSS_GRP1_SHA1) ++ SKIP_KEX_NAME(KEX_GSS_GRP14_SHA1) ++ SKIP_KEX_NAME(KEX_GSS_GRP14_SHA256) ++ SKIP_KEX_NAME(KEX_GSS_GRP16_SHA512) ++ SKIP_KEX_NAME(KEX_GSS_GEX_SHA1) ++ SKIP_KEX_NAME(KEX_GSS_NISTP256_SHA256) ++ SKIP_KEX_NAME(KEX_GSS_C25519_SHA256) + default: + return GSS_C_NO_OID; + } + ++#undef SKIP_KEX_NAME ++ + while (gss_enc2oid[i].encoded != NULL && + strcmp(name, gss_enc2oid[i].encoded) != 0) + i++; @@ -363,10 +646,10 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + return gss_enc2oid[i].oid; +} + - /* sshbuf_get for gss_buffer_desc */ + /* Check that the OID in a data stream matches that in the context */ int - ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) -@@ -218,7 +373,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int de + ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) +@@ -218,7 +398,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, } ctx->major = gss_init_sec_context(&ctx->minor, @@ -375,10 +658,11 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 0, NULL, recv_tok, NULL, send_tok, flags, NULL); -@@ -248,8 +403,42 @@ ssh_gssapi_import_name(Gssctxt *ctx, con +@@ -247,9 +427,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) + return (ctx->major); } - OM_uint32 ++OM_uint32 +ssh_gssapi_client_identity(Gssctxt *ctx, const char *name) +{ + gss_buffer_desc gssbuf; @@ -396,8 +680,8 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + GSS_C_NT_USER_NAME, &gssname); + + if (!ctx->major) -+ ctx->major = gss_acquire_cred(&ctx->minor, -+ gssname, 0, oidset, GSS_C_INITIATE, ++ ctx->major = gss_acquire_cred(&ctx->minor, ++ gssname, 0, oidset, GSS_C_INITIATE, + &ctx->client_creds, NULL, NULL); + + gss_release_name(&status, &gssname); @@ -409,16 +693,16 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + return(ctx->major); +} + -+OM_uint32 + OM_uint32 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) { -+ if (ctx == NULL) ++ if (ctx == NULL) + return -1; + if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, GSS_C_QOP_DEFAULT, buffer, hash))) ssh_gssapi_error(ctx); -@@ -257,6 +446,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer +@@ -257,6 +471,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) return (ctx->major); } @@ -438,12 +722,12 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c void ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, const char *context) -@@ -273,11 +475,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, co +@@ -273,11 +500,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, } int -ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) -+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, ++ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, + const char *client) { gss_buffer_desc token = GSS_C_EMPTY_BUFFER; @@ -456,7 +740,7 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c /* RFC 4462 says we MUST NOT do SPNEGO */ if (oid->length == spnego_oid.length && -@@ -287,6 +494,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx +@@ -287,6 +519,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) ssh_gssapi_build_ctx(ctx); ssh_gssapi_set_oid(*ctx, oid); major = ssh_gssapi_import_name(*ctx, host); @@ -467,12 +751,12 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c if (!GSS_ERROR(major)) { major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, NULL); -@@ -296,10 +507,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx +@@ -296,10 +532,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) GSS_C_NO_BUFFER); } - if (GSS_ERROR(major)) -+ if (GSS_ERROR(major) || intctx != NULL) ++ if (GSS_ERROR(major) || intctx != NULL) ssh_gssapi_delete_ctx(ctx); return (!GSS_ERROR(major)); @@ -487,7 +771,7 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + static OM_uint32 last_call = 0; + OM_uint32 lifetime, now, major, minor; + int equal; -+ ++ + now = time(NULL); + + if (ctxt) { @@ -515,8 +799,8 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c + + if (saved_mech == GSS_C_NO_OID) + return 0; -+ -+ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, ++ ++ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, + &name, &lifetime, NULL, NULL); + if (major == GSS_S_CREDENTIALS_EXPIRED) + return 0; @@ -535,42 +819,194 @@ diff -up openssh/gss-genr.c.gsskex openssh/gss-genr.c +} + #endif /* GSSAPI */ -diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c ---- openssh/gss-serv.c.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/gss-serv.c 2018-08-22 11:47:33.310216448 +0200 -@@ -44,17 +44,19 @@ - #include "session.h" - #include "misc.h" - #include "servconf.h" -+#include "uidswap.h" +diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c +index a151bc1e..8d2b677f 100644 +--- a/gss-serv-krb5.c ++++ b/gss-serv-krb5.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv-krb5.c,v 1.9 2018/07/09 21:37:55 markus Exp $ */ - #include "ssh-gss.h" -+#include "monitor_wrap.h" + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2007 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) + krb5_error_code problem; + krb5_principal princ; + OM_uint32 maj_status, min_status; +- int len; ++ const char *new_ccname, *new_cctype; + const char *errmsg; - extern ServerOptions options; + if (client->creds == NULL) { +@@ -180,11 +180,26 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) + return; + } - static ssh_gssapi_client gssapi_client = -- { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, -- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; -+ { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL, -+ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL}, 0, 0}; +- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); ++ new_cctype = krb5_cc_get_type(krb_context, ccache); ++ new_ccname = krb5_cc_get_name(krb_context, ccache); ++ + client->store.envvar = "KRB5CCNAME"; +- len = strlen(client->store.filename) + 6; +- client->store.envval = xmalloc(len); +- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); ++#ifdef USE_CCAPI ++ xasprintf(&client->store.envval, "API:%s", new_ccname); ++ client->store.filename = NULL; ++#else ++ if (new_ccname[0] == ':') ++ new_ccname++; ++ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); ++ if (strcmp(new_cctype, "DIR") == 0) { ++ char *p; ++ p = strrchr(client->store.envval, '/'); ++ if (p) ++ *p = '\0'; ++ } ++ if ((strcmp(new_cctype, "FILE") == 0) || (strcmp(new_cctype, "DIR") == 0)) ++ client->store.filename = xstrdup(new_ccname); ++#endif - ssh_gssapi_mech gssapi_null_mech = -- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; -+ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; + #ifdef USE_PAM + if (options.use_pam) +@@ -193,9 +208,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) - #ifdef KRB5 - extern ssh_gssapi_mech gssapi_kerberos_mech; -@@ -141,6 +143,28 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss + krb5_cc_close(krb_context, ccache); + ++ client->store.data = krb_context; ++ + return; } - /* Unprivileged */ -+char * -+ssh_gssapi_server_mechanisms() { ++int ++ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, ++ ssh_gssapi_client *client) ++{ ++ krb5_ccache ccache = NULL; ++ krb5_principal principal = NULL; ++ char *name = NULL; ++ krb5_error_code problem; ++ OM_uint32 maj_status, min_status; ++ ++ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { ++ logit("krb5_cc_resolve(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ return 0; ++ } ++ ++ /* Find out who the principal in this cache is */ ++ if ((problem = krb5_cc_get_principal(krb_context, ccache, ++ &principal))) { ++ logit("krb5_cc_get_principal(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { ++ logit("krb5_unparse_name(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ ++ if (strcmp(name,client->exportedname.value)!=0) { ++ debug("Name in local credentials cache differs. Not storing"); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ krb5_free_unparsed_name(krb_context, name); ++ return 0; ++ } ++ krb5_free_unparsed_name(krb_context, name); ++ ++ /* Name matches, so lets get on with it! */ ++ ++ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { ++ logit("krb5_cc_initialize(): %.100s", ++ krb5_get_err_text(krb_context, problem)); ++ krb5_free_principal(krb_context, principal); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ krb5_free_principal(krb_context, principal); ++ ++ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, ++ ccache))) { ++ logit("gss_krb5_copy_ccache() failed. Sorry!"); ++ krb5_cc_close(krb_context, ccache); ++ return 0; ++ } ++ ++ return 1; ++} ++ + ssh_gssapi_mech gssapi_kerberos_mech = { + "toWM5Slw5Ew8Mqkay+al2g==", + "Kerberos", +@@ -203,7 +285,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { + NULL, + &ssh_gssapi_krb5_userok, + NULL, +- &ssh_gssapi_krb5_storecreds ++ &ssh_gssapi_krb5_storecreds, ++ &ssh_gssapi_krb5_updatecreds + }; + + #endif /* KRB5 */ +diff --git a/gss-serv.c b/gss-serv.c +index ab3a15f0..6ce56e92 100644 +--- a/gss-serv.c ++++ b/gss-serv.c +@@ -1,7 +1,7 @@ + /* $OpenBSD: gss-serv.c,v 1.32 2020/03/13 03:17:07 djm Exp $ */ + + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -44,17 +44,19 @@ + #include "session.h" + #include "misc.h" + #include "servconf.h" ++#include "uidswap.h" + + #include "ssh-gss.h" ++#include "monitor_wrap.h" + + extern ServerOptions options; + + static ssh_gssapi_client gssapi_client = +- { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, +- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; ++ { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL, ++ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0}; + + ssh_gssapi_mech gssapi_null_mech = +- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; ++ { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL, NULL}; + + #ifdef KRB5 + extern ssh_gssapi_mech gssapi_kerberos_mech; +@@ -140,6 +142,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) + return (ssh_gssapi_acquire_cred(*ctx)); + } + ++/* Unprivileged */ ++char * ++ssh_gssapi_server_mechanisms(void) { + if (supported_oids == NULL) + ssh_gssapi_prepare_supported_oids(); + return (ssh_gssapi_kex_mechs(supported_oids, -+ &ssh_gssapi_server_check_mech, NULL, NULL)); ++ &ssh_gssapi_server_check_mech, NULL, NULL, ++ options.gss_kex_algorithms)); +} + +/* Unprivileged */ @@ -579,18 +1015,17 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c + const char *dummy) { + Gssctxt *ctx = NULL; + int res; -+ ++ + res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); + ssh_gssapi_delete_ctx(&ctx); + + return (res); +} + -+/* Unprivileged */ + /* Unprivileged */ void ssh_gssapi_supported_oids(gss_OID_set *oidset) - { -@@ -150,7 +174,9 @@ ssh_gssapi_supported_oids(gss_OID_set *o +@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset) gss_OID_set supported; gss_create_empty_oid_set(&min_status, oidset); @@ -601,7 +1036,7 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c while (supported_mechs[i]->name != NULL) { if (GSS_ERROR(gss_test_oid_set_member(&min_status, -@@ -276,8 +302,48 @@ OM_uint32 +@@ -276,8 +303,48 @@ OM_uint32 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) { int i = 0; @@ -617,41 +1052,41 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c + return GSS_S_COMPLETE; + } + -+ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, -+ ctx->client_creds, ctx->oid, &new_name, ++ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, ++ ctx->client_creds, ctx->oid, &new_name, + NULL, NULL, NULL))) { + ssh_gssapi_error(ctx); + return (ctx->major); + } -+ -+ ctx->major = gss_compare_name(&ctx->minor, client->name, + +- gss_buffer_desc ename; ++ ctx->major = gss_compare_name(&ctx->minor, client->name, + new_name, &equal); + + if (GSS_ERROR(ctx->major)) { + ssh_gssapi_error(ctx); + return (ctx->major); + } -+ ++ + if (!equal) { + debug("Rekeyed credentials have different name"); + return GSS_S_COMPLETE; + } + + debug("Marking rekeyed credentials for export"); - -- gss_buffer_desc ename; ++ + gss_release_name(&ctx->minor, &client->name); + gss_release_cred(&ctx->minor, &client->creds); + client->name = new_name; + client->creds = ctx->client_creds; -+ ctx->client_creds = GSS_C_NO_CREDENTIAL; ++ ctx->client_creds = GSS_C_NO_CREDENTIAL; + client->updated = 1; + return GSS_S_COMPLETE; + } client->mech = NULL; -@@ -292,6 +358,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g +@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) if (client->mech == NULL) return GSS_S_FAILURE; @@ -665,7 +1100,7 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, &client->displayname, NULL))) { ssh_gssapi_error(ctx); -@@ -309,6 +382,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g +@@ -309,6 +383,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) return (ctx->major); } @@ -674,7 +1109,7 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c /* We can't copy this structure, so we just move the pointer to it */ client->creds = ctx->client_creds; ctx->client_creds = GSS_C_NO_CREDENTIAL; -@@ -319,11 +394,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_g +@@ -319,11 +395,20 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) void ssh_gssapi_cleanup_creds(void) { @@ -691,7 +1126,7 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c + debug("%s: krb5_cc_resolve(): %.100s", __func__, + krb5_get_err_text(gssapi_client.store.data, problem)); + } else if ((problem = krb5_cc_destroy(gssapi_client.store.data, ccache))) { -+ debug("%s: krb5_cc_resolve(): %.100s", __func__, ++ debug("%s: krb5_cc_destroy(): %.100s", __func__, + krb5_get_err_text(gssapi_client.store.data, problem)); + } else { + krb5_free_context(gssapi_client.store.data); @@ -700,16 +1135,20 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c } } -@@ -356,7 +440,7 @@ ssh_gssapi_do_child(char ***envp, u_int +@@ -356,19 +441,23 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep) /* Privileged */ int -ssh_gssapi_userok(char *user) -+ssh_gssapi_userok(char *user, struct passwd *pw) ++ssh_gssapi_userok(char *user, struct passwd *pw, int kex) { OM_uint32 lmin; -@@ -366,9 +450,11 @@ ssh_gssapi_userok(char *user) ++ (void) kex; /* used in privilege separation */ ++ + if (gssapi_client.exportedname.length == 0 || + gssapi_client.exportedname.value == NULL) { + debug("No suitable client data"); return 0; } if (gssapi_client.mech && gssapi_client.mech->userok) @@ -723,14 +1162,14 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c /* Destroy delegated credentials if userok fails */ gss_release_buffer(&lmin, &gssapi_client.displayname); gss_release_buffer(&lmin, &gssapi_client.exportedname); -@@ -382,14 +468,89 @@ ssh_gssapi_userok(char *user) +@@ -382,14 +471,90 @@ ssh_gssapi_userok(char *user) return (0); } -/* Privileged */ -OM_uint32 -ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) -+/* These bits are only used for rekeying. The unpriviledged child is running ++/* These bits are only used for rekeying. The unpriviledged child is running + * as the user, the monitor is root. + * + * In the child, we want to : @@ -741,7 +1180,7 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c +/* Stuff for PAM */ + +#ifdef USE_PAM -+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, ++static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, + struct pam_response **resp, void *data) { - ctx->major = gss_verify_mic(&ctx->minor, ctx->context, @@ -752,19 +1191,20 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c - return (ctx->major); +void -+ssh_gssapi_rekey_creds() { ++ssh_gssapi_rekey_creds(void) { + int ok; -+ int ret; +#ifdef USE_PAM ++ int ret; + pam_handle_t *pamh = NULL; + struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; + char *envstr; +#endif + -+ if (gssapi_client.store.envval == NULL && ++ if (gssapi_client.store.filename == NULL && ++ gssapi_client.store.envval == NULL && + gssapi_client.store.envvar == NULL) + return; -+ ++ + ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); + + if (!ok) @@ -787,7 +1227,7 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c + if (ret) + return; + -+ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, ++ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, + gssapi_client.store.envval); + + ret = pam_putenv(pamh, envstr); @@ -797,7 +1237,7 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c +#endif +} + -+int ++int +ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { + int ok = 0; + @@ -819,137 +1259,17 @@ diff -up openssh/gss-serv.c.gsskex openssh/gss-serv.c } /* Privileged */ -diff -up openssh/gss-serv-krb5.c.gsskex openssh/gss-serv-krb5.c ---- openssh/gss-serv-krb5.c.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/gss-serv-krb5.c 2018-08-22 11:47:33.311216457 +0200 -@@ -120,7 +120,7 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - krb5_error_code problem; - krb5_principal princ; - OM_uint32 maj_status, min_status; -- int len; -+ const char *new_ccname, *new_cctype; - const char *errmsg; - - if (client->creds == NULL) { -@@ -180,11 +180,23 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - return; - } - -- client->store.filename = xstrdup(krb5_cc_get_name(krb_context, ccache)); -+ new_cctype = krb5_cc_get_type(krb_context, ccache); -+ new_ccname = krb5_cc_get_name(krb_context, ccache); -+ - client->store.envvar = "KRB5CCNAME"; -- len = strlen(client->store.filename) + 6; -- client->store.envval = xmalloc(len); -- snprintf(client->store.envval, len, "FILE:%s", client->store.filename); -+#ifdef USE_CCAPI -+ xasprintf(&client->store.envval, "API:%s", new_ccname); -+#else -+ if (new_ccname[0] == ':') -+ new_ccname++; -+ xasprintf(&client->store.envval, "%s:%s", new_cctype, new_ccname); -+ if (strcmp(new_cctype, "DIR") == 0) { -+ char *p; -+ p = strrchr(client->store.envval, '/'); -+ if (p) -+ *p = '\0'; -+ } -+#endif - - #ifdef USE_PAM - if (options.use_pam) -@@ -193,9 +205,76 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_cl - - krb5_cc_close(krb_context, ccache); - -+ client->store.data = krb_context; -+ - return; - } - -+int -+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, -+ ssh_gssapi_client *client) -+{ -+ krb5_ccache ccache = NULL; -+ krb5_principal principal = NULL; -+ char *name = NULL; -+ krb5_error_code problem; -+ OM_uint32 maj_status, min_status; -+ -+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { -+ logit("krb5_cc_resolve(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ return 0; -+ } -+ -+ /* Find out who the principal in this cache is */ -+ if ((problem = krb5_cc_get_principal(krb_context, ccache, -+ &principal))) { -+ logit("krb5_cc_get_principal(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ if ((problem = krb5_unparse_name(krb_context, principal, &name))) { -+ logit("krb5_unparse_name(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ -+ if (strcmp(name,client->exportedname.value)!=0) { -+ debug("Name in local credentials cache differs. Not storing"); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ krb5_free_unparsed_name(krb_context, name); -+ return 0; -+ } -+ krb5_free_unparsed_name(krb_context, name); -+ -+ /* Name matches, so lets get on with it! */ -+ -+ if ((problem = krb5_cc_initialize(krb_context, ccache, principal))) { -+ logit("krb5_cc_initialize(): %.100s", -+ krb5_get_err_text(krb_context, problem)); -+ krb5_free_principal(krb_context, principal); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ krb5_free_principal(krb_context, principal); -+ -+ if ((maj_status = gss_krb5_copy_ccache(&min_status, client->creds, -+ ccache))) { -+ logit("gss_krb5_copy_ccache() failed. Sorry!"); -+ krb5_cc_close(krb_context, ccache); -+ return 0; -+ } -+ -+ return 1; -+} -+ - ssh_gssapi_mech gssapi_kerberos_mech = { - "toWM5Slw5Ew8Mqkay+al2g==", - "Kerberos", -@@ -203,7 +282,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { - NULL, - &ssh_gssapi_krb5_userok, - NULL, -- &ssh_gssapi_krb5_storecreds -+ &ssh_gssapi_krb5_storecreds, -+ &ssh_gssapi_krb5_updatecreds - }; +diff --git a/kex.c b/kex.c +index ce85f043..574c7609 100644 +--- a/kex.c ++++ b/kex.c +@@ -57,11 +57,16 @@ + #include "misc.h" + #include "dispatch.h" + #include "monitor.h" ++#include "xmalloc.h" - #endif /* KRB5 */ -diff -up openssh/kex.c.gsskex openssh/kex.c ---- openssh/kex.c.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/kex.c 2018-08-22 11:47:33.311216457 +0200 -@@ -54,6 +54,10 @@ + #include "ssherr.h" #include "sshbuf.h" #include "digest.h" @@ -960,38 +1280,228 @@ diff -up openssh/kex.c.gsskex openssh/kex.c /* prototype */ static int kex_choose_conf(struct ssh *); static int kex_input_newkeys(int, u_int32_t, struct ssh *); -@@ -103,6 +107,11 @@ static const struct kexalg kexalgs[] = { - { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, - { KEX_CURVE25519_SHA256_OLD, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, +@@ -115,15 +120,28 @@ static const struct kexalg kexalgs[] = { #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ + { NULL, 0, -1, -1}, + }; ++static const struct kexalg gss_kexalgs[] = { +#ifdef GSSAPI + { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, + { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, + { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, ++ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 }, ++ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256, ++ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, ++ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, +#endif - { NULL, -1, -1, -1}, - }; ++ { NULL, 0, -1, -1}, ++}; -@@ -136,6 +145,12 @@ kex_alg_by_name(const char *name) - for (k = kexalgs; k->name != NULL; k++) { - if (strcmp(k->name, name) == 0) - return k; -+#ifdef GSSAPI -+ if (strncmp(name, "gss-", 4) == 0) { -+ if (strncmp(k->name, name, strlen(k->name)) == 0) -+ return k; -+ } -+#endif - } - return NULL; +-char * +-kex_alg_list(char sep) ++static char * ++kex_alg_list_internal(char sep, const struct kexalg *algs) + { + char *ret = NULL, *tmp; + size_t nlen, rlen = 0; + const struct kexalg *k; + +- for (k = kexalgs; k->name != NULL; k++) { ++ for (k = algs; k->name != NULL; k++) { + if (ret != NULL) + ret[rlen++] = sep; + nlen = strlen(k->name); +@@ -138,6 +156,18 @@ kex_alg_list(char sep) + return ret; } -diff -up openssh/kexgssc.c.gsskex openssh/kexgssc.c ---- openssh/kexgssc.c.gsskex 2018-08-22 11:47:33.311216457 +0200 -+++ openssh/kexgssc.c 2018-08-22 11:47:33.311216457 +0200 -@@ -0,0 +1,338 @@ -+/* -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. -+ * + ++char * ++kex_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, kexalgs); ++} ++ ++char * ++kex_gss_alg_list(char sep) ++{ ++ return kex_alg_list_internal(sep, gss_kexalgs); ++} ++ + static const struct kexalg * + kex_alg_by_name(const char *name) + { +@@ -147,6 +177,10 @@ kex_alg_by_name(const char *name) + if (strcmp(k->name, name) == 0) + return k; + } ++ for (k = gss_kexalgs; k->name != NULL; k++) { ++ if (strncmp(k->name, name, strlen(k->name)) == 0) ++ return k; ++ } + return NULL; + } + +@@ -315,6 +349,29 @@ kex_assemble_names(char **listp, const char *def, const char *all) + return r; + } + ++/* Validate GSS KEX method name list */ ++int ++kex_gss_names_valid(const char *names) ++{ ++ char *s, *cp, *p; ++ ++ if (names == NULL || *names == '\0') ++ return 0; ++ s = cp = xstrdup(names); ++ for ((p = strsep(&cp, ",")); p && *p != '\0'; ++ (p = strsep(&cp, ","))) { ++ if (strncmp(p, "gss-", 4) != 0 ++ || kex_alg_by_name(p) == NULL) { ++ error("Unsupported KEX algorithm \"%.100s\"", p); ++ free(s); ++ return 0; ++ } ++ } ++ debug3("gss kex names ok: [%s]", names); ++ free(s); ++ return 1; ++} ++ + /* put algorithm proposal into buffer */ + int + kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX]) +@@ -698,6 +755,9 @@ kex_free(struct kex *kex) + sshbuf_free(kex->server_version); + sshbuf_free(kex->client_pub); + free(kex->session_id); ++#ifdef GSSAPI ++ free(kex->gss_host); ++#endif /* GSSAPI */ + free(kex->failed_choice); + free(kex->hostkey_alg); + free(kex->name); +diff --git a/kex.h b/kex.h +index a5ae6ac0..fe714141 100644 +--- a/kex.h ++++ b/kex.h +@@ -102,6 +102,15 @@ enum kex_exchange { + KEX_ECDH_SHA2, + KEX_C25519_SHA256, + KEX_KEM_SNTRUP4591761X25519_SHA512, ++#ifdef GSSAPI ++ KEX_GSS_GRP1_SHA1, ++ KEX_GSS_GRP14_SHA1, ++ KEX_GSS_GRP14_SHA256, ++ KEX_GSS_GRP16_SHA512, ++ KEX_GSS_GEX_SHA1, ++ KEX_GSS_NISTP256_SHA256, ++ KEX_GSS_C25519_SHA256, ++#endif + KEX_MAX + }; + +@@ -153,6 +162,12 @@ struct kex { + u_int flags; + int hash_alg; + int ec_nid; ++#ifdef GSSAPI ++ int gss_deleg_creds; ++ int gss_trust_dns; ++ char *gss_host; ++ char *gss_client; ++#endif + char *failed_choice; + int (*verify_host_key)(struct sshkey *, struct ssh *); + struct sshkey *(*load_host_public_key)(int, int, struct ssh *); +@@ -174,8 +189,10 @@ struct kex { + + int kex_names_valid(const char *); + char *kex_alg_list(char); ++char *kex_gss_alg_list(char); + char *kex_names_cat(const char *, const char *); + int kex_assemble_names(char **, const char *, const char *); ++int kex_gss_names_valid(const char *); + + int kex_exchange_identification(struct ssh *, int, const char *); + +@@ -202,6 +219,12 @@ int kexgex_client(struct ssh *); + int kexgex_server(struct ssh *); + int kex_gen_client(struct ssh *); + int kex_gen_server(struct ssh *); ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++int kexgssgex_client(struct ssh *); ++int kexgssgex_server(struct ssh *); ++int kexgss_client(struct ssh *); ++int kexgss_server(struct ssh *); ++#endif + + int kex_dh_keypair(struct kex *); + int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **, +@@ -234,6 +257,12 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *, + const BIGNUM *, const u_char *, size_t, + u_char *, size_t *); + ++int kex_gen_hash(int hash_alg, const struct sshbuf *client_version, ++ const struct sshbuf *server_version, const struct sshbuf *client_kexinit, ++ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob, ++ const struct sshbuf *client_pub, const struct sshbuf *server_pub, ++ const struct sshbuf *shared_secret, u_char *hash, size_t *hashlen); ++ + void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE]) + __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) + __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))); +diff --git a/kexdh.c b/kexdh.c +index 67133e33..edaa4676 100644 +--- a/kexdh.c ++++ b/kexdh.c +@@ -48,13 +48,23 @@ kex_dh_keygen(struct kex *kex) + { + switch (kex->kex_type) { + case KEX_DH_GRP1_SHA1: ++#ifdef GSSAPI ++ case KEX_GSS_GRP1_SHA1: ++#endif + kex->dh = dh_new_group1(); + break; + case KEX_DH_GRP14_SHA1: + case KEX_DH_GRP14_SHA256: ++#ifdef GSSAPI ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++#endif + kex->dh = dh_new_group14(); + break; + case KEX_DH_GRP16_SHA512: ++#ifdef GSSAPI ++ case KEX_GSS_GRP16_SHA512: ++#endif + kex->dh = dh_new_group16(); + break; + case KEX_DH_GRP18_SHA512: +diff --git a/kexgen.c b/kexgen.c +index 69348b96..c0e8c2f4 100644 +--- a/kexgen.c ++++ b/kexgen.c +@@ -44,7 +44,7 @@ + static int input_kex_gen_init(int, u_int32_t, struct ssh *); + static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh); + +-static int ++int + kex_gen_hash( + int hash_alg, + const struct sshbuf *client_version, +diff --git a/kexgssc.c b/kexgssc.c +new file mode 100644 +index 00000000..f6e1405e +--- /dev/null ++++ b/kexgssc.c +@@ -0,0 +1,606 @@ ++/* ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. ++ * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: @@ -1015,7 +1525,7 @@ diff -up openssh/kexgssc.c.gsskex openssh/kexgssc.c + +#include "includes.h" + -+#ifdef GSSAPI ++#if defined(GSSAPI) && defined(WITH_OPENSSL) + +#include "includes.h" + @@ -1034,111 +1544,88 @@ diff -up openssh/kexgssc.c.gsskex openssh/kexgssc.c +#include "packet.h" +#include "dh.h" +#include "digest.h" ++#include "ssherr.h" + +#include "ssh-gss.h" + +int -+kexgss_client(struct ssh *ssh) { -+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; -+ gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; ++kexgss_client(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, ++ recv_tok = GSS_C_EMPTY_BUFFER, ++ gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; + Gssctxt *ctxt; + OM_uint32 maj_status, min_status, ret_flags; -+ u_int klen, kout, slen = 0, strlen; -+ DH *dh; -+ BIGNUM *dh_server_pub = NULL; -+ BIGNUM *shared_secret = NULL; -+ BIGNUM *p = NULL; -+ BIGNUM *g = NULL; -+ u_char *kbuf; -+ u_char *serverhostkey = NULL; -+ u_char *empty = ""; -+ char *msg; -+ char *lang; ++ struct sshbuf *server_blob = NULL; ++ struct sshbuf *shared_secret = NULL; ++ struct sshbuf *server_host_key_blob = NULL; ++ struct sshbuf *empty = NULL; ++ u_char *msg; + int type = 0; + int first = 1; -+ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t hashlen; ++ u_char c; ++ int r; + -+ /* Initialise our GSSAPI world */ ++ /* Initialise our GSSAPI world */ + ssh_gssapi_build_ctx(&ctxt); -+ if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type) ++ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) + == GSS_C_NO_OID) + fatal("Couldn't identify host exchange"); + -+ if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host)) ++ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) + fatal("Couldn't import hostname"); + -+ if (ssh->kex->gss_client && -+ ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client)) ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(ctxt, kex->gss_client)) + fatal("Couldn't acquire client credentials"); + -+ switch (ssh->kex->kex_type) { ++ /* Step 1 */ ++ switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: -+ dh = dh_new_group1(); -+ break; + case KEX_GSS_GRP14_SHA1: -+ dh = dh_new_group14(); ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_keypair(kex); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_keypair(kex); + break; -+ case KEX_GSS_GEX_SHA1: -+ debug("Doing group exchange\n"); -+ nbits = dh_estimate(ssh->kex->we_need * 8); -+ packet_start(SSH2_MSG_KEXGSS_GROUPREQ); -+ packet_put_int(min); -+ packet_put_int(nbits); -+ packet_put_int(max); -+ -+ packet_send(); -+ -+ packet_read_expect(SSH2_MSG_KEXGSS_GROUP); -+ -+ if ((p = BN_new()) == NULL) -+ fatal("BN_new() failed"); -+ packet_get_bignum2(p); -+ if ((g = BN_new()) == NULL) -+ fatal("BN_new() failed"); -+ packet_get_bignum2(g); -+ packet_check_eom(); -+ -+ if (BN_num_bits(p) < min || BN_num_bits(p) > max) -+ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", -+ min, BN_num_bits(p), max); -+ -+ dh = dh_new_group(g, p); ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_keypair(kex); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); + } -+ -+ /* Step 1 - e is dh->pub_key */ -+ dh_gen_key(dh, ssh->kex->we_need * 8); -+ -+ /* This is f, we initialise it now to make life easier */ -+ dh_server_pub = BN_new(); -+ if (dh_server_pub == NULL) -+ fatal("dh_server_pub == NULL"); ++ if (r != 0) ++ return r; + + token_ptr = GSS_C_NO_BUFFER; -+ ++ + do { + debug("Calling gss_init_sec_context"); -+ ++ + maj_status = ssh_gssapi_init_ctx(ctxt, -+ ssh->kex->gss_deleg_creds, token_ptr, &send_tok, ++ kex->gss_deleg_creds, token_ptr, &send_tok, + &ret_flags); + + if (GSS_ERROR(maj_status)) { ++ /* XXX Useles code: Missing send? */ + if (send_tok.length != 0) { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, -+ send_tok.length); ++ if ((r = sshpkt_start(ssh, ++ SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); + } + fatal("gss_init_context failed"); + } + + /* If we've got an old receive buffer get rid of it */ + if (token_ptr != GSS_C_NO_BUFFER) -+ free(recv_tok.value); ++ gss_release_buffer(&min_status, &recv_tok); + + if (maj_status == GSS_S_COMPLETE) { + /* If mutual state flag is not true, kex fails */ @@ -1150,75 +1637,90 @@ diff -up openssh/kexgssc.c.gsskex openssh/kexgssc.c + fatal("Integrity check failed"); + } + -+ /* ++ /* + * If we have data to send, then the last message that we -+ * received cannot have been a 'complete'. ++ * received cannot have been a 'complete'. + */ + if (send_tok.length != 0) { + if (first) { -+ packet_start(SSH2_MSG_KEXGSS_INIT); -+ packet_put_string(send_tok.value, -+ send_tok.length); -+ packet_put_bignum2(dh->pub_key); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0 || ++ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); + first = 0; + } else { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, -+ send_tok.length); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0) ++ fatal("failed to construct packet: %s", ssh_err(r)); + } -+ packet_send(); ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("failed to send packet: %s", ssh_err(r)); + gss_release_buffer(&min_status, &send_tok); + + /* If we've sent them data, they should reply */ -+ do { -+ type = packet_read(); ++ do { ++ type = ssh_packet_read(ssh); + if (type == SSH2_MSG_KEXGSS_HOSTKEY) { + debug("Received KEXGSS_HOSTKEY"); -+ if (serverhostkey) ++ if (server_host_key_blob) + fatal("Server host key received more than once"); -+ serverhostkey = -+ packet_get_string(&slen); ++ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) ++ fatal("Failed to read server host key: %s", ssh_err(r)); + } + } while (type == SSH2_MSG_KEXGSS_HOSTKEY); + + switch (type) { + case SSH2_MSG_KEXGSS_CONTINUE: + debug("Received GSSAPI_CONTINUE"); -+ if (maj_status == GSS_S_COMPLETE) ++ if (maj_status == GSS_S_COMPLETE) + fatal("GSSAPI Continue received from server when complete"); -+ recv_tok.value = packet_get_string(&strlen); -+ recv_tok.length = strlen; ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); + break; + case SSH2_MSG_KEXGSS_COMPLETE: + debug("Received GSSAPI_COMPLETE"); -+ packet_get_bignum2(dh_server_pub); -+ msg_tok.value = packet_get_string(&strlen); -+ msg_tok.length = strlen; ++ if (msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &msg_tok)) != 0) ++ fatal("Failed to read message: %s", ssh_err(r)); + + /* Is there a token included? */ -+ if (packet_get_char()) { -+ recv_tok.value= -+ packet_get_string(&strlen); -+ recv_tok.length = strlen; ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc( ++ ssh, &recv_tok)) != 0) ++ fatal("Failed to read token: %s", ssh_err(r)); + /* If we're already complete - protocol error */ + if (maj_status == GSS_S_COMPLETE) -+ packet_disconnect("Protocol error: received token when complete"); -+ } else { -+ /* No token included */ -+ if (maj_status != GSS_S_COMPLETE) -+ packet_disconnect("Protocol error: did not receive final token"); ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ /* No token included */ ++ if (maj_status != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ if ((r = sshpkt_get_end(ssh)) != 0) { ++ fatal("Expecting end of packet."); + } + break; + case SSH2_MSG_KEXGSS_ERROR: + debug("Received Error"); -+ maj_status = packet_get_int(); -+ min_status = packet_get_int(); -+ msg = packet_get_string(NULL); -+ lang = packet_get_string(NULL); -+ fatal("GSSAPI Error: \n%.400s",msg); ++ if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || ++ (r = sshpkt_get_u32(ssh, &min_status)) != 0 || ++ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || ++ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt_get failed: %s", ssh_err(r)); ++ fatal("GSSAPI Error: \n%.400s", msg); + default: -+ packet_disconnect("Protocol error: didn't expect packet type %d", -+ type); ++ sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", ++ type); + } + token_ptr = &recv_tok; + } else { @@ -1228,92 +1730,358 @@ diff -up openssh/kexgssc.c.gsskex openssh/kexgssc.c + } + } while (maj_status & GSS_S_CONTINUE_NEEDED); + -+ /* -+ * We _must_ have received a COMPLETE message in reply from the -+ * server, which will have set dh_server_pub and msg_tok ++ /* ++ * We _must_ have received a COMPLETE message in reply from the ++ * server, which will have set server_blob and msg_tok + */ + + if (type != SSH2_MSG_KEXGSS_COMPLETE) + fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); + -+ /* Check f in range [1, p-1] */ -+ if (!dh_pub_is_valid(dh, dh_server_pub)) -+ packet_disconnect("bad server public DH value"); -+ -+ /* compute K=f^x mod p */ -+ klen = DH_size(dh); -+ kbuf = xmalloc(klen); -+ kout = DH_compute_key(kbuf, dh_server_pub, dh); -+ if ((int)kout < 0) -+ fatal("DH_compute_key: failed"); -+ -+ shared_secret = BN_new(); -+ if (shared_secret == NULL) -+ fatal("kexgss_client: BN_new failed"); -+ -+ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) -+ fatal("kexdh_client: BN_bin2bn failed"); -+ -+ memset(kbuf, 0, klen); -+ free(kbuf); -+ -+ hashlen = sizeof(hash); -+ switch (ssh->kex->kex_type) { ++ /* compute shared secret */ ++ switch (kex->kex_type) { + case KEX_GSS_GRP1_SHA1: + case KEX_GSS_GRP14_SHA1: -+ kex_dh_hash(ssh->kex->hash_alg, ssh->kex->client_version_string, -+ ssh->kex->server_version_string, -+ sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), -+ sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), -+ (serverhostkey ? serverhostkey : empty), slen, -+ dh->pub_key, /* e */ -+ dh_server_pub, /* f */ -+ shared_secret, /* K */ -+ hash, &hashlen -+ ); ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_dec(kex, server_blob, &shared_secret); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80) ++ fatal("The received key has MSB of last octet set!"); ++ r = kex_c25519_dec(kex, server_blob, &shared_secret); + break; -+ case KEX_GSS_GEX_SHA1: -+ kexgex_hash( -+ ssh->kex->hash_alg, -+ ssh->kex->client_version_string, -+ ssh->kex->server_version_string, -+ sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), -+ sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), -+ (serverhostkey ? serverhostkey : empty), slen, -+ min, nbits, max, -+ dh->p, dh->g, -+ dh->pub_key, -+ dh_server_pub, -+ shared_secret, -+ hash, &hashlen -+ ); ++ case KEX_GSS_NISTP256_SHA256: ++ if (sshbuf_len(server_blob) != 65) ++ fatal("The received NIST-P256 key did not match" ++ "expected length (expected 65, got %zu)", sshbuf_len(server_blob)); ++ ++ if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED) ++ fatal("The received NIST-P256 key does not have first octet 0x04"); ++ ++ r = kex_ecdh_dec(kex, server_blob, &shared_secret); + break; + default: -+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); ++ r = SSH_ERR_INVALID_ARGUMENT; ++ break; ++ } ++ if (r != 0) ++ goto out; ++ ++ if ((empty = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; + } + ++ hashlen = sizeof(hash); ++ if ((r = kex_gen_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->my, ++ kex->peer, ++ (server_host_key_blob ? server_host_key_blob : empty), ++ kex->client_pub, ++ server_blob, ++ shared_secret, ++ hash, &hashlen)) != 0) ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ + gssbuf.value = hash; + gssbuf.length = hashlen; + + /* Verify that the hash matches the MIC we just got. */ + if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) -+ packet_disconnect("Hash's MIC didn't verify"); ++ sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); + -+ free(msg_tok.value); ++ gss_release_buffer(&min_status, &msg_tok); + -+ DH_free(dh); -+ if (serverhostkey) -+ free(serverhostkey); -+ BN_clear_free(dh_server_pub); ++ if (kex->gss_deleg_creds) ++ ssh_gssapi_credentials_updated(ctxt); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++ ++out: ++ explicit_bzero(hash, sizeof(hash)); ++ explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key)); ++ sshbuf_free(empty); ++ sshbuf_free(server_host_key_blob); ++ sshbuf_free(server_blob); ++ sshbuf_free(shared_secret); ++ sshbuf_free(kex->client_pub); ++ kex->client_pub = NULL; ++ return r; ++} ++ ++int ++kexgssgex_client(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER, ++ recv_tok = GSS_C_EMPTY_BUFFER, gssbuf, ++ msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr; ++ Gssctxt *ctxt; ++ OM_uint32 maj_status, min_status, ret_flags; ++ struct sshbuf *shared_secret = NULL; ++ BIGNUM *p = NULL; ++ BIGNUM *g = NULL; ++ struct sshbuf *buf = NULL; ++ struct sshbuf *server_host_key_blob = NULL; ++ struct sshbuf *server_blob = NULL; ++ BIGNUM *dh_server_pub = NULL; ++ u_char *msg; ++ int type = 0; ++ int first = 1; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX; ++ struct sshbuf *empty = NULL; ++ u_char c; ++ int r; ++ ++ /* Initialise our GSSAPI world */ ++ ssh_gssapi_build_ctx(&ctxt); ++ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type) ++ == GSS_C_NO_OID) ++ fatal("Couldn't identify host exchange"); ++ ++ if (ssh_gssapi_import_name(ctxt, kex->gss_host)) ++ fatal("Couldn't import hostname"); ++ ++ if (kex->gss_client && ++ ssh_gssapi_client_identity(ctxt, kex->gss_client)) ++ fatal("Couldn't acquire client credentials"); ++ ++ debug("Doing group exchange"); ++ nbits = dh_estimate(kex->dh_need * 8); ++ ++ kex->min = DH_GRP_MIN; ++ kex->max = DH_GRP_MAX; ++ kex->nbits = nbits; ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 || ++ (r = sshpkt_put_u32(ssh, min)) != 0 || ++ (r = sshpkt_put_u32(ssh, nbits)) != 0 || ++ (r = sshpkt_put_u32(ssh, max)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("Failed to construct a packet: %s", ssh_err(r)); ++ ++ if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0) ++ fatal("Error: %s", ssh_err(r)); ++ ++ if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &g)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("shpkt_get_bignum2 failed: %s", ssh_err(r)); ++ ++ if (BN_num_bits(p) < min || BN_num_bits(p) > max) ++ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d", ++ min, BN_num_bits(p), max); ++ ++ if ((kex->dh = dh_new_group(g, p)) == NULL) ++ fatal("dn_new_group() failed"); ++ p = g = NULL; /* belong to kex->dh now */ ++ ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) ++ goto out; ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ ++ token_ptr = GSS_C_NO_BUFFER; ++ ++ do { ++ /* Step 2 - call GSS_Init_sec_context() */ ++ debug("Calling gss_init_sec_context"); ++ ++ maj_status = ssh_gssapi_init_ctx(ctxt, ++ kex->gss_deleg_creds, token_ptr, &send_tok, ++ &ret_flags); ++ ++ if (GSS_ERROR(maj_status)) { ++ /* XXX Useles code: Missing send? */ ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_start(ssh, ++ SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("gss_init_context failed"); ++ } ++ ++ /* If we've got an old receive buffer get rid of it */ ++ if (token_ptr != GSS_C_NO_BUFFER) ++ gss_release_buffer(&min_status, &recv_tok); ++ ++ if (maj_status == GSS_S_COMPLETE) { ++ /* If mutual state flag is not true, kex fails */ ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual authentication failed"); ++ ++ /* If integ avail flag is not true kex fails */ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity check failed"); ++ } ++ ++ /* ++ * If we have data to send, then the last message that we ++ * received cannot have been a 'complete'. ++ */ ++ if (send_tok.length != 0) { ++ if (first) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, ++ send_tok.length)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ first = 0; ++ } else { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh,send_tok.value, ++ send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt_send failed: %s", ssh_err(r)); ++ gss_release_buffer(&min_status, &send_tok); ++ ++ /* If we've sent them data, they should reply */ ++ do { ++ type = ssh_packet_read(ssh); ++ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { ++ debug("Received KEXGSS_HOSTKEY"); ++ if (server_host_key_blob) ++ fatal("Server host key received more than once"); ++ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); ++ ++ switch (type) { ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ debug("Received GSSAPI_CONTINUE"); ++ if (maj_status == GSS_S_COMPLETE) ++ fatal("GSSAPI Continue received from server when complete"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ break; ++ case SSH2_MSG_KEXGSS_COMPLETE: ++ debug("Received GSSAPI_COMPLETE"); ++ if (msg_tok.value != NULL) ++ fatal("Received GSSAPI_COMPLETE twice?"); ++ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 || ++ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &msg_tok)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ /* Is there a token included? */ ++ if ((r = sshpkt_get_u8(ssh, &c)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ if (c) { ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc( ++ ssh, &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ /* If we're already complete - protocol error */ ++ if (maj_status == GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: received token when complete"); ++ } else { ++ /* No token included */ ++ if (maj_status != GSS_S_COMPLETE) ++ sshpkt_disconnect(ssh, "Protocol error: did not receive final token"); ++ } ++ break; ++ case SSH2_MSG_KEXGSS_ERROR: ++ debug("Received Error"); ++ if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 || ++ (r = sshpkt_get_u32(ssh, &min_status)) != 0 || ++ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 || ++ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */ ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ fatal("GSSAPI Error: \n%.400s", msg); ++ default: ++ sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d", ++ type); ++ } ++ token_ptr = &recv_tok; ++ } else { ++ /* No data, and not complete */ ++ if (maj_status != GSS_S_COMPLETE) ++ fatal("Not complete, and no token output"); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ /* ++ * We _must_ have received a COMPLETE message in reply from the ++ * server, which will have set dh_server_pub and msg_tok ++ */ ++ ++ if (type != SSH2_MSG_KEXGSS_COMPLETE) ++ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); ++ ++ /* 7. C verifies that the key Q_S is valid */ ++ /* 8. C computes shared secret */ ++ if ((buf = sshbuf_new()) == NULL || ++ (r = sshbuf_put_stringb(buf, server_blob)) != 0 || ++ (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0) ++ goto out; ++ sshbuf_free(buf); ++ buf = NULL; ++ ++ if ((shared_secret = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0) ++ goto out; ++ if ((empty = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ hashlen = sizeof(hash); ++ if ((r = kexgex_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->my, ++ kex->peer, ++ (server_host_key_blob ? server_host_key_blob : empty), ++ kex->min, kex->nbits, kex->max, ++ dh_p, dh_g, ++ pub_key, ++ dh_server_pub, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), ++ hash, &hashlen)) != 0) ++ fatal("Failed to calculate hash: %s", ssh_err(r)); ++ ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; ++ ++ /* Verify that the hash matches the MIC we just got. */ ++ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) ++ sshpkt_disconnect(ssh, "Hash's MIC didn't verify"); ++ ++ gss_release_buffer(&min_status, &msg_tok); + + /* save session id */ -+ if (ssh->kex->session_id == NULL) { -+ ssh->kex->session_id_len = hashlen; -+ ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); -+ memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); ++ if (kex->session_id == NULL) { ++ kex->session_id_len = hashlen; ++ kex->session_id = xmalloc(kex->session_id_len); ++ memcpy(kex->session_id, hash, kex->session_id_len); + } + -+ if (ssh->kex->gss_deleg_creds) ++ if (kex->gss_deleg_creds) + ssh_gssapi_credentials_updated(ctxt); + + if (gss_kex_context == NULL) @@ -1321,16 +2089,28 @@ diff -up openssh/kexgssc.c.gsskex openssh/kexgssc.c + else + ssh_gssapi_delete_ctx(&ctxt); + -+ kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); -+ BN_clear_free(shared_secret); -+ return kex_send_newkeys(ssh); ++ /* Finally derive the keys and send them */ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++out: ++ sshbuf_free(buf); ++ sshbuf_free(server_blob); ++ sshbuf_free(empty); ++ explicit_bzero(hash, sizeof(hash)); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ BN_clear_free(dh_server_pub); ++ sshbuf_free(shared_secret); ++ sshbuf_free(server_host_key_blob); ++ return r; +} -+ -+#endif /* GSSAPI */ -diff -up openssh/kexgsss.c.gsskex openssh/kexgsss.c ---- openssh/kexgsss.c.gsskex 2018-08-22 11:47:33.311216457 +0200 -+++ openssh/kexgsss.c 2018-08-22 11:47:33.311216457 +0200 -@@ -0,0 +1,297 @@ ++#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ +diff --git a/kexgsss.c b/kexgsss.c +new file mode 100644 +index 00000000..60bc02de +--- /dev/null ++++ b/kexgsss.c +@@ -0,0 +1,474 @@ +/* + * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * @@ -1357,7 +2137,7 @@ diff -up openssh/kexgsss.c.gsskex openssh/kexgsss.c + +#include "includes.h" + -+#ifdef GSSAPI ++#if defined(GSSAPI) && defined(WITH_OPENSSL) + +#include + @@ -1379,37 +2159,37 @@ diff -up openssh/kexgsss.c.gsskex openssh/kexgsss.c +#include "servconf.h" +#include "ssh-gss.h" +#include "digest.h" ++#include "ssherr.h" + +extern ServerOptions options; + +int +kexgss_server(struct ssh *ssh) +{ ++ struct kex *kex = ssh->kex; + OM_uint32 maj_status, min_status; -+ -+ /* ++ ++ /* + * Some GSSAPI implementations use the input value of ret_flags (an -+ * output variable) as a means of triggering mechanism specific -+ * features. Initializing it to zero avoids inadvertently -+ * activating this non-standard behaviour. ++ * output variable) as a means of triggering mechanism specific ++ * features. Initializing it to zero avoids inadvertently ++ * activating this non-standard behaviour. + */ + + OM_uint32 ret_flags = 0; + gss_buffer_desc gssbuf, recv_tok, msg_tok; + gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; + Gssctxt *ctxt = NULL; -+ u_int slen, klen, kout; -+ u_char *kbuf; -+ DH *dh; -+ int min = -1, max = -1, nbits = -1; -+ int cmin = -1, cmax = -1; /* client proposal */ -+ BIGNUM *shared_secret = NULL; -+ BIGNUM *dh_client_pub = NULL; ++ struct sshbuf *shared_secret = NULL; ++ struct sshbuf *client_pubkey = NULL; ++ struct sshbuf *server_pubkey = NULL; ++ struct sshbuf *empty = sshbuf_new(); + int type = 0; + gss_OID oid; + char *mechs; + u_char hash[SSH_DIGEST_MAX_LENGTH]; + size_t hashlen; ++ int r; + + /* Initialise GSSAPI */ + @@ -1417,12 +2197,13 @@ diff -up openssh/kexgsss.c.gsskex openssh/kexgsss.c + * in the GSSAPI code are no longer available. This kludges them back + * into life + */ -+ if (!ssh_gssapi_oid_table_ok()) -+ if ((mechs = ssh_gssapi_server_mechanisms())) -+ free(mechs); ++ if (!ssh_gssapi_oid_table_ok()) { ++ mechs = ssh_gssapi_server_mechanisms(); ++ free(mechs); ++ } + -+ debug2("%s: Identifying %s", __func__, ssh->kex->name); -+ oid = ssh_gssapi_id_kex(NULL, ssh->kex->name, ssh->kex->kex_type); ++ debug2("%s: Identifying %s", __func__, kex->name); ++ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); + if (oid == GSS_C_NO_OID) + fatal("Unknown gssapi mechanism"); + @@ -1431,95 +2212,82 @@ diff -up openssh/kexgsss.c.gsskex openssh/kexgsss.c + if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) + fatal("Unable to acquire credentials for the server"); + -+ switch (ssh->kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ dh = dh_new_group1(); -+ break; -+ case KEX_GSS_GRP14_SHA1: -+ dh = dh_new_group14(); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ debug("Doing group exchange"); -+ packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ); -+ /* store client proposal to provide valid signature */ -+ cmin = packet_get_int(); -+ nbits = packet_get_int(); -+ cmax = packet_get_int(); -+ min = MAX(DH_GRP_MIN, cmin); -+ max = MIN(DH_GRP_MAX, cmax); -+ packet_check_eom(); -+ if (max < min || nbits < min || max < nbits) -+ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", -+ min, nbits, max); -+ dh = PRIVSEP(choose_dh(min, nbits, max)); -+ if (dh == NULL) -+ packet_disconnect("Protocol error: no matching group found"); -+ -+ packet_start(SSH2_MSG_KEXGSS_GROUP); -+ packet_put_bignum2(dh->p); -+ packet_put_bignum2(dh->g); -+ packet_send(); -+ -+ packet_write_wait(); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); -+ } -+ -+ dh_gen_key(dh, ssh->kex->we_need * 8); -+ + do { -+ debug("Wait SSH2_MSG_GSSAPI_INIT"); -+ type = packet_read(); ++ debug("Wait SSH2_MSG_KEXGSS_INIT"); ++ type = ssh_packet_read(ssh); + switch(type) { + case SSH2_MSG_KEXGSS_INIT: -+ if (dh_client_pub != NULL) ++ if (client_pubkey != NULL) + fatal("Received KEXGSS_INIT after initialising"); -+ recv_tok.value = packet_get_string(&slen); -+ recv_tok.length = slen; -+ -+ if ((dh_client_pub = BN_new()) == NULL) -+ fatal("dh_client_pub == NULL"); -+ -+ packet_get_bignum2(dh_client_pub); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ switch (kex->kex_type) { ++ case KEX_GSS_GRP1_SHA1: ++ case KEX_GSS_GRP14_SHA1: ++ case KEX_GSS_GRP14_SHA256: ++ case KEX_GSS_GRP16_SHA512: ++ r = kex_dh_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ break; ++ case KEX_GSS_NISTP256_SHA256: ++ r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ break; ++ case KEX_GSS_C25519_SHA256: ++ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey, ++ &shared_secret); ++ break; ++ default: ++ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type); ++ } ++ if (r != 0) ++ goto out; + + /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ + break; + case SSH2_MSG_KEXGSS_CONTINUE: -+ recv_tok.value = packet_get_string(&slen); -+ recv_tok.length = slen; ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); + break; + default: -+ packet_disconnect( ++ sshpkt_disconnect(ssh, + "Protocol error: didn't expect packet type %d", + type); + } + -+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, + &send_tok, &ret_flags)); + -+ free(recv_tok.value); ++ gss_release_buffer(&min_status, &recv_tok); + + if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) + fatal("Zero length token output when incomplete"); + -+ if (dh_client_pub == NULL) ++ if (client_pubkey == NULL) + fatal("No client public key"); -+ ++ + if (maj_status & GSS_S_CONTINUE_NEEDED) { + debug("Sending GSSAPI_CONTINUE"); -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, send_tok.length); -+ packet_send(); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); + gss_release_buffer(&min_status, &send_tok); + } + } while (maj_status & GSS_S_CONTINUE_NEEDED); + + if (GSS_ERROR(maj_status)) { + if (send_tok.length > 0) { -+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); -+ packet_put_string(send_tok.value, send_tok.length); -+ packet_send(); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); + } + fatal("accept_ctx died"); + } @@ -1529,177 +2297,308 @@ diff -up openssh/kexgsss.c.gsskex openssh/kexgsss.c + + if (!(ret_flags & GSS_C_INTEG_FLAG)) + fatal("Integrity flag wasn't set"); -+ -+ if (!dh_pub_is_valid(dh, dh_client_pub)) -+ packet_disconnect("bad client public DH value"); + -+ klen = DH_size(dh); -+ kbuf = xmalloc(klen); -+ kout = DH_compute_key(kbuf, dh_client_pub, dh); -+ if ((int)kout < 0) -+ fatal("DH_compute_key: failed"); ++ hashlen = sizeof(hash); ++ if ((r = kex_gen_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->peer, ++ kex->my, ++ empty, ++ client_pubkey, ++ server_pubkey, ++ shared_secret, ++ hash, &hashlen)) != 0) ++ goto out; + -+ shared_secret = BN_new(); -+ if (shared_secret == NULL) -+ fatal("kexgss_server: BN_new failed"); ++ gssbuf.value = hash; ++ gssbuf.length = hashlen; + -+ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) -+ fatal("kexgss_server: BN_bin2bn failed"); ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) ++ fatal("Couldn't get MIC"); + -+ memset(kbuf, 0, klen); -+ free(kbuf); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || ++ (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 || ++ (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); + -+ hashlen = sizeof(hash); -+ switch (ssh->kex->kex_type) { -+ case KEX_GSS_GRP1_SHA1: -+ case KEX_GSS_GRP14_SHA1: -+ kex_dh_hash(ssh->kex->hash_alg, -+ ssh->kex->client_version_string, ssh->kex->server_version_string, -+ sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), -+ sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), -+ NULL, 0, /* Change this if we start sending host keys */ -+ dh_client_pub, dh->pub_key, shared_secret, -+ hash, &hashlen -+ ); -+ break; -+ case KEX_GSS_GEX_SHA1: -+ kexgex_hash( -+ ssh->kex->hash_alg, -+ ssh->kex->client_version_string, ssh->kex->server_version_string, -+ sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), -+ sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), -+ NULL, 0, -+ cmin, nbits, cmax, -+ dh->p, dh->g, -+ dh_client_pub, -+ dh->pub_key, -+ shared_secret, -+ hash, &hashlen -+ ); -+ break; -+ default: -+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); ++ if (send_tok.length != 0) { ++ if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } else { ++ if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ ++ fatal("sshpkt failed: %s", ssh_err(r)); + } ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt_send failed: %s", ssh_err(r)); + -+ BN_clear_free(dh_client_pub); ++ gss_release_buffer(&min_status, &send_tok); ++ gss_release_buffer(&min_status, &msg_tok); ++ ++ if (gss_kex_context == NULL) ++ gss_kex_context = ctxt; ++ else ++ ssh_gssapi_delete_ctx(&ctxt); ++ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); ++ ++ /* If this was a rekey, then save out any delegated credentials we ++ * just exchanged. */ ++ if (options.gss_store_rekey) ++ ssh_gssapi_rekey_creds(); ++out: ++ sshbuf_free(empty); ++ explicit_bzero(hash, sizeof(hash)); ++ sshbuf_free(shared_secret); ++ sshbuf_free(client_pubkey); ++ sshbuf_free(server_pubkey); ++ return r; ++} ++ ++int ++kexgssgex_server(struct ssh *ssh) ++{ ++ struct kex *kex = ssh->kex; ++ OM_uint32 maj_status, min_status; ++ ++ /* ++ * Some GSSAPI implementations use the input value of ret_flags (an ++ * output variable) as a means of triggering mechanism specific ++ * features. Initializing it to zero avoids inadvertently ++ * activating this non-standard behaviour. ++ */ ++ ++ OM_uint32 ret_flags = 0; ++ gss_buffer_desc gssbuf, recv_tok, msg_tok; ++ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; ++ Gssctxt *ctxt = NULL; ++ struct sshbuf *shared_secret = NULL; ++ int type = 0; ++ gss_OID oid; ++ char *mechs; ++ u_char hash[SSH_DIGEST_MAX_LENGTH]; ++ size_t hashlen; ++ BIGNUM *dh_client_pub = NULL; ++ const BIGNUM *pub_key, *dh_p, *dh_g; ++ int min = -1, max = -1, nbits = -1; ++ int cmin = -1, cmax = -1; /* client proposal */ ++ struct sshbuf *empty = sshbuf_new(); ++ int r; ++ ++ /* Initialise GSSAPI */ ++ ++ /* If we're rekeying, privsep means that some of the private structures ++ * in the GSSAPI code are no longer available. This kludges them back ++ * into life ++ */ ++ if (!ssh_gssapi_oid_table_ok()) ++ if ((mechs = ssh_gssapi_server_mechanisms())) ++ free(mechs); ++ ++ debug2("%s: Identifying %s", __func__, kex->name); ++ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type); ++ if (oid == GSS_C_NO_OID) ++ fatal("Unknown gssapi mechanism"); ++ ++ debug2("%s: Acquiring credentials", __func__); ++ ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) ++ fatal("Unable to acquire credentials for the server"); ++ ++ /* 5. S generates an ephemeral key pair (do the allocations early) */ ++ debug("Doing group exchange"); ++ ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUPREQ); ++ /* store client proposal to provide valid signature */ ++ if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 || ++ (r = sshpkt_get_u32(ssh, &nbits)) != 0 || ++ (r = sshpkt_get_u32(ssh, &cmax)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ kex->nbits = nbits; ++ kex->min = cmin; ++ kex->max = cmax; ++ min = MAX(DH_GRP_MIN, cmin); ++ max = MIN(DH_GRP_MAX, cmax); ++ nbits = MAXIMUM(DH_GRP_MIN, nbits); ++ nbits = MINIMUM(DH_GRP_MAX, nbits); ++ if (max < min || nbits < min || max < nbits) ++ fatal("GSS_GEX, bad parameters: %d !< %d !< %d", ++ min, nbits, max); ++ kex->dh = PRIVSEP(choose_dh(min, nbits, max)); ++ if (kex->dh == NULL) { ++ sshpkt_disconnect(ssh, "Protocol error: no matching group found"); ++ fatal("Protocol error: no matching group found"); ++ } ++ ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ if ((r = ssh_packet_write_wait(ssh)) != 0) ++ fatal("ssh_packet_write_wait: %s", ssh_err(r)); ++ ++ /* Compute our exchange value in parallel with the client */ ++ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0) ++ goto out; ++ ++ do { ++ debug("Wait SSH2_MSG_GSSAPI_INIT"); ++ type = ssh_packet_read(ssh); ++ switch(type) { ++ case SSH2_MSG_KEXGSS_INIT: ++ if (dh_client_pub != NULL) ++ fatal("Received KEXGSS_INIT after initialising"); ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ ++ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ ++ break; ++ case SSH2_MSG_KEXGSS_CONTINUE: ++ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh, ++ &recv_tok)) != 0 || ++ (r = sshpkt_get_end(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ break; ++ default: ++ sshpkt_disconnect(ssh, ++ "Protocol error: didn't expect packet type %d", ++ type); ++ } ++ ++ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, ++ &send_tok, &ret_flags)); ++ ++ gss_release_buffer(&min_status, &recv_tok); + -+ if (ssh->kex->session_id == NULL) { -+ ssh->kex->session_id_len = hashlen; -+ ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); -+ memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); ++ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) ++ fatal("Zero length token output when incomplete"); ++ ++ if (dh_client_pub == NULL) ++ fatal("No client public key"); ++ ++ if (maj_status & GSS_S_CONTINUE_NEEDED) { ++ debug("Sending GSSAPI_CONTINUE"); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ gss_release_buffer(&min_status, &send_tok); ++ } ++ } while (maj_status & GSS_S_CONTINUE_NEEDED); ++ ++ if (GSS_ERROR(maj_status)) { ++ if (send_tok.length > 0) { ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 || ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); ++ } ++ fatal("accept_ctx died"); + } + ++ if (!(ret_flags & GSS_C_MUTUAL_FLAG)) ++ fatal("Mutual Authentication flag wasn't set"); ++ ++ if (!(ret_flags & GSS_C_INTEG_FLAG)) ++ fatal("Integrity flag wasn't set"); ++ ++ /* calculate shared secret */ ++ if ((shared_secret = sshbuf_new()) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0) ++ goto out; ++ ++ DH_get0_key(kex->dh, &pub_key, NULL); ++ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g); ++ hashlen = sizeof(hash); ++ if ((r = kexgex_hash( ++ kex->hash_alg, ++ kex->client_version, ++ kex->server_version, ++ kex->peer, ++ kex->my, ++ empty, ++ cmin, nbits, cmax, ++ dh_p, dh_g, ++ dh_client_pub, ++ pub_key, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret), ++ hash, &hashlen)) != 0) ++ fatal("kexgex_hash failed: %s", ssh_err(r)); ++ + gssbuf.value = hash; + gssbuf.length = hashlen; + -+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) ++ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok)))) + fatal("Couldn't get MIC"); + -+ packet_start(SSH2_MSG_KEXGSS_COMPLETE); -+ packet_put_bignum2(dh->pub_key); -+ packet_put_string(msg_tok.value,msg_tok.length); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 || ++ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 || ++ (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); + + if (send_tok.length != 0) { -+ packet_put_char(1); /* true */ -+ packet_put_string(send_tok.value, send_tok.length); ++ if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */ ++ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); + } else { -+ packet_put_char(0); /* false */ ++ if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */ ++ fatal("sshpkt failed: %s", ssh_err(r)); + } -+ packet_send(); ++ if ((r = sshpkt_send(ssh)) != 0) ++ fatal("sshpkt failed: %s", ssh_err(r)); + + gss_release_buffer(&min_status, &send_tok); + gss_release_buffer(&min_status, &msg_tok); + + if (gss_kex_context == NULL) + gss_kex_context = ctxt; -+ else ++ else + ssh_gssapi_delete_ctx(&ctxt); + -+ DH_free(dh); -+ -+ kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); -+ BN_clear_free(shared_secret); -+ kex_send_newkeys(ssh); ++ /* Finally derive the keys and send them */ ++ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0) ++ r = kex_send_newkeys(ssh); + + /* If this was a rekey, then save out any delegated credentials we + * just exchanged. */ + if (options.gss_store_rekey) + ssh_gssapi_rekey_creds(); -+ return 0; ++out: ++ sshbuf_free(empty); ++ explicit_bzero(hash, sizeof(hash)); ++ DH_free(kex->dh); ++ kex->dh = NULL; ++ BN_clear_free(dh_client_pub); ++ sshbuf_free(shared_secret); ++ return r; +} -+#endif /* GSSAPI */ -diff -up openssh/kex.h.gsskex openssh/kex.h ---- openssh/kex.h.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/kex.h 2018-08-22 11:47:33.311216457 +0200 -@@ -100,6 +100,11 @@ enum kex_exchange { - KEX_DH_GEX_SHA256, - KEX_ECDH_SHA2, - KEX_C25519_SHA256, -+#ifdef GSSAPI -+ KEX_GSS_GRP1_SHA1, -+ KEX_GSS_GRP14_SHA1, -+ KEX_GSS_GEX_SHA1, -+#endif - KEX_MAX - }; - -@@ -148,6 +153,12 @@ struct kex { - u_int flags; - int hash_alg; - int ec_nid; -+#ifdef GSSAPI -+ int gss_deleg_creds; -+ int gss_trust_dns; -+ char *gss_host; -+ char *gss_client; -+#endif - char *client_version_string; - char *server_version_string; - char *failed_choice; -@@ -197,6 +208,10 @@ int kexecdh_client(struct ssh *); - int kexecdh_server(struct ssh *); - int kexc25519_client(struct ssh *); - int kexc25519_server(struct ssh *); -+#ifdef GSSAPI -+int kexgss_client(struct ssh *); -+int kexgss_server(struct ssh *); -+#endif - - int kex_dh_hash(int, const char *, const char *, - const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, -diff -up openssh/Makefile.in.gsskex openssh/Makefile.in ---- openssh/Makefile.in.gsskex 2018-08-22 11:47:33.312216465 +0200 -+++ openssh/Makefile.in 2018-08-22 13:19:54.955928277 +0200 -@@ -100,6 +100,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - readpass.o ttymodes.o xmalloc.o addrmatch.o \ - atomicio.o dispatch.o mac.o uuencode.o misc.o utf8.o \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ -+ kexgssc.o \ - msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ - ssh-pkcs11.o smult_curve25519_ref.o \ - poly1305.o chacha.o cipher-chachapoly.o \ -@@ -121,7 +122,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passw - auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ - auth2-none.o auth2-passwd.o auth2-pubkey.o \ - monitor.o monitor_wrap.o auth-krb5.o \ -- auth2-gss.o gss-serv.o gss-serv-krb5.o \ -+ auth2-gss.o gss-serv.o gss-serv-krb5.o kexgsss.o \ - loginrec.o auth-pam.o auth-shadow.o auth-sia.o md5crypt.o \ - sftp-server.o sftp-common.o \ - sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ -diff -up openssh/monitor.c.gsskex openssh/monitor.c ---- openssh/monitor.c.gsskex 2018-08-22 11:47:33.263216069 +0200 -+++ openssh/monitor.c 2018-08-22 13:22:19.589095240 +0200 -@@ -146,6 +146,8 @@ int mm_answer_gss_setup_ctx(int, struct - int mm_answer_gss_accept_ctx(int, struct sshbuf *); - int mm_answer_gss_userok(int, struct sshbuf *); - int mm_answer_gss_checkmic(int, struct sshbuf *); -+int mm_answer_gss_sign(int, struct sshbuf *); -+int mm_answer_gss_updatecreds(int, struct sshbuf *); ++#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */ +diff --git a/monitor.c b/monitor.c +index 2ce89fe9..ebf76c7f 100644 +--- a/monitor.c ++++ b/monitor.c +@@ -148,6 +148,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *); + int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *); + int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *); + int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *); ++int mm_answer_gss_sign(struct ssh *, int, struct sshbuf *); ++int mm_answer_gss_updatecreds(struct ssh *, int, struct sshbuf *); #endif #ifdef SSH_AUDIT_EVENTS -@@ -219,11 +221,18 @@ struct mon_table mon_dispatch_proto20[] +@@ -220,11 +222,18 @@ struct mon_table mon_dispatch_proto20[] = { {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, @@ -1718,7 +2617,7 @@ diff -up openssh/monitor.c.gsskex openssh/monitor.c #ifdef WITH_OPENSSL {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, #endif -@@ -293,6 +302,10 @@ monitor_child_preauth(Authctxt *_authctx +@@ -293,6 +302,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor) /* Permit requests for moduli and signatures */ monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); @@ -1729,50 +2628,58 @@ diff -up openssh/monitor.c.gsskex openssh/monitor.c /* The first few requests do not require asynchronous access */ while (!authenticated) { -@@ -405,6 +418,10 @@ monitor_child_postauth(struct monitor *p +@@ -406,6 +419,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor) monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); +#ifdef GSSAPI + /* and for the GSSAPI key exchange */ + monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); -+#endif ++#endif if (auth_opts->permit_pty_flag) { monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); -@@ -1695,6 +1712,13 @@ monitor_apply_keystate(struct monitor *p +@@ -1713,6 +1730,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor) + # ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif ++# ifdef GSSAPI ++ if (options.gss_keyex) { ++ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; ++ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; ++ } ++# endif #endif /* WITH_OPENSSL */ - kex->kex[KEX_C25519_SHA256] = kexc25519_server; -+#ifdef GSSAPI -+ if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; -+ } -+#endif - kex->load_host_public_key=&get_hostkey_public_by_type; - kex->load_host_private_key=&get_hostkey_private_by_type; - kex->host_key_index=&get_hostkey_index; -@@ -1785,7 +1809,7 @@ mm_answer_gss_setup_ctx(int sock, struct + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; +@@ -1806,8 +1834,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m) u_char *p; int r; - if (!options.gss_authentication) +- fatal("%s: GSSAPI authentication not enabled", __func__); + if (!options.gss_authentication && !options.gss_keyex) - fatal("%s: GSSAPI authentication not enabled", __func__); ++ fatal("%s: GSSAPI not enabled", __func__); if ((r = sshbuf_get_string(m, &p, &len)) != 0) -@@ -1818,7 +1842,7 @@ mm_answer_gss_accept_ctx(int sock, struc + fatal("%s: buffer error: %s", __func__, ssh_err(r)); +@@ -1839,8 +1867,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) OM_uint32 flags = 0; /* GSI needs this */ int r; - if (!options.gss_authentication) +- fatal("%s: GSSAPI authentication not enabled", __func__); + if (!options.gss_authentication && !options.gss_keyex) - fatal("%s: GSSAPI authentication not enabled", __func__); ++ fatal("%s: GSSAPI not enabled", __func__); if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) -@@ -1839,6 +1863,7 @@ mm_answer_gss_accept_ctx(int sock, struc + fatal("%s: buffer error: %s", __func__, ssh_err(r)); +@@ -1860,6 +1888,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m) monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); @@ -1780,49 +2687,77 @@ diff -up openssh/monitor.c.gsskex openssh/monitor.c } return (0); } -@@ -1850,7 +1875,7 @@ mm_answer_gss_checkmic(int sock, struct +@@ -1871,8 +1900,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) OM_uint32 ret; int r; - if (!options.gss_authentication) +- fatal("%s: GSSAPI authentication not enabled", __func__); + if (!options.gss_authentication && !options.gss_keyex) - fatal("%s: GSSAPI authentication not enabled", __func__); ++ fatal("%s: GSSAPI not enabled", __func__); if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || -@@ -1880,10 +1905,11 @@ mm_answer_gss_userok(int sock, struct ss - int r, authenticated; + (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) +@@ -1898,13 +1927,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m) + int + mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) + { +- int r, authenticated; ++ int r, authenticated, kex; const char *displayname; - if (!options.gss_authentication) +- fatal("%s: GSSAPI authentication not enabled", __func__); + if (!options.gss_authentication && !options.gss_keyex) - fatal("%s: GSSAPI authentication not enabled", __func__); ++ fatal("%s: GSSAPI not enabled", __func__); - authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); ++ if ((r = sshbuf_get_u32(m, &kex)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ + authenticated = authctxt->valid && -+ ssh_gssapi_userok(authctxt->user, authctxt->pw); ++ ssh_gssapi_userok(authctxt->user, authctxt->pw, kex); sshbuf_reset(m); if ((r = sshbuf_put_u32(m, authenticated)) != 0) -@@ -1900,5 +1926,74 @@ mm_answer_gss_userok(int sock, struct ss +@@ -1913,7 +1946,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) + debug3("%s: sending result %d", __func__, authenticated); + mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m); + +- auth_method = "gssapi-with-mic"; ++ if (kex) { ++ auth_method = "gssapi-keyex"; ++ } else { ++ auth_method = "gssapi-with-mic"; ++ } + + if ((displayname = ssh_gssapi_displayname()) != NULL) + auth2_record_info(authctxt, "%s", displayname); +@@ -1921,5 +1958,85 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m) /* Monitor loop will terminate if authenticated */ return (authenticated); } + -+int -+mm_answer_gss_sign(int socket, struct sshbuf *m) ++int ++mm_answer_gss_sign(struct ssh *ssh, int socket, struct sshbuf *m) +{ + gss_buffer_desc data; + gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; + OM_uint32 major, minor; ++ size_t len; ++ u_char *p = NULL; + int r; + + if (!options.gss_authentication && !options.gss_keyex) -+ fatal("In GSSAPI monitor when GSSAPI is disabled"); ++ fatal("%s: GSSAPI not enabled", __func__); + -+ if ((r = sshbuf_get_string(m, (u_char **)&data.value, &data.length)) != 0) ++ if ((r = sshbuf_get_string(m, &p, &len)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ if (data.length != 20) -+ fatal("%s: data length incorrect: %d", __func__, ++ data.value = p; ++ data.length = len; ++ /* Lengths of SHA-1, SHA-256 and SHA-512 hashes that are used */ ++ if (data.length != 20 && data.length != 32 && data.length != 64) ++ fatal("%s: data length incorrect: %d", __func__, + (int) data.length); + + /* Save the session ID on the first time around */ @@ -1836,6 +2771,7 @@ diff -up openssh/monitor.c.gsskex openssh/monitor.c + free(data.value); + + sshbuf_reset(m); ++ + if ((r = sshbuf_put_u32(m, major)) != 0 || + (r = sshbuf_put_string(m, hash.value, hash.length)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); @@ -1846,7 +2782,7 @@ diff -up openssh/monitor.c.gsskex openssh/monitor.c + + /* Turn on getpwnam permissions */ + monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); -+ ++ + /* And credential updating, for when rekeying */ + monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); + @@ -1854,16 +2790,21 @@ diff -up openssh/monitor.c.gsskex openssh/monitor.c +} + +int -+mm_answer_gss_updatecreds(int socket, struct sshbuf *m) { ++mm_answer_gss_updatecreds(struct ssh *ssh, int socket, struct sshbuf *m) { + ssh_gssapi_ccache store; -+ int ok, r; ++ int r, ok; + -+ if ((r = sshbuf_get_cstring(m, &store.envvar, NULL)) != 0 || -+ (r = sshbuf_get_cstring(m, &store.envval, NULL)) != 0) ++ if (!options.gss_authentication && !options.gss_keyex) ++ fatal("%s: GSSAPI not enabled", __func__); ++ ++ if ((r = sshbuf_get_string(m, (u_char **)&store.filename, NULL)) != 0 || ++ (r = sshbuf_get_string(m, (u_char **)&store.envvar, NULL)) != 0 || ++ (r = sshbuf_get_string(m, (u_char **)&store.envval, NULL)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + ok = ssh_gssapi_update_creds(&store); + ++ free(store.filename); + free(store.envvar); + free(store.envval); + @@ -1878,31 +2819,41 @@ diff -up openssh/monitor.c.gsskex openssh/monitor.c + #endif /* GSSAPI */ -diff -up openssh/monitor.h.gsskex openssh/monitor.h ---- openssh/monitor.h.gsskex 2018-08-22 11:47:33.263216069 +0200 -+++ openssh/monitor.h 2018-08-22 11:47:33.313216473 +0200 -@@ -58,6 +58,8 @@ enum monitor_reqtype { - #ifdef WITH_SELINUX - MONITOR_REQ_AUTHROLE = 80, - #endif -+ MONITOR_REQ_GSSSIGN = 82, MONITOR_ANS_GSSSIGN = 83, -+ MONITOR_REQ_GSSUPCREDS = 84, MONITOR_ANS_GSSUPCREDS = 85, - - MONITOR_REQ_PAM_START = 100, - MONITOR_REQ_PAM_ACCOUNT = 102, MONITOR_ANS_PAM_ACCOUNT = 103, -diff -up openssh/monitor_wrap.c.gsskex openssh/monitor_wrap.c ---- openssh/monitor_wrap.c.gsskex 2018-08-22 11:47:33.313216473 +0200 -+++ openssh/monitor_wrap.c 2018-08-22 13:27:38.665669643 +0200 -@@ -1004,7 +1004,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss +diff --git a/monitor.h b/monitor.h +index 683e5e07..2b1a2d59 100644 +--- a/monitor.h ++++ b/monitor.h +@@ -63,6 +63,8 @@ enum monitor_reqtype { + MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, + MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, + ++ MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, ++ MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, + }; + + struct ssh; +diff --git a/monitor_wrap.c b/monitor_wrap.c +index 001a8fa1..6edb509a 100644 +--- a/monitor_wrap.c ++++ b/monitor_wrap.c +@@ -993,13 +993,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) } int -mm_ssh_gssapi_userok(char *user) -+mm_ssh_gssapi_userok(char *user, struct passwd *pw) ++mm_ssh_gssapi_userok(char *user, struct passwd *pw, int kex) { struct sshbuf *m; int r, authenticated = 0; -@@ -1023,4 +1023,52 @@ mm_ssh_gssapi_userok(char *user) + + if ((m = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); ++ if ((r = sshbuf_put_u32(m, kex)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m); + mm_request_receive_expect(pmonitor->m_recvfd, +@@ -1012,4 +1014,57 @@ mm_ssh_gssapi_userok(char *user) debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); return (authenticated); } @@ -1923,25 +2874,29 @@ diff -up openssh/monitor_wrap.c.gsskex openssh/monitor_wrap.c + mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, m); + + if ((r = sshbuf_get_u32(m, &major)) != 0 || -+ (r = sshbuf_get_string(m, (u_char **)&hash->value, &hash->length)) != 0) ++ (r = ssh_gssapi_get_buffer_desc(m, hash)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + sshbuf_free(m); + -+ return(major); ++ return (major); +} + +int +mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) +{ + struct sshbuf *m; -+ int ok, r; ++ int r, ok; + + if ((m = sshbuf_new()) == NULL) + fatal("%s: sshbuf_new failed", __func__); + -+ if ((r = sshbuf_put_cstring(m, store->envvar ? store->envvar : "")) != 0 || -+ (r = sshbuf_put_cstring(m, store->envval ? store->envval : "")) != 0) ++ if ((r = sshbuf_put_cstring(m, ++ store->filename ? store->filename : "")) != 0 || ++ (r = sshbuf_put_cstring(m, ++ store->envvar ? store->envvar : "")) != 0 || ++ (r = sshbuf_put_cstring(m, ++ store->envval ? store->envval : "")) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); + + mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUPCREDS, m); @@ -1954,35 +2909,46 @@ diff -up openssh/monitor_wrap.c.gsskex openssh/monitor_wrap.c + + return (ok); +} ++ #endif /* GSSAPI */ -diff -up openssh/monitor_wrap.h.gsskex openssh/monitor_wrap.h ---- openssh/monitor_wrap.h.gsskex 2018-08-22 11:47:33.263216069 +0200 -+++ openssh/monitor_wrap.h 2018-08-22 11:47:33.313216473 +0200 -@@ -63,8 +63,10 @@ int mm_sshkey_verify(const struct sshkey +diff --git a/monitor_wrap.h b/monitor_wrap.h +index 23ab096a..485590c1 100644 +--- a/monitor_wrap.h ++++ b/monitor_wrap.h +@@ -64,8 +64,10 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); -int mm_ssh_gssapi_userok(char *user); -+int mm_ssh_gssapi_userok(char *user, struct passwd *); ++int mm_ssh_gssapi_userok(char *user, struct passwd *, int kex); OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); +OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); +int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); #endif #ifdef USE_PAM -diff -up openssh/readconf.c.gsskex openssh/readconf.c ---- openssh/readconf.c.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/readconf.c 2018-08-22 13:28:17.487982869 +0200 -@@ -161,6 +161,8 @@ typedef enum { +diff --git a/readconf.c b/readconf.c +index f3cac6b3..da8022dd 100644 +--- a/readconf.c ++++ b/readconf.c +@@ -67,6 +67,7 @@ + #include "uidswap.h" + #include "myproposal.h" + #include "digest.h" ++#include "ssh-gss.h" + + /* Format of the configuration file: + +@@ -160,6 +161,8 @@ typedef enum { oClearAllForwardings, oNoHostAuthenticationForLocalhost, oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, oAddressFamily, oGssAuthentication, oGssDelegateCreds, + oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, -+ oGssServerIdentity, ++ oGssServerIdentity, oGssKexAlgorithms, oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, oHashKnownHosts, -@@ -201,10 +203,19 @@ static struct { +@@ -204,10 +207,22 @@ static struct { /* Sometimes-unsupported options */ #if defined(GSSAPI) { "gssapiauthentication", oGssAuthentication }, @@ -1992,17 +2958,20 @@ diff -up openssh/readconf.c.gsskex openssh/readconf.c + { "gssapiclientidentity", oGssClientIdentity }, + { "gssapiserveridentity", oGssServerIdentity }, + { "gssapirenewalforcesrekey", oGssRenewalRekey }, ++ { "gssapikexalgorithms", oGssKexAlgorithms }, # else { "gssapiauthentication", oUnsupported }, + { "gssapikeyexchange", oUnsupported }, { "gssapidelegatecredentials", oUnsupported }, + { "gssapitrustdns", oUnsupported }, + { "gssapiclientidentity", oUnsupported }, ++ { "gssapiserveridentity", oUnsupported }, + { "gssapirenewalforcesrekey", oUnsupported }, ++ { "gssapikexalgorithms", oUnsupported }, #endif #ifdef ENABLE_PKCS11 - { "smartcarddevice", oPKCS11Provider }, -@@ -973,10 +984,30 @@ parse_time: + { "pkcs11provider", oPKCS11Provider }, +@@ -1029,10 +1044,42 @@ parse_time: intptr = &options->gss_authentication; goto parse_flag; @@ -2029,11 +2998,23 @@ diff -up openssh/readconf.c.gsskex openssh/readconf.c + case oGssRenewalRekey: + intptr = &options->gss_renewal_rekey; + goto parse_flag; ++ ++ case oGssKexAlgorithms: ++ arg = strdelim(&s); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", ++ filename, linenum); ++ if (!kex_gss_names_valid(arg)) ++ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->gss_kex_algorithms == NULL) ++ options->gss_kex_algorithms = xstrdup(arg); ++ break; + case oBatchMode: intptr = &options->batch_mode; goto parse_flag; -@@ -1817,7 +1848,12 @@ initialize_options(Options * options) +@@ -1911,7 +1958,13 @@ initialize_options(Options * options) options->pubkey_authentication = -1; options->challenge_response_authentication = -1; options->gss_authentication = -1; @@ -2043,10 +3024,11 @@ diff -up openssh/readconf.c.gsskex openssh/readconf.c + options->gss_renewal_rekey = -1; + options->gss_client_identity = NULL; + options->gss_server_identity = NULL; ++ options->gss_kex_algorithms = NULL; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->kbd_interactive_devices = NULL; -@@ -1962,8 +1998,14 @@ fill_default_options(Options * options) +@@ -2059,8 +2112,18 @@ fill_default_options(Options * options) options->challenge_response_authentication = 1; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -2058,13 +3040,33 @@ diff -up openssh/readconf.c.gsskex openssh/readconf.c + options->gss_trust_dns = 0; + if (options->gss_renewal_rekey == -1) + options->gss_renewal_rekey = 0; ++#ifdef GSSAPI ++ if (options->gss_kex_algorithms == NULL) ++ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX); ++#endif if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -diff -up openssh/readconf.h.gsskex openssh/readconf.h ---- openssh/readconf.h.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/readconf.h 2018-08-22 11:47:33.314216481 +0200 -@@ -40,7 +40,12 @@ typedef struct { +@@ -2702,7 +2765,14 @@ dump_client_config(Options *o, const char *host) + dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports); + #ifdef GSSAPI + dump_cfg_fmtint(oGssAuthentication, o->gss_authentication); ++ dump_cfg_fmtint(oGssKeyEx, o->gss_keyex); + dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds); ++ dump_cfg_fmtint(oGssTrustDns, o->gss_trust_dns); ++ dump_cfg_fmtint(oGssRenewalRekey, o->gss_renewal_rekey); ++ dump_cfg_string(oGssClientIdentity, o->gss_client_identity); ++ dump_cfg_string(oGssServerIdentity, o->gss_server_identity); ++ dump_cfg_string(oGssKexAlgorithms, o->gss_kex_algorithms ? ++ o->gss_kex_algorithms : GSS_KEX_DEFAULT_KEX); + #endif /* GSSAPI */ + dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts); + dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication); +diff --git a/readconf.h b/readconf.h +index feedb3d2..a8a8870d 100644 +--- a/readconf.h ++++ b/readconf.h +@@ -41,7 +41,13 @@ typedef struct { int challenge_response_authentication; /* Try S/Key or TIS, authentication. */ int gss_authentication; /* Try GSS authentication */ @@ -2074,73 +3076,23 @@ diff -up openssh/readconf.h.gsskex openssh/readconf.h + int gss_renewal_rekey; /* Credential renewal forces rekey */ + char *gss_client_identity; /* Principal to initiate GSSAPI with */ + char *gss_server_identity; /* GSSAPI target principal */ ++ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */ int password_authentication; /* Try password * authentication. */ int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ -diff -up openssh/regress/cert-hostkey.sh.gsskex openssh/regress/cert-hostkey.sh ---- openssh/regress/cert-hostkey.sh.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/regress/cert-hostkey.sh 2018-08-22 11:47:33.314216481 +0200 -@@ -66,7 +66,7 @@ touch $OBJ/host_revoked_plain - touch $OBJ/host_revoked_cert - cat $OBJ/host_ca_key.pub $OBJ/host_ca_key2.pub > $OBJ/host_revoked_ca - --PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` -+PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` - - if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then - PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512" -diff -up openssh/regress/cert-userkey.sh.gsskex openssh/regress/cert-userkey.sh ---- openssh/regress/cert-userkey.sh.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/regress/cert-userkey.sh 2018-08-22 11:47:33.314216481 +0200 -@@ -7,7 +7,7 @@ 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 | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` -+PLAIN_TYPES=`$SSH -Q key-plain | grep -v null | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'` - EXTRA_TYPES="" - - if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then -diff -up openssh/regress/kextype.sh.gsskex openssh/regress/kextype.sh ---- openssh/regress/kextype.sh.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/regress/kextype.sh 2018-08-22 11:47:33.315216489 +0200 -@@ -14,6 +14,9 @@ echo "KexAlgorithms=$KEXOPT" >> $OBJ/ssh - - tries="1 2 3 4" - for k in `${SSH} -Q kex`; do -+ if [ $k = "gss-gex-sha1-" -o $k = "gss-group1-sha1-" -o $k = "gss-group14-sha1-" ]; then -+ continue -+ fi - verbose "kex $k" - for i in $tries; do - ${SSH} -F $OBJ/ssh_proxy -o KexAlgorithms=$k x true -diff -up openssh/regress/rekey.sh.gsskex openssh/regress/rekey.sh ---- openssh/regress/rekey.sh.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/regress/rekey.sh 2018-08-22 11:47:33.315216489 +0200 -@@ -38,6 +38,9 @@ increase_datafile_size 300 - - opts="" - for i in `${SSH} -Q kex`; do -+ if [ $i = "gss-gex-sha1-" -o $i = "gss-group1-sha1-" -o $i = "gss-group14-sha1-" ]; then -+ continue -+ fi - opts="$opts KexAlgorithms=$i" - done - for i in `${SSH} -Q cipher`; do -@@ -56,6 +59,9 @@ done - if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then - for c in `${SSH} -Q cipher-auth`; do - for kex in `${SSH} -Q kex`; do -+ if [ $kex = "gss-gex-sha1-" -o $kex = "gss-group1-sha1-" -o $kex = "gss-group14-sha1-" ]; then -+ continue -+ fi - verbose "client rekey $c $kex" - ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c - done -diff -up openssh/servconf.c.gsskex openssh/servconf.c ---- openssh/servconf.c.gsskex 2018-08-22 11:47:33.296216335 +0200 -+++ openssh/servconf.c 2018-08-22 13:28:41.905179879 +0200 -@@ -124,8 +124,10 @@ initialize_server_options(ServerOptions +diff --git a/servconf.c b/servconf.c +index 70f5f73f..191575a1 100644 +--- a/servconf.c ++++ b/servconf.c +@@ -69,6 +69,7 @@ + #include "auth.h" + #include "myproposal.h" + #include "digest.h" ++#include "ssh-gss.h" + + static void add_listen_addr(ServerOptions *, const char *, + const char *, int); +@@ -133,8 +134,11 @@ initialize_server_options(ServerOptions *options) options->kerberos_ticket_cleanup = -1; options->kerberos_get_afs_token = -1; options->gss_authentication=-1; @@ -2148,10 +3100,11 @@ diff -up openssh/servconf.c.gsskex openssh/servconf.c options->gss_cleanup_creds = -1; options->gss_strict_acceptor = -1; + options->gss_store_rekey = -1; ++ options->gss_kex_algorithms = NULL; options->password_authentication = -1; options->kbd_interactive_authentication = -1; options->challenge_response_authentication = -1; -@@ -334,10 +336,14 @@ fill_default_server_options(ServerOption +@@ -375,10 +379,18 @@ fill_default_server_options(ServerOptions *options) options->kerberos_get_afs_token = 0; if (options->gss_authentication == -1) options->gss_authentication = 0; @@ -2163,37 +3116,45 @@ diff -up openssh/servconf.c.gsskex openssh/servconf.c options->gss_strict_acceptor = 1; + if (options->gss_store_rekey == -1) + options->gss_store_rekey = 0; ++#ifdef GSSAPI ++ if (options->gss_kex_algorithms == NULL) ++ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX); ++#endif if (options->password_authentication == -1) options->password_authentication = 1; if (options->kbd_interactive_authentication == -1) -@@ -484,7 +490,7 @@ typedef enum { +@@ -531,6 +543,7 @@ typedef enum { sHostKeyAlgorithms, sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, -- sAcceptEnv, sSetEnv, sPermitTunnel, -+ sGssKeyEx, sGssStoreRekey, sAcceptEnv, sSetEnv, sPermitTunnel, ++ sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey, + sAcceptEnv, sSetEnv, sPermitTunnel, sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, sUsePrivilegeSeparation, sAllowAgentForwarding, - sHostCertificate, -@@ -559,11 +565,17 @@ static struct { +@@ -607,12 +620,22 @@ static struct { + #ifdef GSSAPI { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, ++ { "gssapicleanupcreds", sGssCleanupCreds, SSHCFG_GLOBAL }, { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, ++ { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL }, #else { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapicleanupcreds", sUnsupported, SSHCFG_GLOBAL }, { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, + { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, + { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, ++ { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL }, #endif + { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, + { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, -@@ -1463,6 +1475,10 @@ process_server_config_line(ServerOptions +@@ -1548,6 +1571,10 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->gss_authentication; goto parse_flag; @@ -2204,31 +3165,45 @@ diff -up openssh/servconf.c.gsskex openssh/servconf.c case sGssCleanupCreds: intptr = &options->gss_cleanup_creds; goto parse_flag; -@@ -1471,6 +1487,10 @@ process_server_config_line(ServerOptions +@@ -1556,6 +1583,22 @@ process_server_config_line_depth(ServerOptions *options, char *line, intptr = &options->gss_strict_acceptor; goto parse_flag; + case sGssStoreRekey: + intptr = &options->gss_store_rekey; + goto parse_flag; ++ ++ case sGssKexAlgorithms: ++ arg = strdelim(&cp); ++ if (!arg || *arg == '\0') ++ fatal("%.200s line %d: Missing argument.", ++ filename, linenum); ++ if (!kex_gss_names_valid(arg)) ++ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.", ++ filename, linenum, arg ? arg : ""); ++ if (*activep && options->gss_kex_algorithms == NULL) ++ options->gss_kex_algorithms = xstrdup(arg); ++ break; + case sPasswordAuthentication: intptr = &options->password_authentication; goto parse_flag; -@@ -2560,6 +2580,9 @@ dump_config(ServerOptions *o) +@@ -2777,6 +2820,10 @@ dump_config(ServerOptions *o) #ifdef GSSAPI dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); + dump_cfg_fmtint(sGssKeyEx, o->gss_keyex); + dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); + dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); ++ dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms); #endif dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); dump_cfg_fmtint(sKbdInteractiveAuthentication, -diff -up openssh/servconf.h.gsskex openssh/servconf.h ---- openssh/servconf.h.gsskex 2018-08-22 11:47:33.296216335 +0200 -+++ openssh/servconf.h 2018-08-22 11:47:33.316216497 +0200 -@@ -124,8 +124,10 @@ typedef struct { +diff --git a/servconf.h b/servconf.h +index 4202a2d0..3f47ea25 100644 +--- a/servconf.h ++++ b/servconf.h +@@ -132,8 +132,11 @@ typedef struct { int kerberos_get_afs_token; /* If true, try to get AFS token if * authenticated with Kerberos. */ int gss_authentication; /* If true, permit GSSAPI authentication */ @@ -2236,198 +3211,315 @@ diff -up openssh/servconf.h.gsskex openssh/servconf.h int gss_cleanup_creds; /* If true, destroy cred cache on logout */ int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ + int gss_store_rekey; ++ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */ int password_authentication; /* If true, permit password * authentication. */ int kbd_interactive_authentication; /* If true, permit */ -diff -up openssh/ssh_config.5.gsskex openssh/ssh_config.5 ---- openssh/ssh_config.5.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/ssh_config.5 2018-08-22 11:47:33.316216497 +0200 -@@ -718,10 +718,40 @@ The default is - Specifies whether user authentication based on GSSAPI is allowed. - The default is - .Cm no . -+.It Cm GSSAPIClientIdentity -+If set, specifies the GSSAPI client identity that ssh should use when -+connecting to the server. The default is unset, which means that the default -+identity will be used. - .It Cm GSSAPIDelegateCredentials - Forward (delegate) credentials to the server. - The default is - .Cm no . -+.It Cm GSSAPIKeyExchange -+Specifies whether key exchange based on GSSAPI may be used. When using -+GSSAPI key exchange the server need not have a host key. -+The default is -+.Dq no . -+.It Cm GSSAPIRenewalForcesRekey -+If set to -+.Dq yes -+then renewal of the client's GSSAPI credentials will force the rekeying of the -+ssh connection. With a compatible server, this can delegate the renewed -+credentials to a session on the server. -+The default is -+.Dq no . -+.It Cm GSSAPIServerIdentity -+If set, specifies the GSSAPI server identity that ssh should expect when -+connecting to the server. The default is unset, which means that the -+expected GSSAPI server identity will be determined from the target -+hostname. -+.It Cm GSSAPITrustDns -+Set to -+.Dq yes to indicate that the DNS is trusted to securely canonicalize -+the name of the host being connected to. If -+.Dq no, the hostname entered on the -+command line will be passed untouched to the GSSAPI library. -+The default is -+.Dq no . - .It Cm HashKnownHosts - Indicates that - .Xr ssh 1 -diff -up openssh/ssh_config.gsskex openssh/ssh_config ---- openssh/ssh_config.gsskex 2018-08-22 11:47:33.289216279 +0200 -+++ openssh/ssh_config 2018-08-22 11:47:33.316216497 +0200 -@@ -24,6 +24,8 @@ - # HostbasedAuthentication no - # GSSAPIAuthentication no - # GSSAPIDelegateCredentials no -+# GSSAPIKeyExchange no -+# GSSAPITrustDNS no - # BatchMode no - # CheckHostIP yes - # AddressFamily any -diff -up openssh/sshconnect2.c.gsskex openssh/sshconnect2.c ---- openssh/sshconnect2.c.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/sshconnect2.c 2018-08-22 13:33:01.674275795 +0200 -@@ -82,6 +82,124 @@ extern char *client_version_string; - extern char *server_version_string; - extern Options options; +diff --git a/session.c b/session.c +index 8c0e54f7..06a33442 100644 +--- a/session.c ++++ b/session.c +@@ -2678,13 +2678,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt) -+/* XXX from auth.h -- refactoring move these useful functions away of client context*/ -+ -+/* -+ * Returns the remote DNS hostname as a string. The returned string must not -+ * be freed. NB. this will usually trigger a DNS query the first time it is -+ * called. -+ * This function does additional checks on the hostname to mitigate some -+ * attacks on legacy rhosts-style authentication. -+ * XXX is RhostsRSAAuthentication vulnerable to these? -+ * XXX Can we remove these checks? (or if not, remove RhostsRSAAuthentication?) -+ */ -+ -+static char * -+remote_hostname(struct ssh *ssh) -+{ -+ struct sockaddr_storage from; -+ socklen_t fromlen; -+ struct addrinfo hints, *ai, *aitop; -+ char name[NI_MAXHOST], ntop2[NI_MAXHOST]; -+ const char *ntop = ssh_remote_ipaddr(ssh); -+ -+ /* Get IP address of client. */ -+ fromlen = sizeof(from); -+ memset(&from, 0, sizeof(from)); -+ if (getpeername(ssh_packet_get_connection_in(ssh), -+ (struct sockaddr *)&from, &fromlen) < 0) { -+ debug("getpeername failed: %.100s", strerror(errno)); -+ return strdup(ntop); -+ } -+ -+ ipv64_normalise_mapped(&from, &fromlen); -+ if (from.ss_family == AF_INET6) -+ fromlen = sizeof(struct sockaddr_in6); -+ -+ debug3("Trying to reverse map address %.100s.", ntop); -+ /* Map the IP address to a host name. */ -+ if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), -+ NULL, 0, NI_NAMEREQD) != 0) { -+ /* Host name not found. Use ip address. */ -+ return strdup(ntop); -+ } -+ -+ /* -+ * if reverse lookup result looks like a numeric hostname, -+ * someone is trying to trick us by PTR record like following: -+ * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 -+ */ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/ -+ hints.ai_flags = AI_NUMERICHOST; -+ if (getaddrinfo(name, NULL, &hints, &ai) == 0) { -+ logit("Nasty PTR record \"%s\" is set up for %s, ignoring", -+ name, ntop); -+ freeaddrinfo(ai); -+ return strdup(ntop); -+ } -+ -+ /* Names are stored in lowercase. */ -+ lowercase(name); -+ -+ /* -+ * Map it back to an IP address and check that the given -+ * address actually is an address of this host. This is -+ * necessary because anyone with access to a name server can -+ * define arbitrary names for an IP address. Mapping from -+ * name to IP address can be trusted better (but can still be -+ * fooled if the intruder has access to the name server of -+ * the domain). -+ */ -+ memset(&hints, 0, sizeof(hints)); -+ hints.ai_family = from.ss_family; -+ hints.ai_socktype = SOCK_STREAM; -+ if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { -+ logit("reverse mapping checking getaddrinfo for %.700s " -+ "[%s] failed.", name, ntop); -+ return strdup(ntop); -+ } -+ /* Look for the address from the list of addresses. */ -+ for (ai = aitop; ai; ai = ai->ai_next) { -+ if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, -+ sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && -+ (strcmp(ntop, ntop2) == 0)) -+ break; + #ifdef KRB5 + if (options.kerberos_ticket_cleanup && +- authctxt->krb5_ctx) ++ authctxt->krb5_ctx) { ++ temporarily_use_uid(authctxt->pw); + krb5_cleanup_proc(authctxt); ++ restore_uid(); + } -+ freeaddrinfo(aitop); -+ /* If we reached the end of the list, the address was not there. */ -+ if (ai == NULL) { -+ /* Address not found for the host name. */ -+ logit("Address %.100s maps to %.600s, but this does not " -+ "map back to the address.", ntop, name); -+ return strdup(ntop); + #endif + + #ifdef GSSAPI +- if (options.gss_cleanup_creds) ++ if (options.gss_cleanup_creds) { ++ temporarily_use_uid(authctxt->pw); + ssh_gssapi_cleanup_creds(); ++ restore_uid(); + } -+ return strdup(name); -+} -+ -+/* -+ * Return the canonical name of the host in the other side of the current -+ * connection. The host name is cached, so it is efficient to call this -+ * several times. -+ */ + #endif + + /* remove agent socket */ +diff --git a/ssh-gss.h b/ssh-gss.h +index 36180d07..70dd3665 100644 +--- a/ssh-gss.h ++++ b/ssh-gss.h +@@ -1,6 +1,6 @@ + /* $OpenBSD: ssh-gss.h,v 1.14 2018/07/10 09:13:30 djm Exp $ */ + /* +- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. ++ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions +@@ -61,10 +61,34 @@ + + #define SSH_GSS_OIDTYPE 0x06 + ++#define SSH2_MSG_KEXGSS_INIT 30 ++#define SSH2_MSG_KEXGSS_CONTINUE 31 ++#define SSH2_MSG_KEXGSS_COMPLETE 32 ++#define SSH2_MSG_KEXGSS_HOSTKEY 33 ++#define SSH2_MSG_KEXGSS_ERROR 34 ++#define SSH2_MSG_KEXGSS_GROUPREQ 40 ++#define SSH2_MSG_KEXGSS_GROUP 41 ++#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" ++#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" ++#define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-" ++#define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-" ++#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" ++#define KEX_GSS_NISTP256_SHA256_ID "gss-nistp256-sha256-" ++#define KEX_GSS_C25519_SHA256_ID "gss-curve25519-sha256-" + -+const char * -+get_canonical_hostname(struct ssh *ssh, int use_dns) -+{ -+ static char *dnsname; -+ -+ if (!use_dns) -+ return ssh_remote_ipaddr(ssh); -+ else if (dnsname != NULL) -+ return dnsname; -+ else { -+ dnsname = remote_hostname(ssh); -+ return dnsname; -+ } -+} ++#define GSS_KEX_DEFAULT_KEX \ ++ KEX_GSS_GRP14_SHA256_ID "," \ ++ KEX_GSS_GRP16_SHA512_ID "," \ ++ KEX_GSS_NISTP256_SHA256_ID "," \ ++ KEX_GSS_C25519_SHA256_ID "," \ ++ KEX_GSS_GRP14_SHA1_ID "," \ ++ KEX_GSS_GEX_SHA1_ID + + typedef struct { + char *filename; + char *envvar; + char *envval; ++ struct passwd *owner; + void *data; + } ssh_gssapi_ccache; + +@@ -72,8 +92,11 @@ typedef struct { + gss_buffer_desc displayname; + gss_buffer_desc exportedname; + gss_cred_id_t creds; ++ gss_name_t name; + struct ssh_gssapi_mech_struct *mech; + ssh_gssapi_ccache store; ++ int used; ++ int updated; + } ssh_gssapi_client; + + typedef struct ssh_gssapi_mech_struct { +@@ -84,6 +107,7 @@ typedef struct ssh_gssapi_mech_struct { + int (*userok) (ssh_gssapi_client *, char *); + int (*localname) (ssh_gssapi_client *, char **); + void (*storecreds) (ssh_gssapi_client *); ++ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); + } ssh_gssapi_mech; + + typedef struct { +@@ -94,10 +118,11 @@ typedef struct { + gss_OID oid; /* client */ + gss_cred_id_t creds; /* server */ + gss_name_t client; /* server */ +- gss_cred_id_t client_creds; /* server */ ++ gss_cred_id_t client_creds; /* both */ + } Gssctxt; + + extern ssh_gssapi_mech *supported_mechs[]; ++extern Gssctxt *gss_kex_context; + + int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); + void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); +@@ -109,6 +134,7 @@ OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *); + + struct sshbuf; + int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *); ++int ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *, gss_buffer_desc *); + + OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *); + OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int, +@@ -123,17 +149,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **); + OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_buildmic(struct sshbuf *, const char *, + const char *, const char *); +-int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); ++int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); ++OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); ++int ssh_gssapi_credentials_updated(Gssctxt *); + + /* In the server */ ++typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, ++ const char *); ++char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *); ++char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, ++ const char *, const char *); ++gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); ++int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, ++ const char *); + OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); +-int ssh_gssapi_userok(char *name); ++int ssh_gssapi_userok(char *name, struct passwd *, int kex); + OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); + void ssh_gssapi_do_child(char ***, u_int *); + void ssh_gssapi_cleanup_creds(void); + void ssh_gssapi_storecreds(void); + const char *ssh_gssapi_displayname(void); + ++char *ssh_gssapi_server_mechanisms(void); ++int ssh_gssapi_oid_table_ok(void); + ++int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); ++void ssh_gssapi_rekey_creds(void); + + #endif /* GSSAPI */ + + #endif /* _SSH_GSS_H */ +diff --git a/ssh.1 b/ssh.1 +index 60de6087..db5c65bc 100644 +--- a/ssh.1 ++++ b/ssh.1 +@@ -503,7 +503,13 @@ For full details of the options listed below, and their possible values, see + .It GatewayPorts + .It GlobalKnownHostsFile + .It GSSAPIAuthentication ++.It GSSAPIKeyExchange ++.It GSSAPIClientIdentity + .It GSSAPIDelegateCredentials ++.It GSSAPIKexAlgorithms ++.It GSSAPIRenewalForcesRekey ++.It GSSAPIServerIdentity ++.It GSSAPITrustDns + .It HashKnownHosts + .It Host + .It HostbasedAuthentication +@@ -579,6 +585,8 @@ flag), + (supported message integrity codes), + .Ar kex + (key exchange algorithms), ++.Ar kex-gss ++(GSSAPI key exchange algorithms), + .Ar key + (key types), + .Ar key-cert +diff --git a/ssh.c b/ssh.c +index 15aee569..110cf9c1 100644 +--- a/ssh.c ++++ b/ssh.c +@@ -747,6 +747,8 @@ main(int ac, char **av) + else if (strcmp(optarg, "kex") == 0 || + strcasecmp(optarg, "KexAlgorithms") == 0) + cp = kex_alg_list('\n'); ++ else if (strcmp(optarg, "kex-gss") == 0) ++ cp = kex_gss_alg_list('\n'); + else if (strcmp(optarg, "key") == 0) + cp = sshkey_alg_list(0, 0, 0, '\n'); + else if (strcmp(optarg, "key-cert") == 0) +@@ -772,8 +774,8 @@ main(int ac, char **av) + } else if (strcmp(optarg, "help") == 0) { + cp = xstrdup( + "cipher\ncipher-auth\ncompression\nkex\n" +- "key\nkey-cert\nkey-plain\nkey-sig\nmac\n" +- "protocol-version\nsig"); ++ "kex-gss\nkey\nkey-cert\nkey-plain\n" ++ "key-sig\nmac\nprotocol-version\nsig"); + } + if (cp == NULL) + fatal("Unsupported query \"%s\"", optarg); +diff --git a/ssh_config b/ssh_config +index 5e8ef548..1ff999b6 100644 +--- a/ssh_config ++++ b/ssh_config +@@ -24,6 +24,8 @@ + # HostbasedAuthentication no + # GSSAPIAuthentication no + # GSSAPIDelegateCredentials no ++# GSSAPIKeyExchange no ++# GSSAPITrustDNS no + # BatchMode no + # CheckHostIP yes + # AddressFamily any +diff --git a/ssh_config.5 b/ssh_config.5 +index 06a32d31..3f490697 100644 +--- a/ssh_config.5 ++++ b/ssh_config.5 +@@ -766,10 +766,68 @@ The default is + Specifies whether user authentication based on GSSAPI is allowed. + The default is + .Cm no . ++.It Cm GSSAPIClientIdentity ++If set, specifies the GSSAPI client identity that ssh should use when ++connecting to the server. The default is unset, which means that the default ++identity will be used. + .It Cm GSSAPIDelegateCredentials + Forward (delegate) credentials to the server. + The default is + .Cm no . ++.It Cm GSSAPIKeyExchange ++Specifies whether key exchange based on GSSAPI may be used. When using ++GSSAPI key exchange the server need not have a host key. ++The default is ++.Dq no . ++.It Cm GSSAPIRenewalForcesRekey ++If set to ++.Dq yes ++then renewal of the client's GSSAPI credentials will force the rekeying of the ++ssh connection. With a compatible server, this will delegate the renewed ++credentials to a session on the server. ++.Pp ++Checks are made to ensure that credentials are only propagated when the new ++credentials match the old ones on the originating client and where the ++receiving server still has the old set in its cache. ++.Pp ++The default is ++.Dq no . ++.Pp ++For this to work ++.Cm GSSAPIKeyExchange ++needs to be enabled in the server and also used by the client. ++.It Cm GSSAPIServerIdentity ++If set, specifies the GSSAPI server identity that ssh should expect when ++connecting to the server. The default is unset, which means that the ++expected GSSAPI server identity will be determined from the target ++hostname. ++.It Cm GSSAPITrustDns ++Set to ++.Dq yes ++to indicate that the DNS is trusted to securely canonicalize ++the name of the host being connected to. If ++.Dq no , ++the hostname entered on the ++command line will be passed untouched to the GSSAPI library. ++The default is ++.Dq no . ++.It Cm GSSAPIKexAlgorithms ++The list of key exchange algorithms that are offered for GSSAPI ++key exchange. Possible values are ++.Bd -literal -offset 3n ++gss-gex-sha1-, ++gss-group1-sha1-, ++gss-group14-sha1-, ++gss-group14-sha256-, ++gss-group16-sha512-, ++gss-nistp256-sha256-, ++gss-curve25519-sha256- ++.Ed ++.Pp ++The default is ++.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, ++gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . ++This option only applies to connections using GSSAPI. + .It Cm HashKnownHosts + Indicates that + .Xr ssh 1 +diff --git a/sshconnect2.c b/sshconnect2.c +index af00fb30..03bc87eb 100644 +--- a/sshconnect2.c ++++ b/sshconnect2.c +@@ -80,8 +80,6 @@ + #endif + + /* import */ +-extern char *client_version_string; +-extern char *server_version_string; + extern Options options; + /* - * SSH2 key exchange - */ -@@ -162,9 +280,34 @@ ssh_kex2(char *host, struct sockaddr *ho - struct kex *kex; - int r; +@@ -163,6 +161,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + char *s, *all_key; + int r, use_known_hosts_order = 0; -+#ifdef GSSAPI ++#if defined(GSSAPI) && defined(WITH_OPENSSL) + char *orig = NULL, *gss = NULL; + char *gss_host = NULL; +#endif @@ -2435,152 +3527,189 @@ diff -up openssh/sshconnect2.c.gsskex openssh/sshconnect2.c xxx_host = host; xxx_hostaddr = hostaddr; -+#ifdef GSSAPI +@@ -206,6 +209,42 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + compat_pkalg_proposal(options.hostkeyalgorithms); + } + ++#if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { -+ /* Add the GSSAPI mechanisms currently supported on this ++ /* Add the GSSAPI mechanisms currently supported on this + * client to the key exchange algorithm proposal */ -+ orig = options.kex_algorithms; ++ orig = myproposal[PROPOSAL_KEX_ALGS]; + -+ if (options.gss_trust_dns) -+ gss_host = (char *)get_canonical_hostname(active_state, 1); -+ else -+ gss_host = host; ++ if (options.gss_server_identity) { ++ gss_host = xstrdup(options.gss_server_identity); ++ } else if (options.gss_trust_dns) { ++ gss_host = remote_hostname(ssh); ++ /* Fall back to specified host if we are using proxy command ++ * and can not use DNS on that socket */ ++ if (strcmp(gss_host, "UNKNOWN") == 0) { ++ free(gss_host); ++ gss_host = xstrdup(host); ++ } ++ } else { ++ gss_host = xstrdup(host); ++ } + -+ gss = ssh_gssapi_client_mechanisms(gss_host, options.gss_client_identity); ++ gss = ssh_gssapi_client_mechanisms(gss_host, ++ options.gss_client_identity, options.gss_kex_algorithms); + if (gss) { + debug("Offering GSSAPI proposal: %s", gss); -+ xasprintf(&options.kex_algorithms, ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], + "%s,%s", gss, orig); -+ } -+ } -+#endif + - if ((s = kex_names_cat(options.kex_algorithms, "ext-info-c")) == NULL) - fatal("%s: kex_names_cat", __func__); - myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(s); -@@ -194,6 +337,17 @@ ssh_kex2(char *host, struct sockaddr *ho - order_hostkeyalgs(host, hostaddr, port)); - } - -+#ifdef GSSAPI -+ /* If we've got GSSAPI algorithms, then we also support the -+ * 'null' hostkey, as a last resort */ -+ if (options.gss_keyex && gss) { -+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; -+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], -+ "%s,null", orig); -+ free(gss); ++ /* If we've got GSSAPI algorithms, then we also support the ++ * 'null' hostkey, as a last resort */ ++ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], ++ "%s,null", orig); ++ } + } +#endif + if (options.rekey_limit || options.rekey_interval) - packet_set_rekey_limits(options.rekey_limit, + ssh_packet_set_rekey_limits(ssh, options.rekey_limit, options.rekey_interval); -@@ -214,11 +368,31 @@ ssh_kex2(char *host, struct sockaddr *ho - kex->kex[KEX_ECDH_SHA2] = kexecdh_client; +@@ -224,16 +256,46 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port) + # ifdef OPENSSL_HAS_ECC + ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client; # endif - #endif -+#ifdef GSSAPI +-#endif ++# ifdef GSSAPI + if (options.gss_keyex) { -+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; -+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_client; ++ ssh->kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_client; ++ ssh->kex->kex[KEX_GSS_C25519_SHA256] = kexgss_client; + } -+#endif - kex->kex[KEX_C25519_SHA256] = kexc25519_client; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; - kex->verify_host_key=&verify_host_key_callback; ++# endif ++#endif /* WITH_OPENSSL */ + ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client; + ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client; + ssh->kex->verify_host_key=&verify_host_key_callback; -+#ifdef GSSAPI ++#if defined(GSSAPI) && defined(WITH_OPENSSL) + if (options.gss_keyex) { -+ kex->gss_deleg_creds = options.gss_deleg_creds; -+ kex->gss_trust_dns = options.gss_trust_dns; -+ kex->gss_client = options.gss_client_identity; -+ if (options.gss_server_identity) { -+ kex->gss_host = options.gss_server_identity; -+ } else { -+ kex->gss_host = gss_host; -+ } ++ ssh->kex->gss_deleg_creds = options.gss_deleg_creds; ++ ssh->kex->gss_trust_dns = options.gss_trust_dns; ++ ssh->kex->gss_client = options.gss_client_identity; ++ ssh->kex->gss_host = gss_host; + } +#endif + - ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); + ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done); /* remove ext-info from the KEX proposals for rekeying */ -@@ -314,6 +488,7 @@ int input_gssapi_token(int type, u_int32 - int input_gssapi_hash(int type, u_int32_t, struct ssh *); - int input_gssapi_error(int, u_int32_t, struct ssh *); - int input_gssapi_errtok(int, u_int32_t, struct ssh *); -+int userauth_gsskeyex(Authctxt *authctxt); + myproposal[PROPOSAL_KEX_ALGS] = + compat_kex_proposal(options.kex_algorithms); ++#if defined(GSSAPI) && defined(WITH_OPENSSL) ++ /* repair myproposal after it was crumpled by the */ ++ /* ext-info removal above */ ++ if (gss) { ++ orig = myproposal[PROPOSAL_KEX_ALGS]; ++ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], ++ "%s,%s", gss, orig); ++ free(gss); ++ } ++#endif + if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0) + fatal("kex_prop2buf: %s", ssh_err(r)); + +@@ -330,6 +392,7 @@ static int input_gssapi_response(int type, u_int32_t, struct ssh *); + static int input_gssapi_token(int type, u_int32_t, struct ssh *); + static int input_gssapi_error(int, u_int32_t, struct ssh *); + static int input_gssapi_errtok(int, u_int32_t, struct ssh *); ++static int userauth_gsskeyex(struct ssh *); #endif - void userauth(Authctxt *, char *); -@@ -330,6 +505,11 @@ static char *authmethods_get(void); + void userauth(struct ssh *, char *); +@@ -346,6 +409,11 @@ static char *authmethods_get(void); Authmethod authmethods[] = { #ifdef GSSAPI + {"gssapi-keyex", + userauth_gsskeyex, + NULL, -+ &options.gss_authentication, ++ &options.gss_keyex, + NULL}, {"gssapi-with-mic", userauth_gssapi, - NULL, -@@ -657,19 +837,31 @@ userauth_gssapi(Authctxt *authctxt) - static u_int mech = 0; + userauth_gssapi_cleanup, +@@ -716,12 +784,32 @@ userauth_gssapi(struct ssh *ssh) OM_uint32 min; int r, ok = 0; -+ const char *gss_host; + gss_OID mech = NULL; ++ char *gss_host = NULL; + -+ if (options.gss_server_identity) -+ gss_host = options.gss_server_identity; -+ else if (options.gss_trust_dns) -+ gss_host = get_canonical_hostname(active_state, 1); -+ else -+ gss_host = authctxt->host; ++ if (options.gss_server_identity) { ++ gss_host = xstrdup(options.gss_server_identity); ++ } else if (options.gss_trust_dns) { ++ gss_host = remote_hostname(ssh); ++ /* Fall back to specified host if we are using proxy command ++ * and can not use DNS on that socket */ ++ if (strcmp(gss_host, "UNKNOWN") == 0) { ++ free(gss_host); ++ gss_host = xstrdup(authctxt->host); ++ } ++ } else { ++ gss_host = xstrdup(authctxt->host); ++ } /* Try one GSSAPI method at a time, rather than sending them all at * once. */ - if (gss_supported == NULL) -- gss_indicate_mechs(&min, &gss_supported); -+ if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { -+ gss_supported = NULL; + if (authctxt->gss_supported_mechs == NULL) +- gss_indicate_mechs(&min, &authctxt->gss_supported_mechs); ++ if (GSS_ERROR(gss_indicate_mechs(&min, ++ &authctxt->gss_supported_mechs))) { ++ authctxt->gss_supported_mechs = NULL; ++ free(gss_host); + return 0; + } - /* Check to see if the mechanism is usable before we offer it */ - while (mech < gss_supported->count && !ok) { + /* Check to see whether the mechanism is usable before we offer it */ + while (authctxt->mech_tried < authctxt->gss_supported_mechs->count && +@@ -730,13 +811,15 @@ userauth_gssapi(struct ssh *ssh) + elements[authctxt->mech_tried]; /* My DER encoding requires length<128 */ - if (gss_supported->elements[mech].length < 128 && - ssh_gssapi_check_mechanism(&gssctxt, -- &gss_supported->elements[mech], authctxt->host)) { -+ &gss_supported->elements[mech], gss_host, -+ options.gss_client_identity)) { + if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt, +- mech, authctxt->host)) { ++ mech, gss_host, options.gss_client_identity)) { ok = 1; /* Mechanism works */ } else { - mech++; -@@ -906,6 +1098,51 @@ input_gssapi_error(int type, u_int32_t p + authctxt->mech_tried++; + } + } + ++ free(gss_host); ++ + if (!ok || mech == NULL) + return 0; + +@@ -976,6 +1059,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) free(lang); return r; } + +int -+userauth_gsskeyex(Authctxt *authctxt) ++userauth_gsskeyex(struct ssh *ssh) +{ + struct sshbuf *b = NULL; ++ Authctxt *authctxt = ssh->authctxt; + gss_buffer_desc gssbuf; + gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; + OM_uint32 ms; ++ int r; + + static int attempt = 0; + if (attempt++ >= 1) + return (0); + + if (gss_kex_context == NULL) { -+ debug("No valid Key exchange context"); ++ debug("No valid Key exchange context"); + return (0); + } + @@ -2590,7 +3719,8 @@ diff -up openssh/sshconnect2.c.gsskex openssh/sshconnect2.c + ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, + "gssapi-keyex"); + -+ gssbuf.value = sshbuf_mutable_ptr(b); ++ if ((gssbuf.value = sshbuf_mutable_ptr(b)) == NULL) ++ fatal("%s: sshbuf_mutable_ptr failed", __func__); + gssbuf.length = sshbuf_len(b); + + if (GSS_ERROR(ssh_gssapi_sign(gss_kex_context, &gssbuf, &mic))) { @@ -2598,12 +3728,13 @@ diff -up openssh/sshconnect2.c.gsskex openssh/sshconnect2.c + return (0); + } + -+ packet_start(SSH2_MSG_USERAUTH_REQUEST); -+ packet_put_cstring(authctxt->server_user); -+ packet_put_cstring(authctxt->service); -+ packet_put_cstring(authctxt->method->name); -+ packet_put_string(mic.value, mic.length); -+ packet_send(); ++ if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->service)) != 0 || ++ (r = sshpkt_put_cstring(ssh, authctxt->method->name)) != 0 || ++ (r = sshpkt_put_string(ssh, mic.value, mic.length)) != 0 || ++ (r = sshpkt_send(ssh)) != 0) ++ fatal("%s: %s", __func__, ssh_err(r)); + + sshbuf_free(b); + gss_release_buffer(&ms, &mic); @@ -2613,33 +3744,23 @@ diff -up openssh/sshconnect2.c.gsskex openssh/sshconnect2.c + #endif /* GSSAPI */ - int -diff -up openssh/sshd.c.gsskex openssh/sshd.c ---- openssh/sshd.c.gsskex 2018-08-22 11:47:33.299216360 +0200 -+++ openssh/sshd.c 2018-08-22 13:34:28.455975954 +0200 -@@ -537,8 +537,7 @@ privsep_preauth_child(void) - - #ifdef GSSAPI - /* Cache supported mechanism OIDs for later use */ -- if (options.gss_authentication) -- ssh_gssapi_prepare_supported_oids(); -+ ssh_gssapi_prepare_supported_oids(); - #endif - - reseed_prngs(); -@@ -887,8 +887,9 @@ notify_hostkeys(struct ssh *ssh) + static int +diff --git a/sshd.c b/sshd.c +index 60b2aaf7..d92f03aa 100644 +--- a/sshd.c ++++ b/sshd.c +@@ -817,8 +817,8 @@ notify_hostkeys(struct ssh *ssh) } debug3("%s: sent %u hostkeys", __func__, nkeys); if (nkeys == 0) - fatal("%s: no hostkeys", __func__); -- packet_send(); +- if ((r = sshpkt_send(ssh)) != 0) + debug3("%s: no hostkeys", __func__); -+ else -+ packet_send(); ++ else if ((r = sshpkt_send(ssh)) != 0) + sshpkt_fatal(ssh, r, "%s: send", __func__); sshbuf_free(buf); } - -@@ -1841,7 +1842,8 @@ main(int ac, char **av) +@@ -1852,7 +1852,8 @@ main(int ac, char **av) free(fp); } accumulate_host_timing_secret(cfg, NULL); @@ -2649,18 +3770,18 @@ diff -up openssh/sshd.c.gsskex openssh/sshd.c logit("sshd: no hostkeys available -- exiting."); exit(1); } -@@ -2321,6 +2323,48 @@ do_ssh2_kex(void) +@@ -2347,6 +2348,48 @@ do_ssh2_kex(struct ssh *ssh) myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( list_hostkey_types()); -+#ifdef GSSAPI ++#if defined(GSSAPI) && defined(WITH_OPENSSL) + { + char *orig; + char *gss = NULL; + char *newstr = NULL; + orig = myproposal[PROPOSAL_KEX_ALGS]; + -+ /* ++ /* + * If we don't have a host key, then there's no point advertising + * the other key exchange algorithms + */ @@ -2680,10 +3801,10 @@ diff -up openssh/sshd.c.gsskex openssh/sshd.c + else if (orig) + newstr = orig; + -+ /* ++ /* + * If we've got GSSAPI mechanisms, then we've got the 'null' host + * key alg, but we can't tell people about it unless its the only -+ * host key algorithm we support ++ * host key algorithm we support + */ + if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) + myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; @@ -2696,26 +3817,46 @@ diff -up openssh/sshd.c.gsskex openssh/sshd.c +#endif + /* start key exchange */ - if ((r = kex_setup(active_state, myproposal)) != 0) + if ((r = kex_setup(ssh, myproposal)) != 0) fatal("kex_setup: %s", ssh_err(r)); -@@ -2338,6 +2382,13 @@ do_ssh2_kex(void) +@@ -2362,7 +2405,18 @@ do_ssh2_kex(struct ssh *ssh) + # ifdef OPENSSL_HAS_ECC + kex->kex[KEX_ECDH_SHA2] = kex_gen_server; # endif - #endif - kex->kex[KEX_C25519_SHA256] = kexc25519_server; -+#ifdef GSSAPI +-#endif ++# ifdef GSSAPI + if (options.gss_keyex) { + kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; + kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; -+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; ++ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server; ++ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server; ++ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server; ++ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server; + } -+#endif - kex->server = 1; - kex->client_version_string=client_version_string; - kex->server_version_string=server_version_string; -diff -up openssh/sshd_config.5.gsskex openssh/sshd_config.5 ---- openssh/sshd_config.5.gsskex 2018-08-22 11:47:33.297216344 +0200 -+++ openssh/sshd_config.5 2018-08-22 13:35:05.531275099 +0200 -@@ -642,6 +642,11 @@ Specifies whether to automatically destr ++# endif ++#endif /* WITH_OPENSSL */ + kex->kex[KEX_C25519_SHA256] = kex_gen_server; + kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server; + kex->load_host_public_key=&get_hostkey_public_by_type; +diff --git a/sshd_config b/sshd_config +index 19b7c91a..2c48105f 100644 +--- a/sshd_config ++++ b/sshd_config +@@ -69,6 +69,8 @@ AuthorizedKeysFile .ssh/authorized_keys + # GSSAPI options + #GSSAPIAuthentication no + #GSSAPICleanupCredentials yes ++#GSSAPIStrictAcceptorCheck yes ++#GSSAPIKeyExchange no + + # Set this to 'yes' to enable PAM authentication, account processing, + # and session processing. If this is enabled, PAM authentication will +diff --git a/sshd_config.5 b/sshd_config.5 +index 70ccea44..f6b41a2f 100644 +--- a/sshd_config.5 ++++ b/sshd_config.5 +@@ -646,6 +646,11 @@ Specifies whether to automatically destroy the user's credentials cache on logout. The default is .Cm yes . @@ -2723,183 +3864,73 @@ diff -up openssh/sshd_config.5.gsskex openssh/sshd_config.5 +Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange +doesn't rely on ssh keys to verify host identity. +The default is -+.Dq no . ++.Cm no . .It Cm GSSAPIStrictAcceptorCheck Determines whether to be strict about the identity of the GSSAPI acceptor a client authenticates against. -@@ -656,6 +661,11 @@ machine's default store. +@@ -660,6 +665,32 @@ machine's default store. This facility is provided to assist with operation on multi homed machines. The default is .Cm yes . +.It Cm GSSAPIStoreCredentialsOnRekey -+Controls whether the user's GSSAPI credentials should be updated following a -+successful connection rekeying. This option can be used to accepted renewed ++Controls whether the user's GSSAPI credentials should be updated following a ++successful connection rekeying. This option can be used to accepted renewed +or updated credentials from a compatible client. The default is +.Dq no . ++.Pp ++For this to work ++.Cm GSSAPIKeyExchange ++needs to be enabled in the server and also used by the client. ++.It Cm GSSAPIKexAlgorithms ++The list of key exchange algorithms that are accepted by GSSAPI ++key exchange. Possible values are ++.Bd -literal -offset 3n ++gss-gex-sha1-, ++gss-group1-sha1-, ++gss-group14-sha1-, ++gss-group14-sha256-, ++gss-group16-sha512-, ++gss-nistp256-sha256-, ++gss-curve25519-sha256- ++.Ed ++.Pp ++The default is ++.Dq gss-group14-sha256-,gss-group16-sha512-,gss-nistp256-sha256-, ++gss-curve25519-sha256-,gss-group14-sha1-,gss-gex-sha1- . ++This option only applies to connections using GSSAPI. .It Cm HostbasedAcceptedKeyTypes Specifies the key types that will be accepted for hostbased authentication as a list of comma-separated patterns. -diff -up openssh/sshd_config.gsskex openssh/sshd_config ---- openssh/sshd_config.gsskex 2018-08-22 11:47:33.299216360 +0200 -+++ openssh/sshd_config 2018-08-22 11:47:33.318216513 +0200 -@@ -85,6 +85,8 @@ ChallengeResponseAuthentication no - # GSSAPI options - GSSAPIAuthentication yes - GSSAPICleanupCredentials no -+#GSSAPIStrictAcceptorCheck yes -+#GSSAPIKeyExchange no - - # Set this to 'yes' to enable PAM authentication, account processing, - # and session processing. If this is enabled, PAM authentication will -diff -up openssh/ssh-gss.h.gsskex openssh/ssh-gss.h ---- openssh/ssh-gss.h.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/ssh-gss.h 2018-08-22 13:36:44.773075793 +0200 -@@ -1,6 +1,6 @@ - /* $OpenBSD: ssh-gss.h,v 1.14 2018/07/10 09:13:30 djm Exp $ */ - /* -- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. -+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions -@@ -61,10 +61,22 @@ - - #define SSH_GSS_OIDTYPE 0x06 - -+#define SSH2_MSG_KEXGSS_INIT 30 -+#define SSH2_MSG_KEXGSS_CONTINUE 31 -+#define SSH2_MSG_KEXGSS_COMPLETE 32 -+#define SSH2_MSG_KEXGSS_HOSTKEY 33 -+#define SSH2_MSG_KEXGSS_ERROR 34 -+#define SSH2_MSG_KEXGSS_GROUPREQ 40 -+#define SSH2_MSG_KEXGSS_GROUP 41 -+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" -+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" -+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" -+ - typedef struct { - char *filename; - char *envvar; - char *envval; -+ struct passwd *owner; - void *data; - } ssh_gssapi_ccache; - -@@ -72,8 +84,11 @@ typedef struct { - gss_buffer_desc displayname; - gss_buffer_desc exportedname; - gss_cred_id_t creds; -+ gss_name_t name; - struct ssh_gssapi_mech_struct *mech; - ssh_gssapi_ccache store; -+ int used; -+ int updated; - } ssh_gssapi_client; - - typedef struct ssh_gssapi_mech_struct { -@@ -84,6 +99,7 @@ typedef struct ssh_gssapi_mech_struct { - int (*userok) (ssh_gssapi_client *, char *); - int (*localname) (ssh_gssapi_client *, char **); - void (*storecreds) (ssh_gssapi_client *); -+ int (*updatecreds) (ssh_gssapi_ccache *, ssh_gssapi_client *); - } ssh_gssapi_mech; - - typedef struct { -@@ -94,10 +110,11 @@ typedef struct { - gss_OID oid; /* client */ - gss_cred_id_t creds; /* server */ - gss_name_t client; /* server */ -- gss_cred_id_t client_creds; /* server */ -+ gss_cred_id_t client_creds; /* both */ - } Gssctxt; - - extern ssh_gssapi_mech *supported_mechs[]; -+extern Gssctxt *gss_kex_context; - - int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); - void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); -@@ -123,17 +140,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **); - OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_buildmic(struct sshbuf *, const char *, - const char *, const char *); --int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *); -+int ssh_gssapi_check_mechanism(Gssctxt **, gss_OID, const char *, const char *); -+OM_uint32 ssh_gssapi_client_identity(Gssctxt *, const char *); -+int ssh_gssapi_credentials_updated(Gssctxt *); - - /* In the server */ -+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, -+ const char *); -+char *ssh_gssapi_client_mechanisms(const char *, const char *); -+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, -+ const char *); -+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); -+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, -+ const char *); - OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); --int ssh_gssapi_userok(char *name); -+int ssh_gssapi_userok(char *name, struct passwd *); - OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); - void ssh_gssapi_do_child(char ***, u_int *); - void ssh_gssapi_cleanup_creds(void); - void ssh_gssapi_storecreds(void); - const char *ssh_gssapi_displayname(void); - -+char *ssh_gssapi_server_mechanisms(void); -+int ssh_gssapi_oid_table_ok(); -+ -+int ssh_gssapi_update_creds(ssh_gssapi_ccache *store); -+ -+void ssh_gssapi_rekey_creds(void); - #endif /* GSSAPI */ - - #endif /* _SSH_GSS_H */ -diff -up openssh/sshkey.c.gsskex openssh/sshkey.c ---- openssh/sshkey.c.gsskex 2018-08-22 11:47:33.319216521 +0200 -+++ openssh/sshkey.c 2018-08-22 13:37:18.979351804 +0200 -@@ -140,6 +140,7 @@ static const struct keytype keytypes[] = - # endif /* OPENSSL_HAS_NISTP521 */ +diff --git a/sshkey.c b/sshkey.c +index 57995ee6..fd5b7724 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -154,6 +154,7 @@ static const struct keytype keytypes[] = { + KEY_ECDSA_SK_CERT, NID_X9_62_prime256v1, 1, 0 }, # endif /* OPENSSL_HAS_ECC */ #endif /* WITH_OPENSSL */ -+ { "null", "null", NULL, KEY_NULL, 0, 0, 1 }, ++ { "null", "null", NULL, KEY_NULL, 0, 0, 0 }, { NULL, NULL, NULL, -1, -1, 0, 0 } }; -diff -up openssh/sshkey.h.gsskex openssh/sshkey.h ---- openssh/sshkey.h.gsskex 2018-08-20 07:57:29.000000000 +0200 -+++ openssh/sshkey.h 2018-08-22 11:47:33.320216529 +0200 -@@ -63,6 +63,7 @@ enum sshkey_types { - KEY_ED25519_CERT, - KEY_XMSS, - KEY_XMSS_CERT, +@@ -255,7 +256,7 @@ sshkey_alg_list(int certs_only, int plain_only, int include_sigonly, char sep) + const struct keytype *kt; + + for (kt = keytypes; kt->type != -1; kt++) { +- if (kt->name == NULL) ++ if (kt->name == NULL || kt->type == KEY_NULL) + continue; + if (!include_sigonly && kt->sigonly) + continue; +diff --git a/sshkey.h b/sshkey.h +index 71a3fddc..37a43a67 100644 +--- a/sshkey.h ++++ b/sshkey.h +@@ -69,6 +69,7 @@ enum sshkey_types { + KEY_ECDSA_SK_CERT, + KEY_ED25519_SK, + KEY_ED25519_SK_CERT, + KEY_NULL, KEY_UNSPEC }; - ---- openssh/sshconnect2.c.orig 2017-01-04 19:47:10.000000000 +0100 -+++ openssh/sshconnect2.c 2017-01-05 04:13:08.977425272 +0100 -@@ -344,7 +344,6 @@ - orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; - xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], - "%s,null", orig); -- free(gss); - } - #endif - -@@ -398,6 +397,16 @@ - /* remove ext-info from the KEX proposals for rekeying */ - myproposal[PROPOSAL_KEX_ALGS] = - compat_kex_proposal(options.kex_algorithms); -+#ifdef GSSAPI -+ /* repair myproposal after it was crumpled by the */ -+ /* ext-info removal above */ -+ if (gss) { -+ orig = myproposal[PROPOSAL_KEX_ALGS]; -+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], -+ "%s,%s", gss, orig); -+ free(gss); -+ } -+#endif - if ((r = kex_prop2buf(kex->my, myproposal)) != 0) - fatal("kex_prop2buf: %s", ssh_err(r)); diff --git a/openssh-8.0p1-openssl-evp.patch b/openssh-8.0p1-openssl-evp.patch new file mode 100644 index 0000000000000000000000000000000000000000..ade0bbb2118460071a8b8347c81363cbacd21bb3 --- /dev/null +++ b/openssh-8.0p1-openssl-evp.patch @@ -0,0 +1,720 @@ +From ed7ec0cdf577ffbb0b15145340cf51596ca3eb89 Mon Sep 17 00:00:00 2001 +From: Jakub Jelen +Date: Tue, 14 May 2019 10:45:45 +0200 +Subject: [PATCH] Use high-level OpenSSL API for signatures + +--- + digest-openssl.c | 16 ++++ + digest.h | 6 ++ + ssh-dss.c | 65 ++++++++++------ + ssh-ecdsa.c | 69 ++++++++++------- + ssh-rsa.c | 193 +++++++++-------------------------------------- + sshkey.c | 77 +++++++++++++++++++ + sshkey.h | 4 + + 7 files changed, 221 insertions(+), 209 deletions(-) + +diff --git a/digest-openssl.c b/digest-openssl.c +index da7ed72bc..6a21d8adb 100644 +--- a/digest-openssl.c ++++ b/digest-openssl.c +@@ -63,6 +63,22 @@ const struct ssh_digest digests[] = { + { -1, NULL, 0, NULL }, + }; + ++const EVP_MD * ++ssh_digest_to_md(int digest_type) ++{ ++ switch (digest_type) { ++ case SSH_DIGEST_SHA1: ++ return EVP_sha1(); ++ case SSH_DIGEST_SHA256: ++ return EVP_sha256(); ++ case SSH_DIGEST_SHA384: ++ return EVP_sha384(); ++ case SSH_DIGEST_SHA512: ++ return EVP_sha512(); ++ } ++ return NULL; ++} ++ + static const struct ssh_digest * + ssh_digest_by_alg(int alg) + { +diff --git a/digest.h b/digest.h +index 274574d0e..c7ceeb36f 100644 +--- a/digest.h ++++ b/digest.h +@@ -32,6 +32,12 @@ + struct sshbuf; + struct ssh_digest_ctx; + ++#ifdef WITH_OPENSSL ++#include ++/* Converts internal digest representation to the OpenSSL one */ ++const EVP_MD *ssh_digest_to_md(int digest_type); ++#endif ++ + /* Looks up a digest algorithm by name */ + int ssh_digest_alg_by_name(const char *name); + +diff --git a/ssh-dss.c b/ssh-dss.c +index a23c383dc..ea45e7275 100644 +--- a/ssh-dss.c ++++ b/ssh-dss.c +@@ -52,11 +52,15 @@ int + ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) + { ++ EVP_PKEY *pkey = NULL; + DSA_SIG *sig = NULL; + const BIGNUM *sig_r, *sig_s; +- u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; +- size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); ++ u_char sigblob[SIGBLOB_LEN]; ++ size_t rlen, slen; ++ int len; + struct sshbuf *b = NULL; ++ u_char *sigb = NULL; ++ const u_char *psig = NULL; + int ret = SSH_ERR_INVALID_ARGUMENT; + + if (lenp != NULL) +@@ -67,17 +71,24 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + if (key == NULL || key->dsa == NULL || + sshkey_type_plain(key->type) != KEY_DSA) + return SSH_ERR_INVALID_ARGUMENT; +- if (dlen == 0) +- return SSH_ERR_INTERNAL_ERROR; + +- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, +- digest, sizeof(digest))) != 0) ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ ret = sshkey_calculate_signature(pkey, SSH_DIGEST_SHA1, &sigb, &len, ++ data, datalen); ++ EVP_PKEY_free(pkey); ++ if (ret < 0) { + goto out; ++ } + +- if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) { ++ psig = sigb; ++ if ((sig = d2i_DSA_SIG(NULL, &psig, len)) == NULL) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } ++ free(sigb); ++ sigb = NULL; + + DSA_SIG_get0(sig, &sig_r, &sig_s); + rlen = BN_num_bytes(sig_r); +@@ -110,7 +121,7 @@ ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + *lenp = len; + ret = 0; + out: +- explicit_bzero(digest, sizeof(digest)); ++ free(sigb); + DSA_SIG_free(sig); + sshbuf_free(b); + return ret; +@@ -121,20 +132,20 @@ ssh_dss_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat) + { ++ EVP_PKEY *pkey = NULL; + DSA_SIG *sig = NULL; + BIGNUM *sig_r = NULL, *sig_s = NULL; +- u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL; +- size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); ++ u_char *sigblob = NULL; ++ size_t len, slen; + int ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; + char *ktype = NULL; ++ u_char *sigb = NULL, *psig = NULL; + + if (key == NULL || key->dsa == NULL || + sshkey_type_plain(key->type) != KEY_DSA || + signature == NULL || signaturelen == 0) + return SSH_ERR_INVALID_ARGUMENT; +- if (dlen == 0) +- return SSH_ERR_INTERNAL_ERROR; + + /* fetch signature */ + if ((b = sshbuf_from(signature, signaturelen)) == NULL) +@@ -176,25 +187,31 @@ ssh_dss_verify(const struct sshkey *key, + } + sig_r = sig_s = NULL; /* transferred */ + +- /* sha1 the data */ +- if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, +- digest, sizeof(digest))) != 0) ++ if ((slen = i2d_DSA_SIG(sig, NULL)) == 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; +- +- switch (DSA_do_verify(digest, dlen, sig, key->dsa)) { +- case 1: +- ret = 0; +- break; +- case 0: +- ret = SSH_ERR_SIGNATURE_INVALID; ++ } ++ if ((sigb = malloc(slen)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; + goto out; +- default: ++ } ++ psig = sigb; ++ if ((slen = i2d_DSA_SIG(sig, &psig)) == 0) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } + ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_DSA(pkey, key->dsa) != 1) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ret = sshkey_verify_signature(pkey, SSH_DIGEST_SHA1, data, datalen, ++ sigb, slen); ++ EVP_PKEY_free(pkey); ++ + out: +- explicit_bzero(digest, sizeof(digest)); ++ free(sigb); + DSA_SIG_free(sig); + BN_clear_free(sig_r); + BN_clear_free(sig_s); +diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c +index 599c7199d..b036796e8 100644 +--- a/ssh-ecdsa.c ++++ b/ssh-ecdsa.c +@@ -50,11 +50,13 @@ int + ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, u_int compat) + { ++ EVP_PKEY *pkey = NULL; + ECDSA_SIG *sig = NULL; ++ unsigned char *sigb = NULL; ++ const unsigned char *psig; + const BIGNUM *sig_r, *sig_s; + int hash_alg; +- u_char digest[SSH_DIGEST_MAX_LENGTH]; +- size_t len, dlen; ++ int len; + struct sshbuf *b = NULL, *bb = NULL; + int ret = SSH_ERR_INTERNAL_ERROR; + +@@ -67,18 +69,24 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + sshkey_type_plain(key->type) != KEY_ECDSA) + return SSH_ERR_INVALID_ARGUMENT; + +- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || +- (dlen = ssh_digest_bytes(hash_alg)) == 0) ++ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) + return SSH_ERR_INTERNAL_ERROR; +- if ((ret = ssh_digest_memory(hash_alg, data, datalen, +- digest, sizeof(digest))) != 0) ++ ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ ret = sshkey_calculate_signature(pkey, hash_alg, &sigb, &len, data, ++ datalen); ++ EVP_PKEY_free(pkey); ++ if (ret < 0) { + goto out; ++ } + +- if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) { ++ psig = sigb; ++ if ((sig = d2i_ECDSA_SIG(NULL, &psig, len)) == NULL) { + ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; + } +- + if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; + goto out; +@@ -102,7 +110,7 @@ ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + *lenp = len; + ret = 0; + out: +- explicit_bzero(digest, sizeof(digest)); ++ free(sigb); + sshbuf_free(b); + sshbuf_free(bb); + ECDSA_SIG_free(sig); +@@ -115,22 +123,21 @@ ssh_ecdsa_verify(const struct sshkey *key, + const u_char *signature, size_t signaturelen, + const u_char *data, size_t datalen, u_int compat) + { ++ EVP_PKEY *pkey = NULL; + ECDSA_SIG *sig = NULL; + BIGNUM *sig_r = NULL, *sig_s = NULL; +- int hash_alg; +- u_char digest[SSH_DIGEST_MAX_LENGTH]; +- size_t dlen; ++ int hash_alg, len; + int ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL, *sigbuf = NULL; + char *ktype = NULL; ++ unsigned char *sigb = NULL, *psig = NULL; + + if (key == NULL || key->ecdsa == NULL || + sshkey_type_plain(key->type) != KEY_ECDSA || + signature == NULL || signaturelen == 0) + return SSH_ERR_INVALID_ARGUMENT; + +- if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 || +- (dlen = ssh_digest_bytes(hash_alg)) == 0) ++ if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1) + return SSH_ERR_INTERNAL_ERROR; + + /* fetch signature */ +@@ -166,28 +173,36 @@ ssh_ecdsa_verify(const struct sshkey *key, + } + sig_r = sig_s = NULL; /* transferred */ + +- if (sshbuf_len(sigbuf) != 0) { +- ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; ++ /* Figure out the length */ ++ if ((len = i2d_ECDSA_SIG(sig, NULL)) == 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ if ((sigb = malloc(len)) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((ret = ssh_digest_memory(hash_alg, data, datalen, +- digest, sizeof(digest))) != 0) ++ psig = sigb; ++ if ((len = i2d_ECDSA_SIG(sig, &psig)) == 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; + goto out; ++ } + +- switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) { +- case 1: +- ret = 0; +- break; +- case 0: +- ret = SSH_ERR_SIGNATURE_INVALID; ++ if (sshbuf_len(sigbuf) != 0) { ++ ret = SSH_ERR_UNEXPECTED_TRAILING_DATA; + goto out; +- default: +- ret = SSH_ERR_LIBCRYPTO_ERROR; ++ } ++ ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_EC_KEY(pkey, key->ecdsa) != 1) { ++ ret = SSH_ERR_ALLOC_FAIL; + goto out; + } ++ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, sigb, len); ++ EVP_PKEY_free(pkey); + + out: +- explicit_bzero(digest, sizeof(digest)); ++ free(sigb); + sshbuf_free(sigbuf); + sshbuf_free(b); + ECDSA_SIG_free(sig); +diff --git a/ssh-rsa.c b/ssh-rsa.c +index 9b14f9a9a..8ef3a6aca 100644 +--- a/ssh-rsa.c ++++ b/ssh-rsa.c +@@ -37,7 +37,7 @@ + + #include "openbsd-compat/openssl-compat.h" + +-static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *); ++static int openssh_RSA_verify(int, const u_char *, size_t, u_char *, size_t, EVP_PKEY *); + + static const char * + rsa_hash_alg_ident(int hash_alg) +@@ -90,21 +90,6 @@ rsa_hash_id_from_keyname(const char *alg) + return -1; + } + +-static int +-rsa_hash_alg_nid(int type) +-{ +- switch (type) { +- case SSH_DIGEST_SHA1: +- return NID_sha1; +- case SSH_DIGEST_SHA256: +- return NID_sha256; +- case SSH_DIGEST_SHA512: +- return NID_sha512; +- default: +- return -1; +- } +-} +- + int + ssh_rsa_complete_crt_parameters(struct sshkey *key, const BIGNUM *iqmp) + { +@@ -164,11 +149,10 @@ int + ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + const u_char *data, size_t datalen, const char *alg_ident) + { +- const BIGNUM *rsa_n; +- u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL; +- size_t slen = 0; +- u_int dlen, len; +- int nid, hash_alg, ret = SSH_ERR_INTERNAL_ERROR; ++ EVP_PKEY *pkey = NULL; ++ u_char *sig = NULL; ++ int len, slen = 0; ++ int hash_alg, ret = SSH_ERR_INTERNAL_ERROR; + struct sshbuf *b = NULL; + + if (lenp != NULL) +@@ -180,33 +164,24 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + hash_alg = SSH_DIGEST_SHA1; + else + hash_alg = rsa_hash_id_from_keyname(alg_ident); ++ + if (key == NULL || key->rsa == NULL || hash_alg == -1 || + sshkey_type_plain(key->type) != KEY_RSA) + return SSH_ERR_INVALID_ARGUMENT; +- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); +- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) +- return SSH_ERR_KEY_LENGTH; + slen = RSA_size(key->rsa); +- if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) +- return SSH_ERR_INVALID_ARGUMENT; +- +- /* hash the data */ +- nid = rsa_hash_alg_nid(hash_alg); +- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) +- return SSH_ERR_INTERNAL_ERROR; +- if ((ret = ssh_digest_memory(hash_alg, data, datalen, +- digest, sizeof(digest))) != 0) +- goto out; ++ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) ++ return SSH_ERR_KEY_LENGTH; + +- if ((sig = malloc(slen)) == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) ++ return SSH_ERR_ALLOC_FAIL; ++ ret = sshkey_calculate_signature(pkey, hash_alg, &sig, &len, data, ++ datalen); ++ EVP_PKEY_free(pkey); ++ if (ret < 0) { + goto out; + } + +- if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) { +- ret = SSH_ERR_LIBCRYPTO_ERROR; +- goto out; +- } + if (len < slen) { + size_t diff = slen - len; + memmove(sig + diff, sig, len); +@@ -215,6 +190,7 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + ret = SSH_ERR_INTERNAL_ERROR; + goto out; + } ++ + /* encode signature */ + if ((b = sshbuf_new()) == NULL) { + ret = SSH_ERR_ALLOC_FAIL; +@@ -235,7 +211,6 @@ ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp, + *lenp = len; + ret = 0; + out: +- explicit_bzero(digest, sizeof(digest)); + freezero(sig, slen); + sshbuf_free(b); + return ret; +@@ -246,10 +221,10 @@ ssh_rsa_verify(const struct sshkey *key, + const u_char *sig, size_t siglen, const u_char *data, size_t datalen, + const char *alg) + { +- const BIGNUM *rsa_n; ++ EVP_PKEY *pkey = NULL; + char *sigtype = NULL; + int hash_alg, want_alg, ret = SSH_ERR_INTERNAL_ERROR; +- size_t len = 0, diff, modlen, dlen; ++ size_t len = 0, diff, modlen; + struct sshbuf *b = NULL; + u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL; + +@@ -257,8 +232,7 @@ ssh_rsa_verify(const struct sshkey *key, + sshkey_type_plain(key->type) != KEY_RSA || + sig == NULL || siglen == 0) + return SSH_ERR_INVALID_ARGUMENT; +- RSA_get0_key(key->rsa, &rsa_n, NULL, NULL); +- if (BN_num_bits(rsa_n) < SSH_RSA_MINIMUM_MODULUS_SIZE) ++ if (RSA_bits(key->rsa) < SSH_RSA_MINIMUM_MODULUS_SIZE) + return SSH_ERR_KEY_LENGTH; + + if ((b = sshbuf_from(sig, siglen)) == NULL) +@@ -310,16 +284,15 @@ ssh_rsa_verify(const struct sshkey *key, + explicit_bzero(sigblob, diff); + len = modlen; + } +- if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { +- ret = SSH_ERR_INTERNAL_ERROR; ++ ++ if ((pkey = EVP_PKEY_new()) == NULL || ++ EVP_PKEY_set1_RSA(pkey, key->rsa) != 1) { ++ ret = SSH_ERR_ALLOC_FAIL; + goto out; + } +- if ((ret = ssh_digest_memory(hash_alg, data, datalen, +- digest, sizeof(digest))) != 0) +- goto out; ++ ret = openssh_RSA_verify(hash_alg, data, datalen, sigblob, len, pkey); ++ EVP_PKEY_free(pkey); + +- ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, +- key->rsa); + out: + freezero(sigblob, len); + free(sigtype); +@@ -328,122 +301,26 @@ ssh_rsa_verify(const struct sshkey *key, + return ret; + } + +-/* +- * See: +- * http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/ +- * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.asn +- */ +- +-/* +- * id-sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) +- * oiw(14) secsig(3) algorithms(2) 26 } +- */ +-static const u_char id_sha1[] = { +- 0x30, 0x21, /* type Sequence, length 0x21 (33) */ +- 0x30, 0x09, /* type Sequence, length 0x09 */ +- 0x06, 0x05, /* type OID, length 0x05 */ +- 0x2b, 0x0e, 0x03, 0x02, 0x1a, /* id-sha1 OID */ +- 0x05, 0x00, /* NULL */ +- 0x04, 0x14 /* Octet string, length 0x14 (20), followed by sha1 hash */ +-}; +- +-/* +- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html +- * id-sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) +- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) +- * id-sha256(1) } +- */ +-static const u_char id_sha256[] = { +- 0x30, 0x31, /* type Sequence, length 0x31 (49) */ +- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ +- 0x06, 0x09, /* type OID, length 0x09 */ +- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, /* id-sha256 */ +- 0x05, 0x00, /* NULL */ +- 0x04, 0x20 /* Octet string, length 0x20 (32), followed by sha256 hash */ +-}; +- +-/* +- * See http://csrc.nist.gov/groups/ST/crypto_apps_infra/csor/algorithms.html +- * id-sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) +- * organization(1) gov(101) csor(3) nistAlgorithm(4) hashAlgs(2) +- * id-sha256(3) } +- */ +-static const u_char id_sha512[] = { +- 0x30, 0x51, /* type Sequence, length 0x51 (81) */ +- 0x30, 0x0d, /* type Sequence, length 0x0d (13) */ +- 0x06, 0x09, /* type OID, length 0x09 */ +- 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, /* id-sha512 */ +- 0x05, 0x00, /* NULL */ +- 0x04, 0x40 /* Octet string, length 0x40 (64), followed by sha512 hash */ +-}; +- + static int +-rsa_hash_alg_oid(int hash_alg, const u_char **oidp, size_t *oidlenp) ++openssh_RSA_verify(int hash_alg, const u_char *data, size_t datalen, ++ u_char *sigbuf, size_t siglen, EVP_PKEY *pkey) + { +- switch (hash_alg) { +- case SSH_DIGEST_SHA1: +- *oidp = id_sha1; +- *oidlenp = sizeof(id_sha1); +- break; +- case SSH_DIGEST_SHA256: +- *oidp = id_sha256; +- *oidlenp = sizeof(id_sha256); +- break; +- case SSH_DIGEST_SHA512: +- *oidp = id_sha512; +- *oidlenp = sizeof(id_sha512); +- break; +- default: +- return SSH_ERR_INVALID_ARGUMENT; +- } +- return 0; +-} ++ size_t rsasize = 0; ++ const RSA *rsa; ++ int ret; + +-static int +-openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen, +- u_char *sigbuf, size_t siglen, RSA *rsa) +-{ +- size_t rsasize = 0, oidlen = 0, hlen = 0; +- int ret, len, oidmatch, hashmatch; +- const u_char *oid = NULL; +- u_char *decrypted = NULL; +- +- if ((ret = rsa_hash_alg_oid(hash_alg, &oid, &oidlen)) != 0) +- return ret; +- ret = SSH_ERR_INTERNAL_ERROR; +- hlen = ssh_digest_bytes(hash_alg); +- if (hashlen != hlen) { +- ret = SSH_ERR_INVALID_ARGUMENT; +- goto done; +- } ++ rsa = EVP_PKEY_get0_RSA(pkey); + rsasize = RSA_size(rsa); + if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM || + siglen == 0 || siglen > rsasize) { + ret = SSH_ERR_INVALID_ARGUMENT; + goto done; + } +- if ((decrypted = malloc(rsasize)) == NULL) { +- ret = SSH_ERR_ALLOC_FAIL; +- goto done; +- } +- if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, +- RSA_PKCS1_PADDING)) < 0) { +- ret = SSH_ERR_LIBCRYPTO_ERROR; +- goto done; +- } +- if (len < 0 || (size_t)len != hlen + oidlen) { +- ret = SSH_ERR_INVALID_FORMAT; +- goto done; +- } +- oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; +- hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; +- if (!oidmatch || !hashmatch) { +- ret = SSH_ERR_SIGNATURE_INVALID; +- goto done; +- } +- ret = 0; ++ ++ ret = sshkey_verify_signature(pkey, hash_alg, data, datalen, ++ sigbuf, siglen); ++ + done: +- freezero(decrypted, rsasize); + return ret; + } + #endif /* WITH_OPENSSL */ +diff --git a/sshkey.c b/sshkey.c +index ad1957762..b95ed0b10 100644 +--- a/sshkey.c ++++ b/sshkey.c +@@ -358,6 +358,83 @@ sshkey_type_plain(int type) + } + + #ifdef WITH_OPENSSL ++int ++sshkey_calculate_signature(EVP_PKEY *pkey, int hash_alg, u_char **sigp, ++ int *lenp, const u_char *data, size_t datalen) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ u_char *sig = NULL; ++ int ret, slen, len; ++ ++ if (sigp == NULL || lenp == NULL) { ++ return SSH_ERR_INVALID_ARGUMENT; ++ } ++ ++ slen = EVP_PKEY_size(pkey); ++ if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM) ++ return SSH_ERR_INVALID_ARGUMENT; ++ ++ len = slen; ++ if ((sig = malloc(slen)) == NULL) { ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ ++ if ((ctx = EVP_MD_CTX_new()) == NULL) { ++ ret = SSH_ERR_ALLOC_FAIL; ++ goto error; ++ } ++ if (EVP_SignInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || ++ EVP_SignUpdate(ctx, data, datalen) <= 0 || ++ EVP_SignFinal(ctx, sig, &len, pkey) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto error; ++ } ++ ++ *sigp = sig; ++ *lenp = len; ++ /* Now owned by the caller */ ++ sig = NULL; ++ ret = 0; ++ ++error: ++ EVP_MD_CTX_free(ctx); ++ free(sig); ++ return ret; ++} ++ ++int ++sshkey_verify_signature(EVP_PKEY *pkey, int hash_alg, const u_char *data, ++ size_t datalen, u_char *sigbuf, int siglen) ++{ ++ EVP_MD_CTX *ctx = NULL; ++ int ret; ++ ++ if ((ctx = EVP_MD_CTX_new()) == NULL) { ++ return SSH_ERR_ALLOC_FAIL; ++ } ++ if (EVP_VerifyInit_ex(ctx, ssh_digest_to_md(hash_alg), NULL) <= 0 || ++ EVP_VerifyUpdate(ctx, data, datalen) <= 0) { ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ goto done; ++ } ++ ret = EVP_VerifyFinal(ctx, sigbuf, siglen, pkey); ++ switch (ret) { ++ case 1: ++ ret = 0; ++ break; ++ case 0: ++ ret = SSH_ERR_SIGNATURE_INVALID; ++ break; ++ default: ++ ret = SSH_ERR_LIBCRYPTO_ERROR; ++ break; ++ } ++ ++done: ++ EVP_MD_CTX_free(ctx); ++ return ret; ++} ++ + /* XXX: these are really begging for a table-driven approach */ + int + sshkey_curve_name_to_nid(const char *name) +diff --git a/sshkey.h b/sshkey.h +index a91e60436..270901a87 100644 +--- a/sshkey.h ++++ b/sshkey.h +@@ -179,6 +179,10 @@ const char *sshkey_ssh_name(const struct sshkey *); + const char *sshkey_ssh_name_plain(const struct sshkey *); + int sshkey_names_valid2(const char *, int); + char *sshkey_alg_list(int, int, int, char); ++int sshkey_calculate_signature(EVP_PKEY*, int, u_char **, ++ int *, const u_char *, size_t); ++int sshkey_verify_signature(EVP_PKEY *, int, const u_char *, ++ size_t, u_char *, int); + + int sshkey_from_blob(const u_char *, size_t, struct sshkey **); + int sshkey_fromb(struct sshbuf *, struct sshkey **); + diff --git a/openssh-8.0p1-openssl-kdf.patch b/openssh-8.0p1-openssl-kdf.patch new file mode 100644 index 0000000000000000000000000000000000000000..1db95c32e0884103c40db09893e74bb67250ea7b --- /dev/null +++ b/openssh-8.0p1-openssl-kdf.patch @@ -0,0 +1,137 @@ +commit 2c3ef499bfffce3cfd315edeebf202850ba4e00a +Author: Jakub Jelen +Date: Tue Apr 16 15:35:18 2019 +0200 + + Use the new OpenSSL KDF + +diff --git a/configure.ac b/configure.ac +index 2a455e4e..e01c3d43 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -2712,6 +2712,7 @@ if test "x$openssl" = "xyes" ; then + HMAC_CTX_init \ + RSA_generate_key_ex \ + RSA_get_default_method \ ++ EVP_KDF_CTX_new_id \ + ]) + + # OpenSSL_add_all_algorithms may be a macro. +diff --git a/kex.c b/kex.c +index b6f041f4..1fbce2bb 100644 +--- a/kex.c ++++ b/kex.c +@@ -38,6 +38,9 @@ + #ifdef WITH_OPENSSL + #include + #include ++# ifdef HAVE_EVP_KDF_CTX_NEW_ID ++# include ++# endif + #endif + + #include "ssh.h" +@@ -942,6 +945,95 @@ kex_choose_conf(struct ssh *ssh) + return r; + } + ++#ifdef HAVE_EVP_KDF_CTX_NEW_ID ++static const EVP_MD * ++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 int ++derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, ++ const struct sshbuf *shared_secret, u_char **keyp) ++{ ++ struct kex *kex = ssh->kex; ++ EVP_KDF_CTX *ctx = NULL; ++ u_char *key = NULL; ++ int r, key_len; ++ ++ if ((key_len = ssh_digest_bytes(kex->hash_alg)) == 0) ++ return SSH_ERR_INVALID_ARGUMENT; ++ key_len = ROUNDUP(need, key_len); ++ if ((key = calloc(1, key_len)) == NULL) { ++ r = SSH_ERR_ALLOC_FAIL; ++ goto out; ++ } ++ ++ ctx = EVP_KDF_CTX_new_id(EVP_KDF_SSHKDF); ++ if (!ctx) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ ++ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_MD, digest_to_md(kex->hash_alg)); ++ if (r != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_KEY, ++ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret)); ++ if (r != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_XCGHASH, hash, hashlen); ++ if (r != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_TYPE, id); ++ if (r != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ r = EVP_KDF_ctrl(ctx, EVP_KDF_CTRL_SET_SSHKDF_SESSION_ID, ++ kex->session_id, kex->session_id_len); ++ if (r != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++ r = EVP_KDF_derive(ctx, key, key_len); ++ if (r != 1) { ++ r = SSH_ERR_LIBCRYPTO_ERROR; ++ goto out; ++ } ++#ifdef DEBUG_KEX ++ fprintf(stderr, "key '%c'== ", id); ++ dump_digest("key", key, key_len); ++#endif ++ *keyp = key; ++ key = NULL; ++ r = 0; ++ ++out: ++ free (key); ++ EVP_KDF_CTX_free(ctx); ++ if (r < 0) { ++ return r; ++ } ++ return 0; ++} ++#else + static int + derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, + const struct sshbuf *shared_secret, u_char **keyp) +@@ -1004,6 +1096,7 @@ derive_key(struct ssh *ssh, int id, u_int need, u_char *hash, u_int hashlen, + ssh_digest_free(hashctx); + return r; + } ++#endif /* HAVE_OPENSSL_EVP_KDF_CTX_NEW_ID */ + + #define NKEYS 6 + int + diff --git a/openssh-7.6p1-pkcs11-uri.patch b/openssh-8.0p1-pkcs11-uri.patch similarity index 41% rename from openssh-7.6p1-pkcs11-uri.patch rename to openssh-8.0p1-pkcs11-uri.patch index 6fd463e8fc7204b804591ee4d3407dbf12c45cb7..50fd29af7af5be98f0dd3da2177f41176cec179e 100644 --- a/openssh-7.6p1-pkcs11-uri.patch +++ b/openssh-8.0p1-pkcs11-uri.patch @@ -1,55 +1,83 @@ +commit ed3eaf7d68c083b6015ca3425b75932999dafaad +Author: Jakub Jelen +Date: Wed Apr 24 17:23:21 2019 +0200 + + PKCS#11 URI from Fedora + + * Print PKCS#11 URIs from ssh-keygen + * Accept PKCS#11 URIs in -i argument to ssh + * Allow PKCS#11 URI specification in ssh_config + * Fallback to p11-kit-proxy + * PKCS#11 URI support for ssh-add and ssh-agent + * internal representation is URI + * Allow to specify pin-value in URI to avoid interactive prompts + + Currently recognized and used parts of PKCS#11 URI: + * path (optional) + * token + * id + * manufacturer + * (library-manufacturer) + * query (optional) + * module-path + * pin-value + + Unit test for PKCS#11 URIs + + * test PKCS#11 URI parser, generator + * test percent_encodeer and decoder + + Regression tests for PKCS#11 URI support + + * soft-pkcs11.so from people.su.se/~lha/soft-pkcs11 + * Return correct CKR for unknown attributes + * Adjust and build it with regress tests (allowing agent-pkcs11 test) + * Test PKCS#11 URIs support with soft-pkcs11 + * Direct usage from commandline (URI, provider and combination) + * Usage from configuration files + * Usage in ssh-agent (add, sign, remove) + * Make sure it is built with correct paths + diff --git a/Makefile.in b/Makefile.in -index ac959c1f..f8ed1781 100644 +index e7549470..4511f82a 100644 --- a/Makefile.in +++ b/Makefile.in -@@ -93,7 +93,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ - monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ - kexgssc.o \ +@@ -102,7 +102,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ + monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-ecdsa-sk.o \ + ssh-ed25519-sk.o ssh-rsa.o dh.o \ msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ - ssh-pkcs11.o smult_curve25519_ref.o \ + ssh-pkcs11.o ssh-pkcs11-uri.o smult_curve25519_ref.o \ - poly1305.o chacha.o cipher-chachapoly.o \ - ssh-ed25519.o digest-openssl.o digest-libc.o hmac.o \ - sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ -@@ -248,6 +248,8 @@ clean: regressclean + poly1305.o chacha.o cipher-chachapoly.o cipher-chachapoly-libcrypto.o \ + ssh-ed25519.o digest-openssl.o digest-libc.o \ + hmac.o sc25519.o ge25519.o fe25519.o ed25519.o verify.o hash.o \ +@@ -289,6 +289,8 @@ clean: regressclean rm -f regress/unittests/match/test_match$(EXEEXT) rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8$(EXEEXT) + rm -f regress/unittests/pkcs11/*.o + rm -f regress/unittests/pkcs11/test_pkcs11$(EXEEXT) - rm -f regress/misc/kexfuzz/*.o - rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) - (cd openbsd-compat && $(MAKE) clean) -@@ -276,6 +278,8 @@ distclean: regressclean + rm -f regress/misc/kexfuzz/*.o + rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) + rm -f regress/misc/sk-dummy/*.o +@@ -322,6 +324,8 @@ distclean: regressclean rm -f regress/unittests/match/test_match rm -f regress/unittests/utf8/*.o rm -f regress/unittests/utf8/test_utf8 + rm -f regress/unittests/pkcs11/*.o + rm -f regress/unittests/pkcs11/test_pkcs11 - rm -f regress/misc/kexfuzz/*.o - rm -f regress/misc/kexfuzz - (cd openbsd-compat && $(MAKE) distclean) -@@ -437,6 +441,7 @@ regress-prep: + rm -f regress/misc/kexfuzz/*.o + rm -f regress/misc/kexfuzz/kexfuzz$(EXEEXT) + (cd openbsd-compat && $(MAKE) distclean) +@@ -490,6 +494,7 @@ regress-prep: $(MKDIR_P) `pwd`/regress/unittests/kex $(MKDIR_P) `pwd`/regress/unittests/match $(MKDIR_P) `pwd`/regress/unittests/utf8 + $(MKDIR_P) `pwd`/regress/unittests/pkcs11 $(MKDIR_P) `pwd`/regress/misc/kexfuzz + $(MKDIR_P) `pwd`/regress/misc/sk-dummy [ -f `pwd`/regress/Makefile ] || \ - ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile -@@ -455,6 +460,11 @@ regress/netcat$(EXEEXT): $(srcdir)/regress/netcat.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/netcat.c \ - $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) - -+regress/soft-pkcs11.so: $(srcdir)/regress/soft-pkcs11.c $(REGRESSLIBS) -+ $(CC) $(CFLAGS) $(CPPFLAGS) -fpic -c $(srcdir)/regress/soft-pkcs11.c \ -+ -o $(srcdir)/regress/soft-pkcs11.o -+ $(CC) -shared -o $@ $(srcdir)/regress/soft-pkcs11.o -+ - regress/check-perm$(EXEEXT): $(srcdir)/regress/check-perm.c $(REGRESSLIBS) - $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $(srcdir)/regress/check-perm.c \ - $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) -@@ -556,6 +566,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \ +@@ -617,6 +622,16 @@ regress/unittests/utf8/test_utf8$(EXEEXT): \ regress/unittests/test_helper/libtest_helper.a \ -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) @@ -64,42 +92,21 @@ index ac959c1f..f8ed1781 100644 + -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) + MISC_KEX_FUZZ_OBJS=\ - regress/misc/kexfuzz/kexfuzz.o - -@@ -566,6 +586,7 @@ regress/misc/kexfuzz/kexfuzz$(EXEEXT): ${MISC_KEX_FUZZ_OBJS} libssh.a - regress-binaries: regress/modpipe$(EXEEXT) \ - regress/setuid-allowed$(EXEEXT) \ - regress/netcat$(EXEEXT) \ -+ regress/soft-pkcs11.so \ - regress/check-perm$(EXEEXT) \ - regress/mkdtemp$(EXEEXT) \ - regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \ -@@ -575,6 +596,7 @@ regress-binaries: regress/modpipe$(EXEEXT) \ + regress/misc/kexfuzz/kexfuzz.o \ + $(SKOBJS) +@@ -655,6 +670,7 @@ regress-unit-binaries: regress-prep $(REGRESSLIBS) \ regress/unittests/kex/test_kex$(EXEEXT) \ regress/unittests/match/test_match$(EXEEXT) \ regress/unittests/utf8/test_utf8$(EXEEXT) \ + regress/unittests/pkcs11/test_pkcs11$(EXEEXT) \ regress/misc/kexfuzz/kexfuzz$(EXEEXT) - tests interop-tests t-exec unit: regress-prep regress-binaries $(TARGETS) -diff --git a/authfd.c b/authfd.c -index 1eff7ba9..35153f47 100644 ---- a/authfd.c -+++ b/authfd.c -@@ -312,6 +312,8 @@ ssh_free_identitylist(struct ssh_identitylist *idl) - if (idl->comments != NULL) - free(idl->comments[i]); - } -+ free(idl->keys); -+ free(idl->comments); - free(idl); - } - + tests: file-tests t-exec interop-tests unit diff --git a/configure.ac b/configure.ac -index d7bcaf01..171a8597 100644 +index b689db4b..98d3ce4f 100644 --- a/configure.ac +++ b/configure.ac -@@ -1895,12 +1895,14 @@ AC_LINK_IFELSE( +@@ -1911,12 +1911,14 @@ AC_LINK_IFELSE( [AC_DEFINE([HAVE_ISBLANK], [1], [Define if you have isblank(3C).]) ]) @@ -114,9 +121,9 @@ index d7bcaf01..171a8597 100644 fi ] ) -@@ -1916,6 +1918,40 @@ if test "x$openssl" = "xyes" && test "x$disable_pkcs11" = "x"; then - ) - fi +@@ -1945,6 +1947,40 @@ AC_SEARCH_LIBS([dlopen], [dl]) + AC_CHECK_FUNCS([dlopen]) + AC_CHECK_DECL([RTLD_NOW], [], [], [#include ]) +# Check whether we have a p11-kit, we got default provider on command line +DEFAULT_PKCS11_PROVIDER_MSG="no" @@ -155,33 +162,29 @@ index d7bcaf01..171a8597 100644 # IRIX has a const char return value for gai_strerror() AC_CHECK_FUNCS([gai_strerror], [ AC_DEFINE([HAVE_GAI_STRERROR]) -@@ -5226,6 +5262,7 @@ echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" +@@ -5401,6 +5437,7 @@ echo " BSD Auth support: $BSD_AUTH_MSG" echo " Random number source: $RAND_MSG" echo " Privsep sandbox style: $SANDBOX_STYLE" - echo " Vendor patch level: $SSH_VENDOR_PATCHLEVEL" + echo " PKCS#11 support: $enable_pkcs11" +echo " Default PKCS#11 provider: $DEFAULT_PKCS11_PROVIDER_MSG" + echo " U2F/FIDO support: $enable_sk" echo "" - diff --git a/regress/Makefile b/regress/Makefile -index d15898ad..9c15afa4 100644 +index 774c10d4..6bf3b627 100644 --- a/regress/Makefile +++ b/regress/Makefile -@@ -108,9 +110,11 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ +@@ -116,7 +116,8 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ known_hosts known_hosts-cert known_hosts.* krl-* ls.copy \ modpipe netcat no_identity_config \ - pidfile putty.rsa2 ready regress.log \ -- remote_pid revoked-* rsa rsa-agent rsa-agent.pub rsa.pub \ -+ remote_pid revoked-* rsa rsa-agent rsa-agent.pub \ -+ rsa-agent-cert.pub rsa.pub \ - rsa1 rsa1-agent rsa1-agent.pub rsa1.pub rsa_ssh2_cr.prv \ -- rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ -+ soft-pkcs11.so soft-pkcs11.o pkcs11*.crt pkcs11*.key \ -+ pkcs11.info rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ + pidfile putty.rsa2 ready regress.log remote_pid \ +- revoked-* rsa rsa-agent rsa-agent.pub rsa.pub rsa_ssh2_cr.prv \ ++ revoked-* rsa rsa-agent rsa-agent.pub rsa-agent-cert.pub \ ++ rsa.pub rsa_ssh2_cr.prv pkcs11*.crt pkcs11*.key pkcs11.info \ + rsa_ssh2_crnl.prv scp-ssh-wrapper.exe \ scp-ssh-wrapper.scp setuid-allowed sftp-server.log \ sftp-server.sh sftp.log ssh-log-wrapper.sh ssh.log \ - ssh_config ssh_config.* ssh_proxy ssh_proxy_bak \ -@@ -225,6 +229,7 @@ unit: +@@ -246,6 +247,7 @@ unit: V="" ; \ test "x${USE_VALGRIND}" = "x" || \ V=${.CURDIR}/valgrind-unit.sh ; \ @@ -190,39 +193,11 @@ index d15898ad..9c15afa4 100644 $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \ -d ${.CURDIR}/unittests/sshkey/testdata ; \ diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh -index db3018b8..4991d0bc 100644 +index fbbaea51..5d75d69f 100644 --- a/regress/agent-pkcs11.sh +++ b/regress/agent-pkcs11.sh -@@ -4,10 +4,17 @@ - tid="pkcs11 agent test" - - TEST_SSH_PIN="" --TEST_SSH_PKCS11=/usr/local/lib/soft-pkcs11.so.0.0 -+TEST_SSH_PKCS11=$OBJ/soft-pkcs11.so - - test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist" - -+# requires ssh-agent built with correct path to ssh-pkcs11-helper -+# otherwise it fails to start the helper -+strings ${TEST_SSH_SSHAGENT} | grep "$TEST_SSH_SSHPKCS11HELPER" -+if [ $? -ne 0 ]; then -+ fatal "Needs to reconfigure with --libexecdir=\`pwd\` or so" -+fi -+ - # setup environment for soft-pkcs11 token - SOFTPKCS11RC=$OBJ/pkcs11.info - export SOFTPKCS11RC -@@ -23,7 +30,7 @@ notty() { - } - - trace "start agent" --eval `${SSHAGENT} -s` > /dev/null -+eval `${SSHAGENT} -s -P "${OBJ}/*"` > /dev/null - r=$? - if [ $r -ne 0 ]; then - fail "could not start ssh-agent: exit code $r" -@@ -60,7 +67,7 @@ else - fi +@@ -113,7 +113,7 @@ else + done trace "remove pkcs11 keys" - echo ${TEST_SSH_PIN} | notty ${SSHADD} -e ${TEST_SSH_PKCS11} > /dev/null 2>&1 @@ -230,97 +205,12 @@ index db3018b8..4991d0bc 100644 r=$? if [ $r -ne 0 ]; then fail "ssh-add -e failed: exit code $r" -diff --git a/regress/locl.h b/regress/locl.h -new file mode 100644 -index 00000000..afefe27d ---- /dev/null -+++ b/regress/locl.h -@@ -0,0 +1,79 @@ -+/* -+ * Copyright (c) 2004, Stockholms universitet -+ * (Stockholm University, Stockholm Sweden) -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. -+ * -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * 3. Neither the name of the university nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+/* $Id: locl.h,v 1.5 2005/08/28 15:30:31 lha Exp $ */ -+ -+#ifdef HAVE_CONFIG_H -+#include -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include "../libcrypto-compat.h" -+ -+#include -+#include -+#include -+#include -+#define _GNU_SOURCE -+#include -+#include -+#include -+#include -+ -+#include "../pkcs11.h" -+ -+#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R) \ -+{ \ -+ unsigned char *p; \ -+ (BL) = i2d_##T((S), NULL); \ -+ if ((BL) <= 0) { \ -+ (R) = EINVAL; \ -+ } else { \ -+ (B) = malloc((BL)); \ -+ if ((B) == NULL) { \ -+ (R) = ENOMEM; \ -+ } else { \ -+ p = (B); \ -+ (R) = 0; \ -+ (BL) = i2d_##T((S), &p); \ -+ if ((BL) <= 0) { \ -+ free((B)); \ -+ (R) = EINVAL; \ -+ } \ -+ } \ -+ } \ -+} diff --git a/regress/pkcs11.sh b/regress/pkcs11.sh new file mode 100644 -index 00000000..cf98e379 +index 00000000..a91aee94 --- /dev/null +++ b/regress/pkcs11.sh -@@ -0,0 +1,300 @@ +@@ -0,0 +1,349 @@ +# +# Copyright (c) 2017 Red Hat +# @@ -340,26 +230,57 @@ index 00000000..cf98e379 + +tid="pkcs11 tests with soft token" + -+TEST_SSH_PIN="" -+TEST_SSH_PKCS11=$OBJ/soft-pkcs11.so ++try_token_libs() { ++ for _lib in "$@" ; do ++ if test -f "$_lib" ; then ++ verbose "Using token library $_lib" ++ TEST_SSH_PKCS11="$_lib" ++ return ++ fi ++ done ++ echo "skipped: Unable to find PKCS#11 token library" ++ exit 0 ++} ++ ++try_token_libs \ ++ /usr/local/lib/softhsm/libsofthsm2.so \ ++ /usr/lib64/pkcs11/libsofthsm2.so \ ++ /usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so ++ ++TEST_SSH_PIN=1234 ++TEST_SSH_SOPIN=12345678 ++if [ "x$TEST_SSH_SSHPKCS11HELPER" != "x" ]; then ++ SSH_PKCS11_HELPER="${TEST_SSH_SSHPKCS11HELPER}" ++ export SSH_PKCS11_HELPER ++fi + +test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist" + -+# requires ssh-agent built with correct path to ssh-pkcs11-helper -+# otherwise it fails to start the helper -+strings ${TEST_SSH_SSHAGENT} | grep "$TEST_SSH_SSHPKCS11HELPER" -+if [ $? -ne 0 ]; then -+ fatal "Needs to reconfigure with --libexecdir=\`pwd\` or so" -+fi ++# setup environment for softhsm token ++DIR=$OBJ/SOFTHSM ++rm -rf $DIR ++TOKEN=$DIR/tokendir ++mkdir -p $TOKEN ++SOFTHSM2_CONF=$DIR/softhsm2.conf ++export SOFTHSM2_CONF ++cat > $SOFTHSM2_CONF << EOF ++# SoftHSM v2 configuration file ++directories.tokendir = ${TOKEN} ++objectstore.backend = file ++# ERROR, WARNING, INFO, DEBUG ++log.level = DEBUG ++# If CKF_REMOVABLE_DEVICE flag should be set ++slots.removable = false ++EOF ++out=$(softhsm2-util --init-token --free --label token-slot-0 --pin "$TEST_SSH_PIN" --so-pin "$TEST_SSH_SOPIN") ++slot=$(echo -- $out | sed 's/.* //') + -+# setup environment for soft-pkcs11 token -+SOFTPKCS11RC=$OBJ/pkcs11.info -+rm -f $SOFTPKCS11RC -+export SOFTPKCS11RC +# prevent ssh-agent from calling ssh-askpass +SSH_ASKPASS=/usr/bin/true +export SSH_ASKPASS +unset DISPLAY ++# We need interactive access to test PKCS# since it prompts for PIN ++sed -i 's/.*BatchMode.*//g' $OBJ/ssh_proxy + +# start command w/o tty, so ssh accepts pin from stdin (from agent-pkcs11.sh) +notty() { @@ -367,136 +288,156 @@ index 00000000..cf98e379 + if (fork) { wait; exit($? >> 8); } else { exec(@ARGV) }' "$@" +} + -+create_key() { -+ ID=$1 -+ LABEL=$2 -+ rm -f $OBJ/pkcs11-${ID}.key $OBJ/pkcs11-${ID}.crt -+ openssl genrsa -out $OBJ/pkcs11-${ID}.key 2048 > /dev/null 2>&1 -+ chmod 600 $OBJ/pkcs11-${ID}.key -+ openssl req -key $OBJ/pkcs11-${ID}.key -new -x509 \ -+ -out $OBJ/pkcs11-${ID}.crt -text -subj '/CN=pkcs11 test' >/dev/null -+ printf "${ID}\t${LABEL}\t$OBJ/pkcs11-${ID}.crt\t$OBJ/pkcs11-${ID}.key\n" \ -+ >> $SOFTPKCS11RC -+} -+ -+trace "Create a key pairs on soft token" ++trace "generating keys" +ID1="02" +ID2="04" -+create_key "$ID1" "SSH RSA Key" -+create_key "$ID2" "SSH RSA Key 2" ++RSA=${DIR}/RSA ++EC=${DIR}/EC ++openssl genpkey -algorithm rsa > $RSA ++openssl pkcs8 -nocrypt -in $RSA |\ ++ softhsm2-util --slot "$slot" --label "SSH RSA Key $ID1" --id $ID1 \ ++ --pin "$TEST_SSH_PIN" --import /dev/stdin ++openssl genpkey \ ++ -genparam \ ++ -algorithm ec \ ++ -pkeyopt ec_paramgen_curve:prime256v1 |\ ++ openssl genpkey \ ++ -paramfile /dev/stdin > $EC ++openssl pkcs8 -nocrypt -in $EC |\ ++ softhsm2-util --slot "$slot" --label "SSH ECDSA Key $ID2" --id $ID2 \ ++ --pin "$TEST_SSH_PIN" --import /dev/stdin + +trace "List the keys in the ssh-keygen with PKCS#11 URIs" +${SSHKEYGEN} -D ${TEST_SSH_PKCS11} > $OBJ/token_keys +if [ $? -ne 0 ]; then -+ fail "keygen fails to enumerate keys on PKCS#11 token" ++ fail "FAIL: keygen fails to enumerate keys on PKCS#11 token" +fi +grep "pkcs11:" $OBJ/token_keys > /dev/null +if [ $? -ne 0 ]; then -+ fail "The keys from ssh-keygen do not contain PKCS#11 URI as a comment" ++ fail "FAIL: The keys from ssh-keygen do not contain PKCS#11 URI as a comment" +fi -+tail -n 1 $OBJ/token_keys > $OBJ/authorized_keys_$USER + ++# Set the ECDSA key to authorized keys ++grep "ECDSA" $OBJ/token_keys > $OBJ/authorized_keys_$USER + +trace "Simple connect with ssh (without PKCS#11 URI)" +echo ${TEST_SSH_PIN} | notty ${SSH} -I ${TEST_SSH_PKCS11} \ + -F $OBJ/ssh_proxy somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with pkcs11 failed (exit code $r)" ++ fail "FAIL: ssh connect with pkcs11 failed (exit code $r)" +fi + -+ +trace "Connect with PKCS#11 URI" -+trace " (second key should succeed)" ++trace " (ECDSA key should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)" +fi + -+trace " (first key should fail)" ++trace " (RSA key should fail)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++r=$? ++if [ $r -eq 5 ]; then ++ fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)" ++fi ++ ++trace "Connect with PKCS#11 URI including PIN should not prompt" ++trace " (ECDSA key should succeed)" ++${SSH} -F $OBJ/ssh_proxy -i \ ++ "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}&pin-value=${TEST_SSH_PIN}" somehost exit 5 ++r=$? ++if [ $r -ne 5 ]; then ++ fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)" ++fi ++ ++trace " (RSA key should fail)" ++${SSH} -F $OBJ/ssh_proxy -i \ ++ "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}&pin-value=${TEST_SSH_PIN}" somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)" +fi + +trace "Connect with various filtering options in PKCS#11 URI" -+trace " (by object label, second key should succeed)" ++trace " (by object label, ECDSA should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:object=SSH%20RSA%20Key%202?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:object=SSH%20ECDSA%20Key%2004?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)" +fi + -+trace " (by object label, first key should fail)" ++trace " (by object label, RSA key should fail)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:object=SSH%20RSA%20Key?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:object=SSH%20RSA%20Key%2002?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)" +fi + -+trace " (by token label, second key should succeed)" ++trace " (by token label, ECDSA key should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:id=${ID2};token=SoftToken%20(token)?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:id=%${ID2};token=token-slot-0?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI failed (exit code $r)" +fi + +trace " (by wrong token label, should fail)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:token=SoftToken?module-path=${TEST_SSH_PKCS11}" somehost exit 5 ++ -i "pkcs11:token=token-slot-99?module-path=${TEST_SSH_PKCS11}" somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI succeeded (should fail)" +fi + + + + +trace "Test PKCS#11 URI specification in configuration files" -+echo "IdentityFile \"pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}\"" \ ++echo "IdentityFile \"pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}\"" \ + >> $OBJ/ssh_proxy -+trace " (second key should succeed)" ++trace " (ECDSA key should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI in config failed (exit code $r)" ++ fail "FAIL: ssh connect with PKCS#11 URI in config failed (exit code $r)" +fi + -+trace " (first key should fail)" -+head -n 1 $OBJ/token_keys > $OBJ/authorized_keys_$USER ++# Set the RSA key as authorized ++grep "RSA" $OBJ/token_keys > $OBJ/authorized_keys_$USER ++ ++trace " (RSA key should fail)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5 +r=$? +if [ $r -eq 5 ]; then -+ fail "ssh connect with PKCS#11 URI in config succeeded (should fail)" ++ fail "FAIL: ssh connect with PKCS#11 URI in config succeeded (should fail)" +fi +sed -i -e "/IdentityFile/d" $OBJ/ssh_proxy + +trace "Test PKCS#11 URI specification in configuration files with bogus spaces" -+echo "IdentityFile \" pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11} \"" \ ++echo "IdentityFile \" pkcs11:?module-path=${TEST_SSH_PKCS11} \"" \ + >> $OBJ/ssh_proxy +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI with bogus spaces in config failed" \ ++ fail "FAIL: ssh connect with PKCS#11 URI with bogus spaces in config failed" \ + "(exit code $r)" +fi +sed -i -e "/IdentityFile/d" $OBJ/ssh_proxy + + +trace "Combination of PKCS11Provider and PKCS11URI on commandline" -+trace " (first key should succeed)" ++trace " (RSA key should succeed)" +echo ${TEST_SSH_PIN} | notty ${SSH} -F $OBJ/ssh_proxy \ -+ -i "pkcs11:id=${ID1}" -I ${TEST_SSH_PKCS11} somehost exit 5 ++ -i "pkcs11:id=%${ID1}" -I ${TEST_SSH_PKCS11} somehost exit 5 +r=$? +if [ $r -ne 5 ]; then -+ fail "ssh connect with PKCS#11 URI and provider combination" \ ++ fail "FAIL: ssh connect with PKCS#11 URI and provider combination" \ + "failed (exit code $r)" +fi + @@ -505,14 +446,14 @@ index 00000000..cf98e379 + -o IdentityFile=\"pkcs11:token=segfault\" somehost exit 5 +r=$? +if [ $r -eq 139 ]; then -+ fail "ssh connect with missing provider_id from configuration option" \ ++ fail "FAIL: ssh connect with missing provider_id from configuration option" \ + "crashed (exit code $r)" +fi + + +trace "SSH Agent can work with PKCS#11 URI" +trace "start the agent" -+eval `${SSHAGENT} -s -P "${OBJ}/*"` > /dev/null ++eval `${SSHAGENT} -s` > /dev/null + +r=$? +if [ $r -ne 0 ]; then @@ -520,2419 +461,345 @@ index 00000000..cf98e379 +else + trace "add whole provider to agent" + echo ${TEST_SSH_PIN} | notty ${SSHADD} \ -+ "pkcs11:?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 ++ "pkcs11:?module-path=${TEST_SSH_PKCS11}" #> /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add failed with whole provider: exit code $r" ++ fail "FAIL: ssh-add failed with whole provider: exit code $r" + fi + + trace " pkcs11 list via agent (all keys)" + ${SSHADD} -l > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add -l failed with whole provider: exit code $r" ++ fail "FAIL: ssh-add -l failed with whole provider: exit code $r" + fi + + trace " pkcs11 connect via agent (all keys)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -ne 5 ]; then -+ fail "ssh connect failed with whole provider (exit code $r)" ++ fail "FAIL: ssh connect failed with whole provider (exit code $r)" + fi + + trace " remove pkcs11 keys (all keys)" + ${SSHADD} -d "pkcs11:?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add -d failed with whole provider: exit code $r" ++ fail "FAIL: ssh-add -d failed with whole provider: exit code $r" + fi + -+ trace "add only first key to the agent" ++ trace "add only RSA key to the agent" + echo ${TEST_SSH_PIN} | notty ${SSHADD} \ -+ "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 ++ "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add failed with first key: exit code $r" ++ fail "FAIL ssh-add failed with RSA key: exit code $r" + fi + -+ trace " pkcs11 connect via agent (first key)" ++ trace " pkcs11 connect via agent (RSA key)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -ne 5 ]; then -+ fail "ssh connect failed with first key (exit code $r)" ++ fail "FAIL: ssh connect failed with RSA key (exit code $r)" + fi + -+ trace " remove first pkcs11 key" -+ ${SSHADD} -d "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" \ ++ trace " remove RSA pkcs11 key" ++ ${SSHADD} -d "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" \ + > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add -d failed with first key: exit code $r" ++ fail "FAIL: ssh-add -d failed with RSA key: exit code $r" + fi + -+ trace "add only second key to the agent" ++ trace "add only ECDSA key to the agent" + echo ${TEST_SSH_PIN} | notty ${SSHADD} \ -+ "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 ++ "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add failed with second key: exit code $r" ++ fail "FAIL: ssh-add failed with second key: exit code $r" + fi + -+ trace " pkcs11 connect via agent (second key should fail)" ++ trace " pkcs11 connect via agent (ECDSA key should fail)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -eq 5 ]; then -+ fail "ssh connect passed without key (should fail)" ++ fail "FAIL: ssh connect passed with ECDSA key (should fail)" + fi + -+ trace "add also the first key to the agent" ++ trace "add also the RSA key to the agent" + echo ${TEST_SSH_PIN} | notty ${SSHADD} \ -+ "pkcs11:id=${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 ++ "pkcs11:id=%${ID1}?module-path=${TEST_SSH_PKCS11}" > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add failed with first key: exit code $r" ++ fail "FAIL: ssh-add failed with first key: exit code $r" + fi + -+ trace " remove second pkcs11 key" -+ ${SSHADD} -d "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" \ ++ trace " remove ECDSA pkcs11 key" ++ ${SSHADD} -d "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" \ + > /dev/null 2>&1 + r=$? + if [ $r -ne 0 ]; then -+ fail "ssh-add -d failed with second key: exit code $r" ++ fail "ssh-add -d failed with ECDSA key: exit code $r" + fi + + trace " remove already-removed pkcs11 key should fail" -+ ${SSHADD} -d "pkcs11:id=${ID2}?module-path=${TEST_SSH_PKCS11}" \ ++ ${SSHADD} -d "pkcs11:id=%${ID2}?module-path=${TEST_SSH_PKCS11}" \ + > /dev/null 2>&1 + r=$? + if [ $r -eq 0 ]; then -+ fail "ssh-add -d passed with non-existing key (should fail)" ++ fail "FAIL: ssh-add -d passed with non-existing key (should fail)" + fi + -+ trace " pkcs11 connect via agent (the first key should be still usable)" ++ trace " pkcs11 connect via agent (the RSA key should be still usable)" + ${SSH} -F $OBJ/ssh_proxy somehost exit 5 + r=$? + if [ $r -ne 5 ]; then -+ fail "ssh connect failed with first key (after removing second): exit code $r" ++ fail "ssh connect failed with RSA key (after removing ECDSA): exit code $r" + fi + + trace "kill agent" + ${SSHAGENT} -k > /dev/null +fi -+ -+rm -rf $OBJ/.tokens $OBJ/token_keys -diff --git a/regress/soft-pkcs11.c b/regress/soft-pkcs11.c +diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile +index 4e56e110..2690ebeb 100644 +--- a/regress/unittests/Makefile ++++ b/regress/unittests/Makefile +@@ -2,6 +2,6 @@ + + REGRESS_FAIL_EARLY?= yes + SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion +-SUBDIR+=authopt misc ++SUBDIR+=authopt misc pkcs11 + + .include +diff --git a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c new file mode 100644 -index 00000000..8b4981bd +index 00000000..b637cb13 --- /dev/null -+++ b/regress/soft-pkcs11.c -@@ -0,0 +1,2058 @@ ++++ b/regress/unittests/pkcs11/tests.c +@@ -0,0 +1,337 @@ +/* -+ * Copyright (c) 2004-2006, Stockholms universitet -+ * (Stockholm University, Stockholm Sweden) -+ * All rights reserved. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer. ++ * Copyright (c) 2017 Red Hat + * -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. ++ * Authors: Jakub Jelen + * -+ * 3. Neither the name of the university nor the names of its contributors -+ * may be used to endorse or promote products derived from this software -+ * without specific prior written permission. ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. + * -+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -+ * POSSIBILITY OF SUCH DAMAGE. ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + -+#include "locl.h" -+ -+/* RCSID("$Id: main.c,v 1.24 2006/01/11 12:42:53 lha Exp $"); */ -+ -+#define OBJECT_ID_MASK 0xfff -+#define HANDLE_OBJECT_ID(h) ((h) & OBJECT_ID_MASK) -+#define OBJECT_ID(obj) HANDLE_OBJECT_ID((obj)->object_handle) ++#include "includes.h" + -+#if OPENSSL_VERSION_NUMBER < 0x10100000L -+ #define RSA_PKCS1_SSLeay RSA_PKCS1_OpenSSL -+#endif ++#include ++#include + -+struct st_attr { -+ CK_ATTRIBUTE attribute; -+ int secret; -+}; ++#include "../test_helper/test_helper.h" + -+struct st_object { -+ CK_OBJECT_HANDLE object_handle; -+ struct st_attr *attrs; -+ int num_attributes; -+ enum { -+ STO_T_CERTIFICATE, -+ STO_T_PRIVATE_KEY, -+ STO_T_PUBLIC_KEY -+ } type; -+ union { -+ X509 *cert; -+ EVP_PKEY *public_key; -+ struct { -+ const char *file; -+ EVP_PKEY *key; -+ X509 *cert; -+ } private_key; -+ } u; -+}; ++#include "sshbuf.h" ++#include "ssh-pkcs11-uri.h" + -+static struct soft_token { -+ CK_VOID_PTR application; -+ CK_NOTIFY notify; -+ struct { -+ struct st_object **objs; -+ int num_objs; -+ } object; -+ struct { -+ int hardware_slot; -+ int app_error_fatal; -+ int login_done; -+ } flags; -+ int open_sessions; -+ struct session_state { -+ CK_SESSION_HANDLE session_handle; -+ -+ struct { -+ CK_ATTRIBUTE *attributes; -+ CK_ULONG num_attributes; -+ int next_object; -+ } find; -+ -+ int encrypt_object; -+ CK_MECHANISM_PTR encrypt_mechanism; -+ int decrypt_object; -+ CK_MECHANISM_PTR decrypt_mechanism; -+ int sign_object; -+ CK_MECHANISM_PTR sign_mechanism; -+ int verify_object; -+ CK_MECHANISM_PTR verify_mechanism; -+ int digest_object; -+ } state[10]; -+#define MAX_NUM_SESSION (sizeof(soft_token.state)/sizeof(soft_token.state[0])) -+ FILE *logfile; -+} soft_token; ++#define EMPTY_URI compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL) + -+static void -+application_error(const char *fmt, ...) -+{ -+ va_list ap; -+ va_start(ap, fmt); -+ vprintf(fmt, ap); -+ va_end(ap); -+ if (soft_token.flags.app_error_fatal) -+ abort(); -+} ++/* prototypes are not public -- specify them here internally for tests */ ++struct sshbuf *percent_encode(const char *, size_t, char *); ++int percent_decode(char *, char **); + -+static void -+st_logf(const char *fmt, ...) ++void ++compare_uri(struct pkcs11_uri *a, struct pkcs11_uri *b) +{ -+ va_list ap; -+ if (soft_token.logfile == NULL) -+ return; -+ va_start(ap, fmt); -+ vfprintf(soft_token.logfile, fmt, ap); -+ va_end(ap); -+ fflush(soft_token.logfile); ++ ASSERT_PTR_NE(a, NULL); ++ ASSERT_PTR_NE(b, NULL); ++ ASSERT_SIZE_T_EQ(a->id_len, b->id_len); ++ ASSERT_MEM_EQ(a->id, b->id, a->id_len); ++ if (b->object != NULL) ++ ASSERT_STRING_EQ(a->object, b->object); ++ else /* both should be null */ ++ ASSERT_PTR_EQ(a->object, b->object); ++ if (b->module_path != NULL) ++ ASSERT_STRING_EQ(a->module_path, b->module_path); ++ else /* both should be null */ ++ ASSERT_PTR_EQ(a->module_path, b->module_path); ++ if (b->token != NULL) ++ ASSERT_STRING_EQ(a->token, b->token); ++ else /* both should be null */ ++ ASSERT_PTR_EQ(a->token, b->token); ++ if (b->manuf != NULL) ++ ASSERT_STRING_EQ(a->manuf, b->manuf); ++ else /* both should be null */ ++ ASSERT_PTR_EQ(a->manuf, b->manuf); ++ if (b->lib_manuf != NULL) ++ ASSERT_STRING_EQ(a->lib_manuf, b->lib_manuf); ++ else /* both should be null */ ++ ASSERT_PTR_EQ(a->lib_manuf, b->lib_manuf); +} + -+static void -+snprintf_fill(char *str, size_t size, char fillchar, const char *fmt, ...) ++void ++check_parse_rv(char *uri, struct pkcs11_uri *expect, int expect_rv) +{ -+ int len; -+ va_list ap; -+ len = vsnprintf(str, size, fmt, ap); -+ va_end(ap); -+ if (len < 0 || len > (int) size) -+ return; -+ while(len < (int) size) -+ str[len++] = fillchar; -+} -+ -+#ifndef TEST_APP -+#define printf error_use_st_logf -+#endif -+ -+#define VERIFY_SESSION_HANDLE(s, state) \ -+{ \ -+ CK_RV ret; \ -+ ret = verify_session_handle(s, state); \ -+ if (ret != CKR_OK) { \ -+ /* return CKR_OK */; \ -+ } \ -+} ++ char *buf = NULL, *str; ++ struct pkcs11_uri *pkcs11uri = NULL; ++ int rv; + -+static CK_RV -+verify_session_handle(CK_SESSION_HANDLE hSession, -+ struct session_state **state) -+{ -+ size_t i; -+ -+ for (i = 0; i < MAX_NUM_SESSION; i++){ -+ if (soft_token.state[i].session_handle == hSession) -+ break; -+ } -+ if (i == MAX_NUM_SESSION) { -+ application_error("use of invalid handle: 0x%08lx\n", -+ (unsigned long)hSession); -+ return CKR_SESSION_HANDLE_INVALID; -+ } -+ if (state) -+ *state = &soft_token.state[i]; -+ return CKR_OK; ++ if (expect_rv == 0) ++ str = "Valid"; ++ else ++ str = "Invalid"; ++ asprintf(&buf, "%s PKCS#11 URI parsing: %s", str, uri); ++ TEST_START(buf); ++ free(buf); ++ pkcs11uri = pkcs11_uri_init(); ++ rv = pkcs11_uri_parse(uri, pkcs11uri); ++ ASSERT_INT_EQ(rv, expect_rv); ++ if (rv == 0) /* in case of failure result is undefined */ ++ compare_uri(pkcs11uri, expect); ++ pkcs11_uri_cleanup(pkcs11uri); ++ free(expect); ++ TEST_DONE(); +} + -+static CK_RV -+object_handle_to_object(CK_OBJECT_HANDLE handle, -+ struct st_object **object) ++void ++check_parse(char *uri, struct pkcs11_uri *expect) +{ -+ int i = HANDLE_OBJECT_ID(handle); -+ -+ *object = NULL; -+ if (i >= soft_token.object.num_objs) -+ return CKR_ARGUMENTS_BAD; -+ if (soft_token.object.objs[i] == NULL) -+ return CKR_ARGUMENTS_BAD; -+ if (soft_token.object.objs[i]->object_handle != handle) -+ return CKR_ARGUMENTS_BAD; -+ *object = soft_token.object.objs[i]; -+ return CKR_OK; ++ check_parse_rv(uri, expect, 0); +} + -+static int -+attributes_match(const struct st_object *obj, -+ const CK_ATTRIBUTE *attributes, -+ CK_ULONG num_attributes) ++struct pkcs11_uri * ++compose_uri(unsigned char *id, size_t id_len, char *token, char *lib_manuf, ++ char *manuf, char *module_path, char *object, char *pin) +{ -+ CK_ULONG i; -+ int j; -+ st_logf("attributes_match: %ld\n", (unsigned long)OBJECT_ID(obj)); -+ -+ for (i = 0; i < num_attributes; i++) { -+ int match = 0; -+ for (j = 0; j < obj->num_attributes; j++) { -+ if (attributes[i].type == obj->attrs[j].attribute.type && -+ attributes[i].ulValueLen == obj->attrs[j].attribute.ulValueLen && -+ memcmp(attributes[i].pValue, obj->attrs[j].attribute.pValue, -+ attributes[i].ulValueLen) == 0) { -+ match = 1; -+ break; -+ } -+ } -+ if (match == 0) { -+ st_logf("type %d attribute have no match\n", attributes[i].type); -+ return 0; ++ struct pkcs11_uri *uri = pkcs11_uri_init(); ++ if (id_len > 0) { ++ uri->id_len = id_len; ++ uri->id = id; + } -+ } -+ st_logf("attribute matches\n"); -+ return 1; ++ uri->module_path = module_path; ++ uri->token = token; ++ uri->lib_manuf = lib_manuf; ++ uri->manuf = manuf; ++ uri->object = object; ++ uri->pin = pin; ++ return uri; +} + +static void -+print_attributes(const CK_ATTRIBUTE *attributes, -+ CK_ULONG num_attributes) ++test_parse_valid(void) +{ -+ CK_ULONG i; -+ -+ st_logf("find objects: attrs: %lu\n", (unsigned long)num_attributes); -+ -+ for (i = 0; i < num_attributes; i++) { -+ st_logf(" type: "); -+ switch (attributes[i].type) { -+ case CKA_TOKEN: { -+ CK_BBOOL *ck_true; -+ if (attributes[i].ulValueLen != sizeof(CK_BBOOL)) { -+ application_error("token attribute wrong length\n"); -+ break; -+ } -+ ck_true = attributes[i].pValue; -+ st_logf("token: %s", *ck_true ? "TRUE" : "FALSE"); -+ break; -+ } -+ case CKA_CLASS: { -+ CK_OBJECT_CLASS *class; -+ if (attributes[i].ulValueLen != sizeof(CK_ULONG)) { -+ application_error("class attribute wrong length\n"); -+ break; -+ } -+ class = attributes[i].pValue; -+ st_logf("class "); -+ switch (*class) { -+ case CKO_CERTIFICATE: -+ st_logf("certificate"); -+ break; -+ case CKO_PUBLIC_KEY: -+ st_logf("public key"); -+ break; -+ case CKO_PRIVATE_KEY: -+ st_logf("private key"); -+ break; -+ case CKO_SECRET_KEY: -+ st_logf("secret key"); -+ break; -+ case CKO_DOMAIN_PARAMETERS: -+ st_logf("domain parameters"); -+ break; -+ default: -+ st_logf("[class %lx]", (long unsigned)*class); -+ break; -+ } -+ break; -+ } -+ case CKA_PRIVATE: -+ st_logf("private"); -+ break; -+ case CKA_LABEL: -+ st_logf("label"); -+ break; -+ case CKA_APPLICATION: -+ st_logf("application"); -+ break; -+ case CKA_VALUE: -+ st_logf("value"); -+ break; -+ case CKA_ID: -+ st_logf("id"); -+ break; -+ default: -+ st_logf("[unknown 0x%08lx]", (unsigned long)attributes[i].type); -+ break; -+ } -+ st_logf("\n"); -+ } -+} ++ /* path arguments */ ++ check_parse("pkcs11:id=%01", ++ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL)); ++ check_parse("pkcs11:id=%00%01", ++ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL)); ++ check_parse("pkcs11:token=SSH%20Keys", ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ check_parse("pkcs11:library-manufacturer=OpenSC", ++ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL)); ++ check_parse("pkcs11:manufacturer=piv_II", ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL)); ++ check_parse("pkcs11:object=SIGN%20Key", ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "SIGN Key", NULL)); ++ /* query arguments */ ++ check_parse("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so", ++ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ check_parse("pkcs11:?pin-value=123456", ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL, "123456")); + -+static struct st_object * -+add_st_object(void) -+{ -+ struct st_object *o, **objs; -+ int i; ++ /* combinations */ ++ /* ID SHOULD be percent encoded */ ++ check_parse("pkcs11:token=SSH%20Key;id=0", ++ compose_uri("0", 1, "SSH Key", NULL, NULL, NULL, NULL, NULL)); ++ check_parse( ++ "pkcs11:manufacturer=CAC?module-path=/usr/lib64/p11-kit-proxy.so", ++ compose_uri(NULL, 0, NULL, NULL, "CAC", ++ "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ check_parse( ++ "pkcs11:object=RSA%20Key?module-path=/usr/lib64/pkcs11/opencryptoki.so", ++ compose_uri(NULL, 0, NULL, NULL, NULL, ++ "/usr/lib64/pkcs11/opencryptoki.so", "RSA Key", NULL)); ++ check_parse("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so&pin-value=123456", ++ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, "123456")); + -+ o = malloc(sizeof(*o)); -+ if (o == NULL) -+ return NULL; -+ memset(o, 0, sizeof(*o)); -+ o->attrs = NULL; -+ o->num_attributes = 0; -+ -+ for (i = 0; i < soft_token.object.num_objs; i++) { -+ if (soft_token.object.objs == NULL) { -+ soft_token.object.objs[i] = o; -+ break; -+ } -+ } -+ if (i == soft_token.object.num_objs) { -+ objs = realloc(soft_token.object.objs, -+ (soft_token.object.num_objs + 1) * sizeof(soft_token.object.objs[0])); -+ if (objs == NULL) { -+ free(o); -+ return NULL; -+ } -+ soft_token.object.objs = objs; -+ soft_token.object.objs[soft_token.object.num_objs++] = o; -+ } -+ soft_token.object.objs[i]->object_handle = -+ (random() & (~OBJECT_ID_MASK)) | i; ++ /* empty path component matches everything */ ++ check_parse("pkcs11:", EMPTY_URI); + -+ return o; ++ /* empty string is a valid to match against (and different from NULL) */ ++ check_parse("pkcs11:token=", ++ compose_uri(NULL, 0, "", NULL, NULL, NULL, NULL, NULL)); ++ /* Percent character needs to be percent-encoded */ ++ check_parse("pkcs11:token=%25", ++ compose_uri(NULL, 0, "%", NULL, NULL, NULL, NULL, NULL)); +} + -+static CK_RV -+add_object_attribute(struct st_object *o, -+ int secret, -+ CK_ATTRIBUTE_TYPE type, -+ CK_VOID_PTR pValue, -+ CK_ULONG ulValueLen) ++static void ++test_parse_invalid(void) +{ -+ struct st_attr *a; -+ int i; -+ -+ i = o->num_attributes; -+ a = realloc(o->attrs, (i + 1) * sizeof(o->attrs[0])); -+ if (a == NULL) -+ return CKR_DEVICE_MEMORY; -+ o->attrs = a; -+ o->attrs[i].secret = secret; -+ o->attrs[i].attribute.type = type; -+ o->attrs[i].attribute.pValue = malloc(ulValueLen); -+ if (o->attrs[i].attribute.pValue == NULL && ulValueLen != 0) -+ return CKR_DEVICE_MEMORY; -+ memcpy(o->attrs[i].attribute.pValue, pValue, ulValueLen); -+ o->attrs[i].attribute.ulValueLen = ulValueLen; -+ o->num_attributes++; -+ -+ return CKR_OK; ++ /* Invalid percent encoding */ ++ check_parse_rv("pkcs11:id=%0", EMPTY_URI, -1); ++ /* Invalid percent encoding */ ++ check_parse_rv("pkcs11:id=%ZZ", EMPTY_URI, -1); ++ /* Space MUST be percent encoded -- XXX not enforced yet */ ++ check_parse("pkcs11:token=SSH Keys", ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ /* MUST NOT contain duplicate attributes of the same name */ ++ check_parse_rv("pkcs11:id=%01;id=%02", EMPTY_URI, -1); ++ /* MUST NOT contain duplicate attributes of the same name */ ++ check_parse_rv("pkcs11:?pin-value=111111&pin-value=123456", EMPTY_URI, -1); ++ /* Unrecognized attribute in path are ignored with log message */ ++ check_parse("pkcs11:key_name=SSH", EMPTY_URI); ++ /* Unrecognized attribute in query SHOULD be ignored */ ++ check_parse("pkcs11:?key_name=SSH", EMPTY_URI); +} + -+static CK_RV -+add_pubkey_info(struct st_object *o, CK_KEY_TYPE key_type, EVP_PKEY *key) ++void ++check_gen(char *expect, struct pkcs11_uri *uri) +{ -+ switch (key_type) { -+ case CKK_RSA: { -+ CK_BYTE *modulus = NULL; -+ size_t modulus_len = 0; -+ CK_ULONG modulus_bits = 0; -+ CK_BYTE *exponent = NULL; -+ size_t exponent_len = 0; -+ RSA* rsa = NULL; -+ const BIGNUM *n = NULL, *e = NULL; -+ -+ rsa = EVP_PKEY_get0_RSA(key); -+ RSA_get0_key(rsa, &n, &e, NULL); -+ -+ modulus_bits = BN_num_bits(n); -+ -+ modulus_len = BN_num_bytes(n); -+ modulus = malloc(modulus_len); -+ BN_bn2bin(n, modulus); -+ -+ exponent_len = BN_num_bytes(e); -+ exponent = malloc(exponent_len); -+ BN_bn2bin(e, exponent); -+ -+ add_object_attribute(o, 0, CKA_MODULUS, modulus, modulus_len); -+ add_object_attribute(o, 0, CKA_MODULUS_BITS, -+ &modulus_bits, sizeof(modulus_bits)); -+ add_object_attribute(o, 0, CKA_PUBLIC_EXPONENT, -+ exponent, exponent_len); -+ -+ RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); -+ -+ free(modulus); -+ free(exponent); -+ } -+ default: -+ /* XXX */ -+ break; -+ } -+ return CKR_OK; -+} -+ ++ char *buf = NULL, *uri_str; + -+static int -+pem_callback(char *buf, int num, int w, void *key) -+{ -+ return -1; ++ asprintf(&buf, "Valid PKCS#11 URI generation: %s", expect); ++ TEST_START(buf); ++ free(buf); ++ uri_str = pkcs11_uri_get(uri); ++ ASSERT_PTR_NE(uri_str, NULL); ++ ASSERT_STRING_EQ(uri_str, expect); ++ free(uri_str); ++ TEST_DONE(); +} + -+ -+static CK_RV -+add_certificate(char *label, -+ const char *cert_file, -+ const char *private_key_file, -+ char *id, -+ int anchor) ++static void ++test_generate_valid(void) +{ -+ struct st_object *o = NULL; -+ CK_BBOOL bool_true = CK_TRUE; -+ CK_BBOOL bool_false = CK_FALSE; -+ CK_OBJECT_CLASS c; -+ CK_CERTIFICATE_TYPE cert_type = CKC_X_509; -+ CK_KEY_TYPE key_type; -+ CK_MECHANISM_TYPE mech_type; -+ void *cert_data = NULL; -+ size_t cert_length; -+ void *subject_data = NULL; -+ size_t subject_length; -+ void *issuer_data = NULL; -+ size_t issuer_length; -+ void *serial_data = NULL; -+ size_t serial_length; -+ CK_RV ret = CKR_GENERAL_ERROR; -+ X509 *cert; -+ EVP_PKEY *public_key; -+ -+ size_t id_len = strlen(id); -+ -+ { -+ FILE *f; -+ -+ f = fopen(cert_file, "r"); -+ if (f == NULL) { -+ st_logf("failed to open file %s\n", cert_file); -+ return CKR_GENERAL_ERROR; -+ } ++ /* path arguments */ ++ check_gen("pkcs11:id=%01", ++ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL, NULL)); ++ check_gen("pkcs11:id=%00%01", ++ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL, NULL)); ++ check_gen("pkcs11:token=SSH%20Keys", /* space must be percent encoded */ ++ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ /* library-manufacturer is not implmented now */ ++ /*check_gen("pkcs11:library-manufacturer=OpenSC", ++ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL, NULL));*/ ++ check_gen("pkcs11:manufacturer=piv_II", ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL, NULL)); ++ check_gen("pkcs11:object=RSA%20Key", ++ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "RSA Key", NULL)); ++ /* query arguments */ ++ check_gen("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so", ++ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); + -+ cert = PEM_read_X509(f, NULL, NULL, NULL); -+ fclose(f); -+ if (cert == NULL) { -+ st_logf("failed reading PEM cert\n"); -+ return CKR_GENERAL_ERROR; -+ } -+ -+ OPENSSL_ASN1_MALLOC_ENCODE(X509, cert_data, cert_length, cert, ret); -+ if (ret) -+ goto out; -+ -+ OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, issuer_data, issuer_length, -+ X509_get_issuer_name(cert), ret); -+ if (ret) -+ goto out; -+ -+ OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, subject_data, subject_length, -+ X509_get_subject_name(cert), ret); -+ if (ret) -+ goto out; -+ -+ OPENSSL_ASN1_MALLOC_ENCODE(ASN1_INTEGER, serial_data, serial_length, -+ X509_get_serialNumber(cert), ret); -+ if (ret) -+ goto out; -+ -+ } -+ -+ st_logf("done parsing, adding to internal structure\n"); -+ -+ o = add_st_object(); -+ if (o == NULL) { -+ ret = CKR_DEVICE_MEMORY; -+ goto out; -+ } -+ o->type = STO_T_CERTIFICATE; -+ o->u.cert = cert; -+ public_key = X509_get_pubkey(o->u.cert); -+ -+ switch (EVP_PKEY_base_id(public_key)) { -+ case EVP_PKEY_RSA: -+ key_type = CKK_RSA; -+ break; -+ case EVP_PKEY_DSA: -+ key_type = CKK_DSA; -+ break; -+ default: -+ /* XXX */ -+ break; -+ } -+ -+ c = CKO_CERTIFICATE; -+ add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); -+ add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); -+ -+ add_object_attribute(o, 0, CKA_CERTIFICATE_TYPE, &cert_type, sizeof(cert_type)); -+ add_object_attribute(o, 0, CKA_ID, id, id_len); -+ -+ add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); -+ add_object_attribute(o, 0, CKA_ISSUER, issuer_data, issuer_length); -+ add_object_attribute(o, 0, CKA_SERIAL_NUMBER, serial_data, serial_length); -+ add_object_attribute(o, 0, CKA_VALUE, cert_data, cert_length); -+ if (anchor) -+ add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true)); -+ else -+ add_object_attribute(o, 0, CKA_TRUSTED, &bool_false, sizeof(bool_false)); -+ -+ st_logf("add cert ok: %lx\n", (unsigned long)OBJECT_ID(o)); -+ -+ o = add_st_object(); -+ if (o == NULL) { -+ ret = CKR_DEVICE_MEMORY; -+ goto out; -+ } -+ o->type = STO_T_PUBLIC_KEY; -+ o->u.public_key = public_key; -+ -+ c = CKO_PUBLIC_KEY; -+ add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); -+ add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_PRIVATE, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); -+ -+ add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type)); -+ add_object_attribute(o, 0, CKA_ID, id, id_len); -+ add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */ -+ add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */ -+ add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false)); -+ mech_type = CKM_RSA_X_509; -+ add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type)); -+ -+ add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); -+ add_object_attribute(o, 0, CKA_ENCRYPT, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_VERIFY, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_VERIFY_RECOVER, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_WRAP, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_TRUSTED, &bool_true, sizeof(bool_true)); -+ -+ add_pubkey_info(o, key_type, public_key); -+ -+ st_logf("add key ok: %lx\n", (unsigned long)OBJECT_ID(o)); -+ -+ if (private_key_file) { -+ CK_FLAGS flags; -+ FILE *f; -+ -+ o = add_st_object(); -+ if (o == NULL) { -+ ret = CKR_DEVICE_MEMORY; -+ goto out; -+ } -+ o->type = STO_T_PRIVATE_KEY; -+ o->u.private_key.file = strdup(private_key_file); -+ o->u.private_key.key = NULL; -+ -+ o->u.private_key.cert = cert; -+ -+ c = CKO_PRIVATE_KEY; -+ add_object_attribute(o, 0, CKA_CLASS, &c, sizeof(c)); -+ add_object_attribute(o, 0, CKA_TOKEN, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_PRIVATE, &bool_true, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_MODIFIABLE, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_LABEL, label, strlen(label)); -+ -+ add_object_attribute(o, 0, CKA_KEY_TYPE, &key_type, sizeof(key_type)); -+ add_object_attribute(o, 0, CKA_ID, id, id_len); -+ add_object_attribute(o, 0, CKA_START_DATE, "", 1); /* XXX */ -+ add_object_attribute(o, 0, CKA_END_DATE, "", 1); /* XXX */ -+ add_object_attribute(o, 0, CKA_DERIVE, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_LOCAL, &bool_false, sizeof(bool_false)); -+ mech_type = CKM_RSA_X_509; -+ add_object_attribute(o, 0, CKA_KEY_GEN_MECHANISM, &mech_type, sizeof(mech_type)); -+ -+ add_object_attribute(o, 0, CKA_SUBJECT, subject_data, subject_length); -+ add_object_attribute(o, 0, CKA_SENSITIVE, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_SECONDARY_AUTH, &bool_false, sizeof(bool_true)); -+ flags = 0; -+ add_object_attribute(o, 0, CKA_AUTH_PIN_FLAGS, &flags, sizeof(flags)); -+ -+ add_object_attribute(o, 0, CKA_DECRYPT, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_SIGN, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_SIGN_RECOVER, &bool_false, sizeof(bool_false)); -+ add_object_attribute(o, 0, CKA_UNWRAP, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_EXTRACTABLE, &bool_true, sizeof(bool_true)); -+ add_object_attribute(o, 0, CKA_NEVER_EXTRACTABLE, &bool_false, sizeof(bool_false)); -+ -+ add_pubkey_info(o, key_type, public_key); -+ -+ f = fopen(private_key_file, "r"); -+ if (f == NULL) { -+ st_logf("failed to open private key\n"); -+ return CKR_GENERAL_ERROR; -+ } -+ -+ o->u.private_key.key = PEM_read_PrivateKey(f, NULL, pem_callback, NULL); -+ fclose(f); -+ if (o->u.private_key.key == NULL) { -+ st_logf("failed to read private key a startup\n"); -+ /* don't bother with this failure for now, -+ fix it at C_Login time */; -+ } else { -+ /* XXX verify keytype */ -+ -+ if (key_type == CKK_RSA) { -+ RSA *rsa = EVP_PKEY_get0_RSA(o->u.private_key.key); -+ RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); -+ } -+ -+ if (X509_check_private_key(cert, o->u.private_key.key) != 1) { -+ EVP_PKEY_free(o->u.private_key.key); -+ o->u.private_key.key = NULL; -+ st_logf("private key doesn't verify\n"); -+ } else { -+ st_logf("private key usable\n"); -+ soft_token.flags.login_done = 1; -+ } -+ } -+ } -+ -+ ret = CKR_OK; -+ out: -+ if (ret != CKR_OK) { -+ st_logf("something went wrong when adding cert!\n"); -+ -+ /* XXX wack o */; -+ } -+ free(cert_data); -+ free(serial_data); -+ free(issuer_data); -+ free(subject_data); -+ -+ return ret; -+} -+ -+static void -+find_object_final(struct session_state *state) -+{ -+ if (state->find.attributes) { -+ CK_ULONG i; -+ -+ for (i = 0; i < state->find.num_attributes; i++) { -+ if (state->find.attributes[i].pValue) -+ free(state->find.attributes[i].pValue); -+ } -+ free(state->find.attributes); -+ state->find.attributes = NULL; -+ state->find.num_attributes = 0; -+ state->find.next_object = -1; -+ } -+} -+ -+static void -+reset_crypto_state(struct session_state *state) -+{ -+ state->encrypt_object = -1; -+ if (state->encrypt_mechanism) -+ free(state->encrypt_mechanism); -+ state->encrypt_mechanism = NULL_PTR; -+ state->decrypt_object = -1; -+ if (state->decrypt_mechanism) -+ free(state->decrypt_mechanism); -+ state->decrypt_mechanism = NULL_PTR; -+ state->sign_object = -1; -+ if (state->sign_mechanism) -+ free(state->sign_mechanism); -+ state->sign_mechanism = NULL_PTR; -+ state->verify_object = -1; -+ if (state->verify_mechanism) -+ free(state->verify_mechanism); -+ state->verify_mechanism = NULL_PTR; -+ state->digest_object = -1; -+} -+ -+static void -+close_session(struct session_state *state) -+{ -+ if (state->find.attributes) { -+ application_error("application didn't do C_FindObjectsFinal\n"); -+ find_object_final(state); -+ } -+ -+ state->session_handle = CK_INVALID_HANDLE; -+ soft_token.application = NULL_PTR; -+ soft_token.notify = NULL_PTR; -+ reset_crypto_state(state); -+} -+ -+static const char * -+has_session(void) -+{ -+ return soft_token.open_sessions > 0 ? "yes" : "no"; -+} -+ -+static void -+read_conf_file(const char *fn) -+{ -+ char buf[1024], *cert, *key, *id, *label, *s, *p; -+ int anchor; -+ FILE *f; -+ -+ f = fopen(fn, "r"); -+ if (f == NULL) { -+ st_logf("can't open configuration file %s\n", fn); -+ return; -+ } -+ -+ while(fgets(buf, sizeof(buf), f) != NULL) { -+ buf[strcspn(buf, "\n")] = '\0'; -+ -+ anchor = 0; -+ -+ st_logf("line: %s\n", buf); -+ -+ p = buf; -+ while (isspace(*p)) -+ p++; -+ if (*p == '#') -+ continue; -+ while (isspace(*p)) -+ p++; -+ -+ s = NULL; -+ id = strtok_r(p, "\t", &s); -+ if (id == NULL) -+ continue; -+ label = strtok_r(NULL, "\t", &s); -+ if (label == NULL) -+ continue; -+ cert = strtok_r(NULL, "\t", &s); -+ if (cert == NULL) -+ continue; -+ key = strtok_r(NULL, "\t", &s); -+ -+ /* XXX */ -+ if (strcmp(id, "anchor") == 0) { -+ id = "\x00\x00"; -+ anchor = 1; -+ } -+ -+ st_logf("adding: %s\n", label); -+ -+ add_certificate(label, cert, key, id, anchor); -+ } -+} -+ -+static CK_RV -+func_not_supported(void) -+{ -+ st_logf("function not supported\n"); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_Initialize(CK_VOID_PTR a) -+{ -+ CK_C_INITIALIZE_ARGS_PTR args = a; -+ st_logf("Initialize\n"); -+ size_t i; -+ -+ OpenSSL_add_all_algorithms(); -+ ERR_load_crypto_strings(); -+ -+ srandom(getpid() ^ time(NULL)); -+ -+ for (i = 0; i < MAX_NUM_SESSION; i++) { -+ soft_token.state[i].session_handle = CK_INVALID_HANDLE; -+ soft_token.state[i].find.attributes = NULL; -+ soft_token.state[i].find.num_attributes = 0; -+ soft_token.state[i].find.next_object = -1; -+ reset_crypto_state(&soft_token.state[i]); -+ } -+ -+ soft_token.flags.hardware_slot = 1; -+ soft_token.flags.app_error_fatal = 0; -+ soft_token.flags.login_done = 0; -+ -+ soft_token.object.objs = NULL; -+ soft_token.object.num_objs = 0; -+ -+ soft_token.logfile = NULL; -+#if 1 -+// soft_token.logfile = stdout; -+#endif -+#if 0 -+ soft_token.logfile = fopen("/tmp/log-pkcs11.txt", "a"); -+#endif -+ -+ if (a != NULL_PTR) { -+ st_logf("\tCreateMutex:\t%p\n", args->CreateMutex); -+ st_logf("\tDestroyMutext\t%p\n", args->DestroyMutex); -+ st_logf("\tLockMutext\t%p\n", args->LockMutex); -+ st_logf("\tUnlockMutext\t%p\n", args->UnlockMutex); -+ st_logf("\tFlags\t%04x\n", (unsigned int)args->flags); -+ } -+ -+ { -+ char *fn = NULL, *home = NULL; -+ -+ if (getuid() == geteuid()) { -+ fn = getenv("SOFTPKCS11RC"); -+ if (fn) -+ fn = strdup(fn); -+ home = getenv("HOME"); -+ } -+ if (fn == NULL && home == NULL) { -+ struct passwd *pw = getpwuid(getuid()); -+ if(pw != NULL) -+ home = pw->pw_dir; -+ } -+ if (fn == NULL) { -+ if (home) -+ asprintf(&fn, "%s/.soft-token.rc", home); -+ else -+ fn = strdup("/etc/soft-token.rc"); -+ } -+ -+ read_conf_file(fn); -+ free(fn); -+ } -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_Finalize(CK_VOID_PTR args) -+{ -+ size_t i; -+ -+ st_logf("Finalize\n"); -+ -+ for (i = 0; i < MAX_NUM_SESSION; i++) { -+ if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) { -+ application_error("application finalized without " -+ "closing session\n"); -+ close_session(&soft_token.state[i]); -+ } -+ } -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_GetInfo(CK_INFO_PTR args) -+{ -+ st_logf("GetInfo\n"); -+ -+ memset(args, 17, sizeof(*args)); -+ args->cryptokiVersion.major = 2; -+ args->cryptokiVersion.minor = 10; -+ snprintf_fill((char *)args->manufacturerID, -+ sizeof(args->manufacturerID), -+ ' ', -+ "SoftToken"); -+ snprintf_fill((char *)args->libraryDescription, -+ sizeof(args->libraryDescription), ' ', -+ "SoftToken"); -+ args->libraryVersion.major = 1; -+ args->libraryVersion.minor = 8; -+ -+ return CKR_OK; -+} -+ -+extern CK_FUNCTION_LIST funcs; -+ -+CK_RV -+C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) -+{ -+ *ppFunctionList = &funcs; -+ return CKR_OK; -+} -+ -+CK_RV -+C_GetSlotList(CK_BBOOL tokenPresent, -+ CK_SLOT_ID_PTR pSlotList, -+ CK_ULONG_PTR pulCount) -+{ -+ st_logf("GetSlotList: %s\n", -+ tokenPresent ? "tokenPresent" : "token not Present"); -+ if (pSlotList) -+ pSlotList[0] = 1; -+ *pulCount = 1; -+ return CKR_OK; -+} -+ -+CK_RV -+C_GetSlotInfo(CK_SLOT_ID slotID, -+ CK_SLOT_INFO_PTR pInfo) -+{ -+ st_logf("GetSlotInfo: slot: %d : %s\n", (int)slotID, has_session()); -+ -+ memset(pInfo, 18, sizeof(*pInfo)); -+ -+ if (slotID != 1) -+ return CKR_ARGUMENTS_BAD; -+ -+ snprintf_fill((char *)pInfo->slotDescription, -+ sizeof(pInfo->slotDescription), -+ ' ', -+ "SoftToken (slot)"); -+ snprintf_fill((char *)pInfo->manufacturerID, -+ sizeof(pInfo->manufacturerID), -+ ' ', -+ "SoftToken (slot)"); -+ pInfo->flags = CKF_TOKEN_PRESENT; -+ if (soft_token.flags.hardware_slot) -+ pInfo->flags |= CKF_HW_SLOT; -+ pInfo->hardwareVersion.major = 1; -+ pInfo->hardwareVersion.minor = 0; -+ pInfo->firmwareVersion.major = 1; -+ pInfo->firmwareVersion.minor = 0; -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_GetTokenInfo(CK_SLOT_ID slotID, -+ CK_TOKEN_INFO_PTR pInfo) -+{ -+ st_logf("GetTokenInfo: %s\n", has_session()); -+ -+ memset(pInfo, 19, sizeof(*pInfo)); -+ -+ snprintf_fill((char *)pInfo->label, -+ sizeof(pInfo->label), -+ ' ', -+ "SoftToken (token)"); -+ snprintf_fill((char *)pInfo->manufacturerID, -+ sizeof(pInfo->manufacturerID), -+ ' ', -+ "SoftToken (token)"); -+ snprintf_fill((char *)pInfo->model, -+ sizeof(pInfo->model), -+ ' ', -+ "SoftToken (token)"); -+ snprintf_fill((char *)pInfo->serialNumber, -+ sizeof(pInfo->serialNumber), -+ ' ', -+ "4711"); -+ pInfo->flags = -+ CKF_TOKEN_INITIALIZED | -+ CKF_USER_PIN_INITIALIZED; -+ -+ if (soft_token.flags.login_done == 0) -+ pInfo->flags |= CKF_LOGIN_REQUIRED; -+ -+ /* CFK_RNG | -+ CKF_RESTORE_KEY_NOT_NEEDED | -+ */ -+ pInfo->ulMaxSessionCount = MAX_NUM_SESSION; -+ pInfo->ulSessionCount = soft_token.open_sessions; -+ pInfo->ulMaxRwSessionCount = MAX_NUM_SESSION; -+ pInfo->ulRwSessionCount = soft_token.open_sessions; -+ pInfo->ulMaxPinLen = 1024; -+ pInfo->ulMinPinLen = 0; -+ pInfo->ulTotalPublicMemory = 4711; -+ pInfo->ulFreePublicMemory = 4712; -+ pInfo->ulTotalPrivateMemory = 4713; -+ pInfo->ulFreePrivateMemory = 4714; -+ pInfo->hardwareVersion.major = 2; -+ pInfo->hardwareVersion.minor = 0; -+ pInfo->firmwareVersion.major = 2; -+ pInfo->firmwareVersion.minor = 0; -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_GetMechanismList(CK_SLOT_ID slotID, -+ CK_MECHANISM_TYPE_PTR pMechanismList, -+ CK_ULONG_PTR pulCount) -+{ -+ st_logf("GetMechanismList\n"); -+ -+ *pulCount = 2; -+ if (pMechanismList == NULL_PTR) -+ return CKR_OK; -+ pMechanismList[0] = CKM_RSA_X_509; -+ pMechanismList[1] = CKM_RSA_PKCS; -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_GetMechanismInfo(CK_SLOT_ID slotID, -+ CK_MECHANISM_TYPE type, -+ CK_MECHANISM_INFO_PTR pInfo) -+{ -+ st_logf("GetMechanismInfo: slot %d type: %d\n", -+ (int)slotID, (int)type); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_InitToken(CK_SLOT_ID slotID, -+ CK_UTF8CHAR_PTR pPin, -+ CK_ULONG ulPinLen, -+ CK_UTF8CHAR_PTR pLabel) -+{ -+ st_logf("InitToken: slot %d\n", (int)slotID); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_OpenSession(CK_SLOT_ID slotID, -+ CK_FLAGS flags, -+ CK_VOID_PTR pApplication, -+ CK_NOTIFY Notify, -+ CK_SESSION_HANDLE_PTR phSession) -+{ -+ size_t i; -+ -+ st_logf("OpenSession: slot: %d\n", (int)slotID); -+ -+ if (soft_token.open_sessions == MAX_NUM_SESSION) -+ return CKR_SESSION_COUNT; -+ -+ soft_token.application = pApplication; -+ soft_token.notify = Notify; -+ -+ for (i = 0; i < MAX_NUM_SESSION; i++) -+ if (soft_token.state[i].session_handle == CK_INVALID_HANDLE) -+ break; -+ if (i == MAX_NUM_SESSION) -+ abort(); -+ -+ soft_token.open_sessions++; -+ -+ soft_token.state[i].session_handle = -+ (CK_SESSION_HANDLE)(random() & 0xfffff); -+ *phSession = soft_token.state[i].session_handle; -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_CloseSession(CK_SESSION_HANDLE hSession) -+{ -+ struct session_state *state; -+ st_logf("CloseSession\n"); -+ -+ if (verify_session_handle(hSession, &state) != CKR_OK) -+ application_error("closed session not open"); -+ else -+ close_session(state); -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_CloseAllSessions(CK_SLOT_ID slotID) -+{ -+ size_t i; -+ -+ st_logf("CloseAllSessions\n"); -+ -+ for (i = 0; i < MAX_NUM_SESSION; i++) -+ if (soft_token.state[i].session_handle != CK_INVALID_HANDLE) -+ close_session(&soft_token.state[i]); -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_GetSessionInfo(CK_SESSION_HANDLE hSession, -+ CK_SESSION_INFO_PTR pInfo) -+{ -+ st_logf("GetSessionInfo\n"); -+ -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ -+ memset(pInfo, 20, sizeof(*pInfo)); -+ -+ pInfo->slotID = 1; -+ if (soft_token.flags.login_done) -+ pInfo->state = CKS_RO_USER_FUNCTIONS; -+ else -+ pInfo->state = CKS_RO_PUBLIC_SESSION; -+ pInfo->flags = CKF_SERIAL_SESSION; -+ pInfo->ulDeviceError = 0; -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_Login(CK_SESSION_HANDLE hSession, -+ CK_USER_TYPE userType, -+ CK_UTF8CHAR_PTR pPin, -+ CK_ULONG ulPinLen) -+{ -+ char *pin = NULL; -+ int i; -+ -+ st_logf("Login\n"); -+ -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ -+ if (pPin != NULL_PTR) { -+ asprintf(&pin, "%.*s", (int)ulPinLen, pPin); -+ st_logf("type: %d password: %s\n", (int)userType, pin); -+ } -+ -+ for (i = 0; i < soft_token.object.num_objs; i++) { -+ struct st_object *o = soft_token.object.objs[i]; -+ FILE *f; -+ -+ if (o->type != STO_T_PRIVATE_KEY) -+ continue; -+ -+ if (o->u.private_key.key) -+ continue; -+ -+ f = fopen(o->u.private_key.file, "r"); -+ if (f == NULL) { -+ st_logf("can't open private file: %s\n", o->u.private_key.file); -+ continue; -+ } -+ -+ o->u.private_key.key = PEM_read_PrivateKey(f, NULL, NULL, pin); -+ fclose(f); -+ if (o->u.private_key.key == NULL) { -+ st_logf("failed to read key: %s error: %s\n", -+ o->u.private_key.file, -+ ERR_error_string(ERR_get_error(), NULL)); -+ /* just ignore failure */; -+ continue; -+ } -+ -+ /* XXX check keytype */ -+ RSA *rsa = EVP_PKEY_get0_RSA(o->u.private_key.key); -+ RSA_set_method(rsa, RSA_PKCS1_OpenSSL()); -+ -+ if (X509_check_private_key(o->u.private_key.cert, o->u.private_key.key) != 1) { -+ EVP_PKEY_free(o->u.private_key.key); -+ o->u.private_key.key = NULL; -+ st_logf("private key %s doesn't verify\n", o->u.private_key.file); -+ continue; -+ } -+ -+ soft_token.flags.login_done = 1; -+ } -+ free(pin); -+ -+ return soft_token.flags.login_done ? CKR_OK : CKR_PIN_INCORRECT; -+} -+ -+CK_RV -+C_Logout(CK_SESSION_HANDLE hSession) -+{ -+ st_logf("Logout\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_GetObjectSize(CK_SESSION_HANDLE hSession, -+ CK_OBJECT_HANDLE hObject, -+ CK_ULONG_PTR pulSize) -+{ -+ st_logf("GetObjectSize\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_GetAttributeValue(CK_SESSION_HANDLE hSession, -+ CK_OBJECT_HANDLE hObject, -+ CK_ATTRIBUTE_PTR pTemplate, -+ CK_ULONG ulCount) -+{ -+ struct session_state *state; -+ struct st_object *obj; -+ CK_ULONG i; -+ CK_RV ret; -+ int j; -+ -+ st_logf("GetAttributeValue: %lx\n", -+ (unsigned long)HANDLE_OBJECT_ID(hObject)); -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ if ((ret = object_handle_to_object(hObject, &obj)) != CKR_OK) { -+ st_logf("object not found: %lx\n", -+ (unsigned long)HANDLE_OBJECT_ID(hObject)); -+ return ret; -+ } -+ -+ ret = CKR_OK; -+ for (i = 0; i < ulCount; i++) { -+ st_logf(" getting 0x%08lx\n", (unsigned long)pTemplate[i].type); -+ for (j = 0; j < obj->num_attributes; j++) { -+ if (obj->attrs[j].secret) { -+ pTemplate[i].ulValueLen = (CK_ULONG)-1; -+ break; -+ } -+ if (pTemplate[i].type == obj->attrs[j].attribute.type) { -+ if (pTemplate[i].pValue != NULL_PTR && obj->attrs[j].secret == 0) { -+ if (pTemplate[i].ulValueLen >= obj->attrs[j].attribute.ulValueLen) -+ memcpy(pTemplate[i].pValue, obj->attrs[j].attribute.pValue, -+ obj->attrs[j].attribute.ulValueLen); -+ } -+ pTemplate[i].ulValueLen = obj->attrs[j].attribute.ulValueLen; -+ break; -+ } -+ } -+ if (j == obj->num_attributes) { -+ st_logf("key type: 0x%08lx not found\n", (unsigned long)pTemplate[i].type); -+ pTemplate[i].ulValueLen = (CK_ULONG)-1; -+ ret = CKR_ATTRIBUTE_TYPE_INVALID; -+ } -+ -+ } -+ return ret; -+} -+ -+CK_RV -+C_FindObjectsInit(CK_SESSION_HANDLE hSession, -+ CK_ATTRIBUTE_PTR pTemplate, -+ CK_ULONG ulCount) -+{ -+ struct session_state *state; -+ -+ st_logf("FindObjectsInit\n"); -+ -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ if (state->find.next_object != -1) { -+ application_error("application didn't do C_FindObjectsFinal\n"); -+ find_object_final(state); -+ } -+ if (ulCount) { -+ CK_ULONG i; -+ -+ print_attributes(pTemplate, ulCount); -+ -+ state->find.attributes = -+ calloc(1, ulCount * sizeof(state->find.attributes[0])); -+ if (state->find.attributes == NULL) -+ return CKR_DEVICE_MEMORY; -+ for (i = 0; i < ulCount; i++) { -+ state->find.attributes[i].pValue = -+ malloc(pTemplate[i].ulValueLen); -+ if (state->find.attributes[i].pValue == NULL) { -+ find_object_final(state); -+ return CKR_DEVICE_MEMORY; -+ } -+ memcpy(state->find.attributes[i].pValue, -+ pTemplate[i].pValue, pTemplate[i].ulValueLen); -+ state->find.attributes[i].type = pTemplate[i].type; -+ state->find.attributes[i].ulValueLen = pTemplate[i].ulValueLen; -+ } -+ state->find.num_attributes = ulCount; -+ state->find.next_object = 0; -+ } else { -+ st_logf("find all objects\n"); -+ state->find.attributes = NULL; -+ state->find.num_attributes = 0; -+ state->find.next_object = 0; -+ } -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_FindObjects(CK_SESSION_HANDLE hSession, -+ CK_OBJECT_HANDLE_PTR phObject, -+ CK_ULONG ulMaxObjectCount, -+ CK_ULONG_PTR pulObjectCount) -+{ -+ struct session_state *state; -+ int i; -+ -+ st_logf("FindObjects\n"); -+ -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ if (state->find.next_object == -1) { -+ application_error("application didn't do C_FindObjectsInit\n"); -+ return CKR_ARGUMENTS_BAD; -+ } -+ if (ulMaxObjectCount == 0) { -+ application_error("application asked for 0 objects\n"); -+ return CKR_ARGUMENTS_BAD; -+ } -+ *pulObjectCount = 0; -+ for (i = state->find.next_object; i < soft_token.object.num_objs; i++) { -+ st_logf("FindObjects: %d\n", i); -+ state->find.next_object = i + 1; -+ if (attributes_match(soft_token.object.objs[i], -+ state->find.attributes, -+ state->find.num_attributes)) { -+ *phObject++ = soft_token.object.objs[i]->object_handle; -+ ulMaxObjectCount--; -+ (*pulObjectCount)++; -+ if (ulMaxObjectCount == 0) -+ break; -+ } -+ } -+ return CKR_OK; -+} -+ -+CK_RV -+C_FindObjectsFinal(CK_SESSION_HANDLE hSession) -+{ -+ struct session_state *state; -+ -+ st_logf("FindObjectsFinal\n"); -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ find_object_final(state); -+ return CKR_OK; -+} -+ -+static CK_RV -+commonInit(CK_ATTRIBUTE *attr_match, int attr_match_len, -+ const CK_MECHANISM_TYPE *mechs, int mechs_len, -+ const CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey, -+ struct st_object **o) -+{ -+ CK_RV ret; -+ int i; -+ -+ *o = NULL; -+ if ((ret = object_handle_to_object(hKey, o)) != CKR_OK) -+ return ret; -+ -+ ret = attributes_match(*o, attr_match, attr_match_len); -+ if (!ret) { -+ application_error("called commonInit on key that doesn't " -+ "support required attr"); -+ return CKR_ARGUMENTS_BAD; -+ } -+ -+ for (i = 0; i < mechs_len; i++) -+ if (mechs[i] == pMechanism->mechanism) -+ break; -+ if (i == mechs_len) { -+ application_error("called mech (%08lx) not supported\n", -+ pMechanism->mechanism); -+ return CKR_ARGUMENTS_BAD; -+ } -+ return CKR_OK; -+} -+ -+ -+static CK_RV -+dup_mechanism(CK_MECHANISM_PTR *dup, const CK_MECHANISM_PTR pMechanism) -+{ -+ CK_MECHANISM_PTR p; -+ -+ p = malloc(sizeof(*p)); -+ if (p == NULL) -+ return CKR_DEVICE_MEMORY; -+ -+ if (*dup) -+ free(*dup); -+ *dup = p; -+ memcpy(p, pMechanism, sizeof(*p)); -+ -+ return CKR_OK; -+} -+ -+ -+CK_RV -+C_EncryptInit(CK_SESSION_HANDLE hSession, -+ CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey) -+{ -+ struct session_state *state; -+ CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; -+ CK_BBOOL bool_true = CK_TRUE; -+ CK_ATTRIBUTE attr[] = { -+ { CKA_ENCRYPT, &bool_true, sizeof(bool_true) } -+ }; -+ struct st_object *o; -+ CK_RV ret; -+ -+ st_logf("EncryptInit\n"); -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), -+ mechs, sizeof(mechs)/sizeof(mechs[0]), -+ pMechanism, hKey, &o); -+ if (ret) -+ return ret; -+ -+ ret = dup_mechanism(&state->encrypt_mechanism, pMechanism); -+ if (ret == CKR_OK) -+ state->encrypt_object = OBJECT_ID(o); -+ -+ return ret; -+} -+ -+CK_RV -+C_Encrypt(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, -+ CK_BYTE_PTR pEncryptedData, -+ CK_ULONG_PTR pulEncryptedDataLen) -+{ -+ struct session_state *state; -+ struct st_object *o; -+ void *buffer = NULL; -+ CK_RV ret; -+ RSA *rsa; -+ int padding, len, buffer_len, padding_len; -+ -+ st_logf("Encrypt\n"); -+ -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ if (state->encrypt_object == -1) -+ return CKR_ARGUMENTS_BAD; -+ -+ o = soft_token.object.objs[state->encrypt_object]; -+ -+ if (o->u.public_key == NULL) { -+ st_logf("public key NULL\n"); -+ return CKR_ARGUMENTS_BAD; -+ } -+ -+ rsa = EVP_PKEY_get0_RSA(o->u.public_key); -+ if (rsa == NULL) -+ return CKR_ARGUMENTS_BAD; -+ -+ RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */ -+ -+ buffer_len = RSA_size(rsa); -+ -+ buffer = malloc(buffer_len); -+ if (buffer == NULL) { -+ ret = CKR_DEVICE_MEMORY; -+ goto out; -+ } -+ -+ ret = CKR_OK; -+ switch(state->encrypt_mechanism->mechanism) { -+ case CKM_RSA_PKCS: -+ padding = RSA_PKCS1_PADDING; -+ padding_len = RSA_PKCS1_PADDING_SIZE; -+ break; -+ case CKM_RSA_X_509: -+ padding = RSA_NO_PADDING; -+ padding_len = 0; -+ break; -+ default: -+ ret = CKR_FUNCTION_NOT_SUPPORTED; -+ goto out; -+ } -+ -+ if (buffer_len + padding_len < (long) ulDataLen) { -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ if (pulEncryptedDataLen == NULL) { -+ st_logf("pulEncryptedDataLen NULL\n"); -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ if (pData == NULL_PTR) { -+ st_logf("data NULL\n"); -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ len = RSA_public_encrypt(ulDataLen, pData, buffer, rsa, padding); -+ if (len <= 0) { -+ ret = CKR_DEVICE_ERROR; -+ goto out; -+ } -+ if (len > buffer_len) -+ abort(); -+ -+ if (pEncryptedData != NULL_PTR) -+ memcpy(pEncryptedData, buffer, len); -+ *pulEncryptedDataLen = len; -+ -+ out: -+ if (buffer) { -+ memset(buffer, 0, buffer_len); -+ free(buffer); -+ } -+ return ret; -+} -+ -+CK_RV -+C_EncryptUpdate(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen, -+ CK_BYTE_PTR pEncryptedPart, -+ CK_ULONG_PTR pulEncryptedPartLen) -+{ -+ st_logf("EncryptUpdate\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+ -+CK_RV -+C_EncryptFinal(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pLastEncryptedPart, -+ CK_ULONG_PTR pulLastEncryptedPartLen) -+{ -+ st_logf("EncryptFinal\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+ -+/* C_DecryptInit initializes a decryption operation. */ -+CK_RV -+C_DecryptInit(CK_SESSION_HANDLE hSession, -+ CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey) -+{ -+ struct session_state *state; -+ CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; -+ CK_BBOOL bool_true = CK_TRUE; -+ CK_ATTRIBUTE attr[] = { -+ { CKA_DECRYPT, &bool_true, sizeof(bool_true) } -+ }; -+ struct st_object *o; -+ CK_RV ret; -+ -+ st_logf("DecryptInit\n"); -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), -+ mechs, sizeof(mechs)/sizeof(mechs[0]), -+ pMechanism, hKey, &o); -+ if (ret) -+ return ret; -+ -+ ret = dup_mechanism(&state->decrypt_mechanism, pMechanism); -+ if (ret == CKR_OK) -+ state->decrypt_object = OBJECT_ID(o); -+ -+ return CKR_OK; -+} -+ -+ -+CK_RV -+C_Decrypt(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pEncryptedData, -+ CK_ULONG ulEncryptedDataLen, -+ CK_BYTE_PTR pData, -+ CK_ULONG_PTR pulDataLen) -+{ -+ struct session_state *state; -+ struct st_object *o; -+ void *buffer = NULL; -+ CK_RV ret; -+ RSA *rsa; -+ int padding, len, buffer_len, padding_len; -+ -+ st_logf("Decrypt\n"); -+ -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ if (state->decrypt_object == -1) -+ return CKR_ARGUMENTS_BAD; -+ -+ o = soft_token.object.objs[state->decrypt_object]; -+ -+ if (o->u.private_key.key == NULL) { -+ st_logf("private key NULL\n"); -+ return CKR_ARGUMENTS_BAD; -+ } -+ -+ rsa = EVP_PKEY_get0_RSA(o->u.private_key.key); -+ if (rsa == NULL) -+ return CKR_ARGUMENTS_BAD; -+ -+ RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */ -+ -+ buffer_len = RSA_size(rsa); -+ -+ buffer = malloc(buffer_len); -+ if (buffer == NULL) { -+ ret = CKR_DEVICE_MEMORY; -+ goto out; -+ } -+ -+ ret = CKR_OK; -+ switch(state->decrypt_mechanism->mechanism) { -+ case CKM_RSA_PKCS: -+ padding = RSA_PKCS1_PADDING; -+ padding_len = RSA_PKCS1_PADDING_SIZE; -+ break; -+ case CKM_RSA_X_509: -+ padding = RSA_NO_PADDING; -+ padding_len = 0; -+ break; -+ default: -+ ret = CKR_FUNCTION_NOT_SUPPORTED; -+ goto out; -+ } -+ -+ if (buffer_len + padding_len < (long) ulEncryptedDataLen) { -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ if (pulDataLen == NULL) { -+ st_logf("pulDataLen NULL\n"); -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ if (pEncryptedData == NULL_PTR) { -+ st_logf("data NULL\n"); -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ len = RSA_private_decrypt(ulEncryptedDataLen, pEncryptedData, buffer, -+ rsa, padding); -+ if (len <= 0) { -+ ret = CKR_DEVICE_ERROR; -+ goto out; -+ } -+ if (len > buffer_len) -+ abort(); -+ -+ if (pData != NULL_PTR) -+ memcpy(pData, buffer, len); -+ *pulDataLen = len; -+ -+ out: -+ if (buffer) { -+ memset(buffer, 0, buffer_len); -+ free(buffer); -+ } -+ return ret; -+} -+ -+ -+CK_RV -+C_DecryptUpdate(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pEncryptedPart, -+ CK_ULONG ulEncryptedPartLen, -+ CK_BYTE_PTR pPart, -+ CK_ULONG_PTR pulPartLen) -+ -+{ -+ st_logf("DecryptUpdate\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+ -+CK_RV -+C_DecryptFinal(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pLastPart, -+ CK_ULONG_PTR pulLastPartLen) -+{ -+ st_logf("DecryptFinal\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_DigestInit(CK_SESSION_HANDLE hSession, -+ CK_MECHANISM_PTR pMechanism) -+{ -+ st_logf("DigestInit\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_SignInit(CK_SESSION_HANDLE hSession, -+ CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey) -+{ -+ struct session_state *state; -+ CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; -+ CK_BBOOL bool_true = CK_TRUE; -+ CK_ATTRIBUTE attr[] = { -+ { CKA_SIGN, &bool_true, sizeof(bool_true) } -+ }; -+ struct st_object *o; -+ CK_RV ret; -+ -+ st_logf("SignInit\n"); -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), -+ mechs, sizeof(mechs)/sizeof(mechs[0]), -+ pMechanism, hKey, &o); -+ if (ret) -+ return ret; -+ -+ ret = dup_mechanism(&state->sign_mechanism, pMechanism); -+ if (ret == CKR_OK) -+ state->sign_object = OBJECT_ID(o); -+ -+ return CKR_OK; -+} -+ -+CK_RV -+C_Sign(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, -+ CK_BYTE_PTR pSignature, -+ CK_ULONG_PTR pulSignatureLen) -+{ -+ struct session_state *state; -+ struct st_object *o; -+ void *buffer = NULL; -+ CK_RV ret; -+ RSA *rsa; -+ int padding, len, buffer_len; -+ size_t padding_len; -+ -+ st_logf("Sign\n"); -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ if (state->sign_object == -1) -+ return CKR_ARGUMENTS_BAD; -+ -+ o = soft_token.object.objs[state->sign_object]; -+ -+ if (o->u.private_key.key == NULL) { -+ st_logf("private key NULL\n"); -+ return CKR_ARGUMENTS_BAD; -+ } -+ -+ rsa = EVP_PKEY_get0_RSA(o->u.private_key.key); -+ if (rsa == NULL) -+ return CKR_ARGUMENTS_BAD; -+ -+ RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */ -+ -+ buffer_len = RSA_size(rsa); -+ -+ buffer = malloc(buffer_len); -+ if (buffer == NULL) { -+ ret = CKR_DEVICE_MEMORY; -+ goto out; -+ } -+ -+ switch(state->sign_mechanism->mechanism) { -+ case CKM_RSA_PKCS: -+ padding = RSA_PKCS1_PADDING; -+ padding_len = RSA_PKCS1_PADDING_SIZE; -+ break; -+ case CKM_RSA_X_509: -+ padding = RSA_NO_PADDING; -+ padding_len = 0; -+ break; -+ default: -+ ret = CKR_FUNCTION_NOT_SUPPORTED; -+ goto out; -+ } -+ -+ if ((size_t) buffer_len < ulDataLen + padding_len) { -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ if (pulSignatureLen == NULL) { -+ st_logf("signature len NULL\n"); -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ if (pData == NULL_PTR) { -+ st_logf("data NULL\n"); -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ len = RSA_private_encrypt(ulDataLen, pData, buffer, rsa, padding); -+ st_logf("private encrypt done\n"); -+ if (len <= 0) { -+ ret = CKR_DEVICE_ERROR; -+ goto out; -+ } -+ if (len > buffer_len) -+ abort(); -+ -+ if (pSignature != NULL_PTR) -+ memcpy(pSignature, buffer, len); -+ *pulSignatureLen = len; -+ -+ ret = CKR_OK; -+ -+ out: -+ if (buffer) { -+ memset(buffer, 0, buffer_len); -+ free(buffer); -+ } -+ return ret; -+} -+ -+CK_RV -+C_SignUpdate(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen) -+{ -+ st_logf("SignUpdate\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+ -+CK_RV -+C_SignFinal(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pSignature, -+ CK_ULONG_PTR pulSignatureLen) -+{ -+ st_logf("SignUpdate\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_VerifyInit(CK_SESSION_HANDLE hSession, -+ CK_MECHANISM_PTR pMechanism, -+ CK_OBJECT_HANDLE hKey) -+{ -+ struct session_state *state; -+ CK_MECHANISM_TYPE mechs[] = { CKM_RSA_PKCS, CKM_RSA_X_509 }; -+ CK_BBOOL bool_true = CK_TRUE; -+ CK_ATTRIBUTE attr[] = { -+ { CKA_VERIFY, &bool_true, sizeof(bool_true) } -+ }; -+ struct st_object *o; -+ CK_RV ret; -+ -+ st_logf("VerifyInit\n"); -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ ret = commonInit(attr, sizeof(attr)/sizeof(attr[0]), -+ mechs, sizeof(mechs)/sizeof(mechs[0]), -+ pMechanism, hKey, &o); -+ if (ret) -+ return ret; -+ -+ ret = dup_mechanism(&state->verify_mechanism, pMechanism); -+ if (ret == CKR_OK) -+ state->verify_object = OBJECT_ID(o); -+ -+ return ret; -+} -+ -+CK_RV -+C_Verify(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pData, -+ CK_ULONG ulDataLen, -+ CK_BYTE_PTR pSignature, -+ CK_ULONG ulSignatureLen) -+{ -+ struct session_state *state; -+ struct st_object *o; -+ void *buffer = NULL; -+ CK_RV ret; -+ RSA *rsa; -+ int padding, len, buffer_len; -+ -+ st_logf("Verify\n"); -+ VERIFY_SESSION_HANDLE(hSession, &state); -+ -+ if (state->verify_object == -1) -+ return CKR_ARGUMENTS_BAD; -+ -+ o = soft_token.object.objs[state->verify_object]; -+ -+ if (o->u.public_key == NULL) { -+ st_logf("public key NULL\n"); -+ return CKR_ARGUMENTS_BAD; -+ } -+ -+ rsa = EVP_PKEY_get0_RSA(o->u.public_key); -+ if (rsa == NULL) -+ return CKR_ARGUMENTS_BAD; -+ -+ RSA_blinding_off(rsa); /* XXX RAND is broken while running in mozilla ? */ -+ -+ buffer_len = RSA_size(rsa); -+ -+ buffer = malloc(buffer_len); -+ if (buffer == NULL) { -+ ret = CKR_DEVICE_MEMORY; -+ goto out; -+ } -+ -+ ret = CKR_OK; -+ switch(state->verify_mechanism->mechanism) { -+ case CKM_RSA_PKCS: -+ padding = RSA_PKCS1_PADDING; -+ break; -+ case CKM_RSA_X_509: -+ padding = RSA_NO_PADDING; -+ break; -+ default: -+ ret = CKR_FUNCTION_NOT_SUPPORTED; -+ goto out; -+ } -+ -+ if (buffer_len < (long) ulDataLen) { -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ if (pSignature == NULL) { -+ st_logf("signature NULL\n"); -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ if (pData == NULL_PTR) { -+ st_logf("data NULL\n"); -+ ret = CKR_ARGUMENTS_BAD; -+ goto out; -+ } -+ -+ len = RSA_public_decrypt(ulDataLen, pData, buffer, rsa, padding); -+ st_logf("private encrypt done\n"); -+ if (len <= 0) { -+ ret = CKR_DEVICE_ERROR; -+ goto out; -+ } -+ if (len > buffer_len) -+ abort(); -+ -+ if ((size_t) len != ulSignatureLen) { -+ ret = CKR_GENERAL_ERROR; -+ goto out; -+ } -+ -+ if (memcmp(pSignature, buffer, len) != 0) { -+ ret = CKR_GENERAL_ERROR; -+ goto out; -+ } -+ -+ out: -+ if (buffer) { -+ memset(buffer, 0, buffer_len); -+ free(buffer); -+ } -+ return ret; -+} -+ -+ -+CK_RV -+C_VerifyUpdate(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pPart, -+ CK_ULONG ulPartLen) -+{ -+ st_logf("VerifyUpdate\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_VerifyFinal(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR pSignature, -+ CK_ULONG ulSignatureLen) -+{ -+ st_logf("VerifyFinal\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+CK_RV -+C_GenerateRandom(CK_SESSION_HANDLE hSession, -+ CK_BYTE_PTR RandomData, -+ CK_ULONG ulRandomLen) -+{ -+ st_logf("GenerateRandom\n"); -+ VERIFY_SESSION_HANDLE(hSession, NULL); -+ return CKR_FUNCTION_NOT_SUPPORTED; -+} -+ -+ -+CK_FUNCTION_LIST funcs = { -+ { 2, 11 }, -+ C_Initialize, -+ C_Finalize, -+ C_GetInfo, -+ C_GetFunctionList, -+ C_GetSlotList, -+ C_GetSlotInfo, -+ C_GetTokenInfo, -+ C_GetMechanismList, -+ C_GetMechanismInfo, -+ C_InitToken, -+ (void *)func_not_supported, /* C_InitPIN */ -+ (void *)func_not_supported, /* C_SetPIN */ -+ C_OpenSession, -+ C_CloseSession, -+ C_CloseAllSessions, -+ C_GetSessionInfo, -+ (void *)func_not_supported, /* C_GetOperationState */ -+ (void *)func_not_supported, /* C_SetOperationState */ -+ C_Login, -+ C_Logout, -+ (void *)func_not_supported, /* C_CreateObject */ -+ (void *)func_not_supported, /* C_CopyObject */ -+ (void *)func_not_supported, /* C_DestroyObject */ -+ (void *)func_not_supported, /* C_GetObjectSize */ -+ C_GetAttributeValue, -+ (void *)func_not_supported, /* C_SetAttributeValue */ -+ C_FindObjectsInit, -+ C_FindObjects, -+ C_FindObjectsFinal, -+ C_EncryptInit, -+ C_Encrypt, -+ C_EncryptUpdate, -+ C_EncryptFinal, -+ C_DecryptInit, -+ C_Decrypt, -+ C_DecryptUpdate, -+ C_DecryptFinal, -+ C_DigestInit, -+ (void *)func_not_supported, /* C_Digest */ -+ (void *)func_not_supported, /* C_DigestUpdate */ -+ (void *)func_not_supported, /* C_DigestKey */ -+ (void *)func_not_supported, /* C_DigestFinal */ -+ C_SignInit, -+ C_Sign, -+ C_SignUpdate, -+ C_SignFinal, -+ (void *)func_not_supported, /* C_SignRecoverInit */ -+ (void *)func_not_supported, /* C_SignRecover */ -+ C_VerifyInit, -+ C_Verify, -+ C_VerifyUpdate, -+ C_VerifyFinal, -+ (void *)func_not_supported, /* C_VerifyRecoverInit */ -+ (void *)func_not_supported, /* C_VerifyRecover */ -+ (void *)func_not_supported, /* C_DigestEncryptUpdate */ -+ (void *)func_not_supported, /* C_DecryptDigestUpdate */ -+ (void *)func_not_supported, /* C_SignEncryptUpdate */ -+ (void *)func_not_supported, /* C_DecryptVerifyUpdate */ -+ (void *)func_not_supported, /* C_GenerateKey */ -+ (void *)func_not_supported, /* C_GenerateKeyPair */ -+ (void *)func_not_supported, /* C_WrapKey */ -+ (void *)func_not_supported, /* C_UnwrapKey */ -+ (void *)func_not_supported, /* C_DeriveKey */ -+ (void *)func_not_supported, /* C_SeedRandom */ -+ C_GenerateRandom, -+ (void *)func_not_supported, /* C_GetFunctionStatus */ -+ (void *)func_not_supported, /* C_CancelFunction */ -+ (void *)func_not_supported /* C_WaitForSlotEvent */ -+}; -diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile -index e464b085..a0e5a37c 100644 ---- a/regress/unittests/Makefile -+++ b/regress/unittests/Makefile -@@ -2,6 +2,6 @@ - - REGRESS_FAIL_EARLY?= yes - SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys utf8 match conversion --SUBDIR+=authopt -+SUBDIR+=pkcs11 authopt - - .include -diff --git a/regress/unittests/pkcs11/Makefile b/regress/unittests/pkcs11/Makefile -new file mode 100644 -index 00000000..481b13d0 ---- /dev/null -+++ b/regress/unittests/pkcs11/Makefile -@@ -0,0 +1,9 @@ -+ -+PROG=test_pkcs11 -+SRCS=tests.c -+REGRESS_TARGETS=run-regress-${PROG} -+ -+run-regress-${PROG}: ${PROG} -+ env ${TEST_ENV} ./${PROG} -+ -+.include -diff --git a/regress/unittests/pkcs11/tests.c b/regress/unittests/pkcs11/tests.c -new file mode 100644 -index 00000000..e83aca54 ---- /dev/null -+++ b/regress/unittests/pkcs11/tests.c -@@ -0,0 +1,330 @@ -+/* -+ * Copyright (c) 2017 Red Hat -+ * -+ * Authors: Jakub Jelen -+ * -+ * Permission to use, copy, modify, and distribute this software for any -+ * purpose with or without fee is hereby granted, provided that the above -+ * copyright notice and this permission notice appear in all copies. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -+ */ -+ -+#include "includes.h" -+ -+#include -+#include -+ -+#include "../test_helper/test_helper.h" -+ -+#include "sshbuf.h" -+#include "ssh-pkcs11-uri.h" -+ -+#define EMPTY_URI compose_uri(NULL, 0, NULL, NULL, NULL, NULL, NULL) -+ -+/* prototypes are not public -- specify them here internally for tests */ -+struct sshbuf *percent_encode(const char *, size_t, char *); -+int percent_decode(char *, char **); -+ -+void -+compare_uri(struct pkcs11_uri *a, struct pkcs11_uri *b) -+{ -+ ASSERT_PTR_NE(a, NULL); -+ ASSERT_PTR_NE(b, NULL); -+ ASSERT_SIZE_T_EQ(a->id_len, b->id_len); -+ ASSERT_MEM_EQ(a->id, b->id, a->id_len); -+ if (b->object != NULL) -+ ASSERT_STRING_EQ(a->object, b->object); -+ else /* both should be null */ -+ ASSERT_PTR_EQ(a->object, b->object); -+ if (b->module_path != NULL) -+ ASSERT_STRING_EQ(a->module_path, b->module_path); -+ else /* both should be null */ -+ ASSERT_PTR_EQ(a->module_path, b->module_path); -+ if (b->token != NULL) -+ ASSERT_STRING_EQ(a->token, b->token); -+ else /* both should be null */ -+ ASSERT_PTR_EQ(a->token, b->token); -+ if (b->manuf != NULL) -+ ASSERT_STRING_EQ(a->manuf, b->manuf); -+ else /* both should be null */ -+ ASSERT_PTR_EQ(a->manuf, b->manuf); -+ if (b->lib_manuf != NULL) -+ ASSERT_STRING_EQ(a->lib_manuf, b->lib_manuf); -+ else /* both should be null */ -+ ASSERT_PTR_EQ(a->lib_manuf, b->lib_manuf); -+} -+ -+void -+check_parse_rv(char *uri, struct pkcs11_uri *expect, int expect_rv) -+{ -+ char *buf = NULL, *str; -+ struct pkcs11_uri *pkcs11uri = NULL; -+ int rv; -+ -+ if (expect_rv == 0) -+ str = "Valid"; -+ else -+ str = "Invalid"; -+ asprintf(&buf, "%s PKCS#11 URI parsing: %s", str, uri); -+ TEST_START(buf); -+ free(buf); -+ pkcs11uri = pkcs11_uri_init(); -+ rv = pkcs11_uri_parse(uri, pkcs11uri); -+ ASSERT_INT_EQ(rv, expect_rv); -+ if (rv == 0) /* in case of failure result is undefined */ -+ compare_uri(pkcs11uri, expect); -+ pkcs11_uri_cleanup(pkcs11uri); -+ free(expect); -+ TEST_DONE(); -+} -+ -+void -+check_parse(char *uri, struct pkcs11_uri *expect) -+{ -+ check_parse_rv(uri, expect, 0); -+} -+ -+struct pkcs11_uri * -+compose_uri(unsigned char *id, size_t id_len, char *token, char *lib_manuf, -+ char *manuf, char *module_path, char *object) -+{ -+ struct pkcs11_uri *uri = pkcs11_uri_init(); -+ if (id_len > 0) { -+ uri->id_len = id_len; -+ uri->id = id; -+ } -+ uri->module_path = module_path; -+ uri->token = token; -+ uri->lib_manuf = lib_manuf; -+ uri->manuf = manuf; -+ uri->object = object; -+ return uri; -+} -+ -+static void -+test_parse_valid(void) -+{ -+ /* path arguments */ -+ check_parse("pkcs11:id=%01", -+ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL)); -+ check_parse("pkcs11:id=%00%01", -+ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL)); -+ check_parse("pkcs11:token=SSH%20Keys", -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL)); -+ check_parse("pkcs11:library-manufacturer=OpenSC", -+ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL)); -+ check_parse("pkcs11:manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL)); -+ check_parse("pkcs11:object=SIGN%20Key", -+ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "SIGN Key")); -+ /* query arguments */ -+ check_parse("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL)); -+ -+ /* combinations */ -+ /* ID SHOULD be percent encoded */ -+ check_parse("pkcs11:token=SSH%20Key;id=0", -+ compose_uri("0", 1, "SSH Key", NULL, NULL, NULL, NULL)); -+ check_parse( -+ "pkcs11:manufacturer=CAC?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, "CAC", -+ "/usr/lib64/p11-kit-proxy.so", NULL)); -+ check_parse( -+ "pkcs11:object=RSA%20Key?module-path=/usr/lib64/pkcs11/opencryptoki.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, -+ "/usr/lib64/pkcs11/opencryptoki.so", "RSA Key")); -+ -+ /* empty path component matches everything */ -+ check_parse("pkcs11:", EMPTY_URI); -+ -+ /* empty string is a valid to match against (and different from NULL) */ -+ check_parse("pkcs11:token=", -+ compose_uri(NULL, 0, "", NULL, NULL, NULL, NULL)); -+ /* Percent character needs to be percent-encoded */ -+ check_parse("pkcs11:token=%25", -+ compose_uri(NULL, 0, "%", NULL, NULL, NULL, NULL)); -+} -+ -+static void -+test_parse_invalid(void) -+{ -+ /* Invalid percent encoding */ -+ check_parse_rv("pkcs11:id=%0", EMPTY_URI, -1); -+ /* Invalid percent encoding */ -+ check_parse_rv("pkcs11:id=%ZZ", EMPTY_URI, -1); -+ /* Space MUST be percent encoded -- XXX not enforced yet */ -+ check_parse("pkcs11:token=SSH Keys", -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL)); -+ /* MUST NOT contain duplicate attributes of the same name */ -+ check_parse_rv("pkcs11:id=%01;id=%02", EMPTY_URI, -1); -+ /* Unrecognized attribute in path SHOULD be error */ -+ check_parse_rv("pkcs11:key_name=SSH", EMPTY_URI, -1); -+ /* Unrecognized attribute in query SHOULD be ignored */ -+ check_parse("pkcs11:?key_name=SSH", EMPTY_URI); -+} -+ -+void -+check_gen(char *expect, struct pkcs11_uri *uri) -+{ -+ char *buf = NULL, *uri_str; -+ -+ asprintf(&buf, "Valid PKCS#11 URI generation: %s", expect); -+ TEST_START(buf); -+ free(buf); -+ uri_str = pkcs11_uri_get(uri); -+ ASSERT_PTR_NE(uri_str, NULL); -+ ASSERT_STRING_EQ(uri_str, expect); -+ free(uri_str); -+ TEST_DONE(); -+} -+ -+static void -+test_generate_valid(void) -+{ -+ /* path arguments */ -+ check_gen("pkcs11:id=%01", -+ compose_uri("\x01", 1, NULL, NULL, NULL, NULL, NULL)); -+ check_gen("pkcs11:id=%00%01", -+ compose_uri("\x00\x01", 2, NULL, NULL, NULL, NULL, NULL)); -+ check_gen("pkcs11:token=SSH%20Keys", /* space must be percent encoded */ -+ compose_uri(NULL, 0, "SSH Keys", NULL, NULL, NULL, NULL)); -+ /* library-manufacturer is not implmented now */ -+ /*check_gen("pkcs11:library-manufacturer=OpenSC", -+ compose_uri(NULL, 0, NULL, "OpenSC", NULL, NULL, NULL));*/ -+ check_gen("pkcs11:manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, NULL)); -+ check_gen("pkcs11:object=RSA%20Key", -+ compose_uri(NULL, 0, NULL, NULL, NULL, NULL, "RSA Key")); -+ /* query arguments */ -+ check_gen("pkcs11:?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri(NULL, 0, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL)); -+ -+ /* combinations */ -+ check_gen("pkcs11:id=%02;token=SSH%20Keys", -+ compose_uri("\x02", 1, "SSH Keys", NULL, NULL, NULL, NULL)); -+ check_gen("pkcs11:id=%EE%02?module-path=/usr/lib64/p11-kit-proxy.so", -+ compose_uri("\xEE\x02", 2, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL)); -+ check_gen("pkcs11:object=Encryption%20Key;manufacturer=piv_II", -+ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, "Encryption Key")); ++ /* combinations */ ++ check_gen("pkcs11:id=%02;token=SSH%20Keys", ++ compose_uri("\x02", 1, "SSH Keys", NULL, NULL, NULL, NULL, NULL)); ++ check_gen("pkcs11:id=%EE%02?module-path=/usr/lib64/p11-kit-proxy.so", ++ compose_uri("\xEE\x02", 2, NULL, NULL, NULL, "/usr/lib64/p11-kit-proxy.so", NULL, NULL)); ++ check_gen("pkcs11:object=Encryption%20Key;manufacturer=piv_II", ++ compose_uri(NULL, 0, NULL, NULL, "piv_II", NULL, "Encryption Key", NULL)); + + /* empty path component matches everything */ + check_gen("pkcs11:", EMPTY_URI); @@ -3049,61 +916,93 @@ index 00000000..e83aca54 + test_generate_valid(); +} diff --git a/ssh-add.c b/ssh-add.c -index adcc4599..e4fd5623 100644 +index 8057eb1f..0c470e32 100644 --- a/ssh-add.c +++ b/ssh-add.c -@@ -64,6 +64,7 @@ - #include "misc.h" +@@ -67,6 +67,7 @@ #include "ssherr.h" #include "digest.h" + #include "ssh-sk.h" +#include "ssh-pkcs11-uri.h" /* argv0 */ extern char *__progname; -@@ -188,6 +189,24 @@ delete_all(int agent_fd) +@@ -193,6 +194,32 @@ delete_all(int agent_fd, int qflag) return ret; } +#ifdef ENABLE_PKCS11 -+static int update_card(int, int, const char *); ++static int update_card(int, int, const char *, int, char *); + +int -+update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri) ++update_pkcs11_uri(int agent_fd, int adding, const char *pkcs11_uri, int qflag) +{ ++ char *pin = NULL; + struct pkcs11_uri *uri; + + /* dry-run parse to make sure the URI is valid and to report errors */ + uri = pkcs11_uri_init(); + if (pkcs11_uri_parse((char *) pkcs11_uri, uri) != 0) + fatal("Failed to parse PKCS#11 URI"); ++ if (uri->pin != NULL) { ++ pin = strdup(uri->pin); ++ if (pin == NULL) { ++ fatal("Failed to dupplicate string"); ++ } ++ /* pin is freed in the update_card() */ ++ } + pkcs11_uri_cleanup(uri); + -+ return update_card(agent_fd, adding, pkcs11_uri); ++ return update_card(agent_fd, adding, pkcs11_uri, qflag, pin); +} +#endif + static int - add_file(int agent_fd, const char *filename, int key_only, int qflag) - { -@@ -480,6 +499,13 @@ lock_agent(int agent_fd, int lock) + add_file(int agent_fd, const char *filename, int key_only, int qflag, + const char *skprovider) +@@ -402,12 +429,11 @@ add_file(int agent_fd, const char *filename, int key_only, int qflag, + } + static int - do_file(int agent_fd, int deleting, int key_only, char *file, int qflag) +-update_card(int agent_fd, int add, const char *id, int qflag) ++update_card(int agent_fd, int add, const char *id, int qflag, char *pin) + { +- char *pin = NULL; + int r, ret = -1; + +- if (add) { ++ if (add && pin == NULL) { + if ((pin = read_passphrase("Enter passphrase for PKCS#11: ", + RP_ALLOW_STDIN)) == NULL) + return -1; +@@ -591,6 +617,13 @@ static int + do_file(int agent_fd, int deleting, int key_only, char *file, int qflag, + const char *skprovider) { +#ifdef ENABLE_PKCS11 + if (strlen(file) >= strlen(PKCS11_URI_SCHEME) && + strncmp(file, PKCS11_URI_SCHEME, + strlen(PKCS11_URI_SCHEME)) == 0) { -+ return update_pkcs11_uri(agent_fd, !deleting, file); ++ return update_pkcs11_uri(agent_fd, !deleting, file, qflag); + } +#endif if (deleting) { if (delete_file(agent_fd, file, key_only, qflag) == -1) return -1; +@@ -773,7 +806,7 @@ main(int argc, char **argv) + } + if (pkcs11provider != NULL) { + if (update_card(agent_fd, !deleting, pkcs11provider, +- qflag) == -1) ++ qflag, NULL) == -1) + ret = 1; + goto done; + } diff --git a/ssh-agent.c b/ssh-agent.c -index 2a4578b0..f6c86240 100644 +index 7eb6f0dc..27d8e4af 100644 --- a/ssh-agent.c +++ b/ssh-agent.c -@@ -546,10 +546,72 @@ no_identities(SocketEntry *e) +@@ -641,10 +641,72 @@ no_identities(SocketEntry *e) } #ifdef ENABLE_PKCS11 @@ -3123,7 +1022,7 @@ index 2a4578b0..f6c86240 100644 + /* PKCS#11 URI */ + uri = pkcs11_uri_init(); + if (uri == NULL) { -+ error("Failed to init PCKS#11 URI"); ++ error("Failed to init PKCS#11 URI"); + return NULL; + } + @@ -3146,7 +1045,7 @@ index 2a4578b0..f6c86240 100644 + return NULL; + } + free(module_path); -+ if (match_pattern_list(canonical_provider, pkcs11_whitelist, 0) != 1) { ++ if (match_pattern_list(canonical_provider, provider_whitelist, 0) != 1) { + verbose("refusing PKCS#11 provider \"%.100s\": " + "not whitelisted", canonical_provider); + pkcs11_uri_cleanup(uri); @@ -3174,10 +1073,10 @@ index 2a4578b0..f6c86240 100644 { - char *provider = NULL, *pin = NULL, canonical_provider[PATH_MAX]; + char *provider = NULL, *pin = NULL, *sane_uri = NULL; + char **comments = NULL; int r, i, count = 0, success = 0, confirm = 0; u_int seconds; - time_t death = 0; -@@ -585,28 +645,23 @@ process_add_smartcard_key(SocketEntry *e) +@@ -681,33 +743,28 @@ process_add_smartcard_key(SocketEntry *e) goto send; } } @@ -3186,7 +1085,7 @@ index 2a4578b0..f6c86240 100644 - provider, strerror(errno)); - goto send; - } -- if (match_pattern_list(canonical_provider, pkcs11_whitelist, 0) != 1) { +- if (match_pattern_list(canonical_provider, provider_whitelist, 0) != 1) { - verbose("refusing PKCS#11 add of \"%.100s\": " - "provider not whitelisted", canonical_provider); + @@ -3199,30 +1098,35 @@ index 2a4578b0..f6c86240 100644 if (lifetime && !death) death = monotime() + lifetime; -- count = pkcs11_add_provider(canonical_provider, pin, &keys); +- count = pkcs11_add_provider(canonical_provider, pin, &keys, &comments); + debug("%s: add %.100s", __func__, sane_uri); -+ count = pkcs11_add_provider(sane_uri, pin, &keys); ++ count = pkcs11_add_provider(sane_uri, pin, &keys, &comments); for (i = 0; i < count; i++) { k = keys[i]; if (lookup_identity(k) == NULL) { id = xcalloc(1, sizeof(Identity)); id->key = k; + keys[i] = NULL; /* transferred */ - id->provider = xstrdup(canonical_provider); -- id->comment = xstrdup(canonical_provider); /* XXX */ + id->provider = xstrdup(sane_uri); -+ id->comment = xstrdup(sane_uri); + if (*comments[i] != '\0') { + id->comment = comments[i]; + comments[i] = NULL; /* transferred */ + } else { +- id->comment = xstrdup(canonical_provider); ++ id->comment = xstrdup(sane_uri); + } id->death = death; id->confirm = confirm; - TAILQ_INSERT_TAIL(&idtab->idlist, id, next); -@@ -620,6 +675,7 @@ process_add_smartcard_key(SocketEntry *e) +@@ -721,6 +778,7 @@ process_add_smartcard_key(SocketEntry *e) send: free(pin); free(provider); + free(sane_uri); free(keys); + free(comments); send_status(e, success); - } -@@ -627,7 +683,7 @@ send: +@@ -729,7 +787,7 @@ send: static void process_remove_smartcard_key(SocketEntry *e) { @@ -3231,7 +1135,7 @@ index 2a4578b0..f6c86240 100644 int r, success = 0; Identity *id, *nxt; -@@ -638,30 +694,29 @@ process_remove_smartcard_key(SocketEntry *e) +@@ -740,30 +798,29 @@ process_remove_smartcard_key(SocketEntry *e) } free(pin); @@ -3269,30 +1173,28 @@ index 2a4578b0..f6c86240 100644 } #endif /* ENABLE_PKCS11 */ diff --git a/ssh-keygen.c b/ssh-keygen.c -index d1ffc30c..00e38049 100644 +index 0d6ed1ff..182f4f2b 100644 --- a/ssh-keygen.c +++ b/ssh-keygen.c -@@ -820,6 +820,7 @@ do_download(struct passwd *pw) +@@ -855,8 +855,11 @@ do_download(struct passwd *pw) free(fp); } else { (void) sshkey_write(keys[i], stdout); /* XXX check */ +- fprintf(stdout, "%s%s\n", +- *(comments[i]) == '\0' ? "" : " ", comments[i]); ++ if (*(comments[i]) != '\0') { ++ fprintf(stdout, " %s", comments[i]); ++ } + (void) pkcs11_uri_write(keys[i], stdout); - fprintf(stdout, "\n"); ++ fprintf(stdout, "\n"); } + free(comments[i]); sshkey_free(keys[i]); diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c -index a023f5f4..882e8381 100644 +index 8a0ffef5..ead8a562 100644 --- a/ssh-pkcs11-client.c +++ b/ssh-pkcs11-client.c -@@ -117,6 +117,7 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, - return (-1); - key.type = KEY_RSA; - key.rsa = rsa; -+ key.ecdsa_nid = 0; - if ((r = sshkey_to_blob(&key, &blob, &blen)) != 0) { - error("%s: sshkey_to_blob: %s", __func__, ssh_err(r)); - return -1; -@@ -195,6 +196,8 @@ pkcs11_add_provider(char *name, char *pin, Key ***keysp) +@@ -323,6 +323,8 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, u_int nkeys, i; struct sshbuf *msg; @@ -3301,20 +1203,20 @@ index a023f5f4..882e8381 100644 if (fd < 0 && pkcs11_start_helper() < 0) return (-1); -@@ -208,6 +211,7 @@ pkcs11_add_provider(char *name, char *pin, Key ***keysp) - if ((r = sshbuf_get_u32(msg, &nkeys)) != 0) - fatal("%s: buffer error: %s", __func__, ssh_err(r)); +@@ -342,6 +344,7 @@ pkcs11_add_provider(char *name, char *pin, struct sshkey ***keysp, *keysp = xcalloc(nkeys, sizeof(struct sshkey *)); + if (labelsp) + *labelsp = xcalloc(nkeys, sizeof(char *)); + debug("%s: nkeys = %u", __func__, nkeys); for (i = 0; i < nkeys; i++) { /* XXX clean up properly instead of fatal() */ if ((r = sshbuf_get_string(msg, &blob, &blen)) != 0 || diff --git a/ssh-pkcs11-uri.c b/ssh-pkcs11-uri.c new file mode 100644 -index 00000000..da15c164 +index 00000000..e1a7b4e0 --- /dev/null +++ b/ssh-pkcs11-uri.c -@@ -0,0 +1,395 @@ +@@ -0,0 +1,421 @@ +/* + * Copyright (c) 2017 Red Hat + * @@ -3358,11 +1260,12 @@ index 00000000..da15c164 +#define PKCS11_URI_LIB_MANUF "library-manufacturer" +#define PKCS11_URI_MANUF "manufacturer" +#define PKCS11_URI_MODULE_PATH "module-path" ++#define PKCS11_URI_PIN_VALUE "pin-value" + +/* Keyword tokens. */ +typedef enum { + pId, pToken, pObject, pLibraryManufacturer, pManufacturer, pModulePath, -+ pBadOption ++ pPinValue, pBadOption +} pkcs11uriOpCodes; + +/* Textual representation of the tokens. */ @@ -3376,6 +1279,7 @@ index 00000000..da15c164 + { PKCS11_URI_LIB_MANUF, pLibraryManufacturer }, + { PKCS11_URI_MANUF, pManufacturer }, + { PKCS11_URI_MODULE_PATH, pModulePath }, ++ { PKCS11_URI_PIN_VALUE, pPinValue }, + { NULL, pBadOption } +}; + @@ -3570,6 +1474,8 @@ index 00000000..da15c164 + free(pkcs11->object); + free(pkcs11->lib_manuf); + free(pkcs11->manuf); ++ if (pkcs11->pin) ++ freezero(pkcs11->pin, strlen(pkcs11->pin)); + free(pkcs11); +} + @@ -3600,9 +1506,9 @@ index 00000000..da15c164 + /* everything before ? */ + tok = strtok_r(str1, "?", &saveptr1); + if (tok == NULL) { -+ free(p); + error("%s: pk11-path expected, got EOF", __func__); -+ return -1; ++ rv = -1; ++ goto out; + } + + /* skip URI schema name: @@ -3613,14 +1519,15 @@ index 00000000..da15c164 + + /* parse pk11-path */ + for (str2 = tok; ; str2 = NULL) { -+ char **charptr; ++ char **charptr, *arg = NULL; + pkcs11uriOpCodes opcode; + tok = strtok_r(str2, PKCS11_URI_PATH_SEPARATOR, &saveptr2); + if (tok == NULL) + break; + opcode = parse_token(tok); ++ if (opcode != pBadOption) ++ arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */ + -+ char *arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */ + switch (opcode) { + case pId: + /* CKA_ID */ @@ -3628,12 +1535,14 @@ index 00000000..da15c164 + verbose("%s: The id already set in the PKCS#11 URI", + __func__); + rv = -1; ++ goto out; + } + len = percent_decode(arg, &pkcs11->id); + if (len <= 0) { + verbose("%s: Failed to percent-decode CKA_ID: %s", + __func__, arg); + rv = -1; ++ goto out; + } else + pkcs11->id_len = len; + debug3("%s: Setting CKA_ID = %s from PKCS#11 URI", @@ -3647,6 +1556,7 @@ index 00000000..da15c164 + verbose("%s: The %s already set in the PKCS#11 URI", + keywords[opcode].name, __func__); + rv = -1; ++ goto out; + } + percent_decode(arg, charptr); + debug3("%s: Setting %s = %s from PKCS#11 URI", @@ -3668,7 +1578,6 @@ index 00000000..da15c164 + charptr = &pkcs11->lib_manuf; + goto parse_string; + -+ case pBadOption: + default: + /* Unrecognized attribute in the URI path SHOULD be error */ + verbose("%s: Unknown part of path in PKCS#11 URI: %s", @@ -3678,33 +1587,52 @@ index 00000000..da15c164 + + tok = strtok_r(NULL, "?", &saveptr1); + if (tok == NULL) { -+ free(p); -+ return rv; ++ goto out; + } + /* parse pk11-query (optional) */ + for (str2 = tok; ; str2 = NULL) { -+ size_t key_len = strlen(PKCS11_URI_MODULE_PATH) + 1; ++ char *arg; ++ pkcs11uriOpCodes opcode; + tok = strtok_r(str2, PKCS11_URI_QUERY_SEPARATOR, &saveptr2); + if (tok == NULL) + break; -+ if (strncasecmp(tok, PKCS11_URI_MODULE_PATH -+ PKCS11_URI_VALUE_SEPARATOR, key_len) == 0) { ++ opcode = parse_token(tok); ++ if (opcode != pBadOption) ++ arg = tok + strlen(keywords[opcode].name) + 1; /* separator "=" */ ++ ++ switch (opcode) { ++ case pModulePath: + /* module-path is PKCS11Provider */ + if (pkcs11->module_path != NULL) { + verbose("%s: Multiple module-path attributes are" + "not supported the PKCS#11 URI", __func__); + rv = -1; ++ goto out; + } -+ percent_decode(tok + key_len, &pkcs11->module_path); ++ percent_decode(arg, &pkcs11->module_path); + debug3("%s: Setting PKCS11Provider = %s from PKCS#11 URI", + __func__, pkcs11->module_path); -+ /* } else if ( pin-value ) { */ -+ } else { ++ break; ++ ++ case pPinValue: ++ /* pin-value */ ++ if (pkcs11->pin != NULL) { ++ verbose("%s: Multiple pin-value attributes are" ++ "not supported the PKCS#11 URI", __func__); ++ rv = -1; ++ goto out; ++ } ++ percent_decode(arg, &pkcs11->pin); ++ debug3("%s: Setting PIN from PKCS#11 URI", __func__); ++ break; ++ ++ default: + /* Unrecognized attribute in the URI query SHOULD be ignored */ + verbose("%s: Unknown part of query in PKCS#11 URI: %s", + __func__, tok); + } + } ++out: + free(p); + return rv; +} @@ -3712,10 +1640,10 @@ index 00000000..da15c164 +#endif /* ENABLE_PKCS11 */ diff --git a/ssh-pkcs11-uri.h b/ssh-pkcs11-uri.h new file mode 100644 -index 00000000..609c4df1 +index 00000000..942a5a5a --- /dev/null +++ b/ssh-pkcs11-uri.h -@@ -0,0 +1,41 @@ +@@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017 Red Hat + * @@ -3749,19 +1677,20 @@ index 00000000..609c4df1 + char *manuf; + /* query */ + char *module_path; ++ char *pin; /* Only parsed, but not printed */ +}; + -+struct pkcs11_uri *pkcs11_uri_init(); -+void pkcs11_uri_cleanup(struct pkcs11_uri *); -+int pkcs11_uri_parse(const char *, struct pkcs11_uri *); -+struct pkcs11_uri *pkcs11_uri_init(); -+char * pkcs11_uri_get(struct pkcs11_uri *uri); ++struct pkcs11_uri *pkcs11_uri_init(); ++void pkcs11_uri_cleanup(struct pkcs11_uri *); ++int pkcs11_uri_parse(const char *, struct pkcs11_uri *); ++struct pkcs11_uri *pkcs11_uri_init(); ++char *pkcs11_uri_get(struct pkcs11_uri *uri); + diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c -index 88c9d6e2..a29b4451 100644 +index a302c79c..879fe917 100644 --- a/ssh-pkcs11.c +++ b/ssh-pkcs11.c -@@ -48,8 +48,8 @@ struct pkcs11_slotinfo { +@@ -54,8 +54,8 @@ struct pkcs11_slotinfo { int logged_in; }; @@ -3772,7 +1701,7 @@ index 88c9d6e2..a29b4451 100644 void *handle; CK_FUNCTION_LIST *function_list; CK_INFO info; -@@ -58,6 +58,13 @@ struct pkcs11_provider { +@@ -64,6 +64,13 @@ struct pkcs11_provider { struct pkcs11_slotinfo *slotinfo; int valid; int refcount; @@ -3786,54 +1715,15 @@ index 88c9d6e2..a29b4451 100644 TAILQ_ENTRY(pkcs11_provider) next; }; -@@ -70,10 +77,46 @@ struct pkcs11_key { - RSA_METHOD rsa_method; +@@ -74,6 +81,7 @@ struct pkcs11_key { + CK_ULONG slotidx; char *keyid; int keyid_len; + char *label; }; int pkcs11_interactive = 0; - -+/* -+ * This can't be in the ssh-pkcs11-uri, becase we can not depend on -+ * PKCS#11 structures in ssh-agent (using client-helper communication) -+ */ -+int -+pkcs11_uri_write(const struct sshkey *key, FILE *f) -+{ -+ char *p = NULL; -+ struct pkcs11_uri uri; -+ struct pkcs11_key *k11; -+ -+ /* sanity - is it a RSA key with associated app_data? */ -+ if (key->type != KEY_RSA || -+ (k11 = RSA_get_app_data(key->rsa)) == NULL) -+ return -1; -+ -+ /* omit type -- we are looking for private-public or private-certificate pairs */ -+ uri.id = k11->keyid; -+ uri.id_len = k11->keyid_len; -+ uri.token = k11->provider->module->slotinfo[k11->slotidx].token.label; -+ uri.object = k11->label; -+ uri.module_path = k11->provider->module->module_path; -+ uri.lib_manuf = k11->provider->module->info.manufacturerID; -+ uri.manuf = k11->provider->module->slotinfo[k11->slotidx].token.manufacturerID; -+ -+ p = pkcs11_uri_get(&uri); -+ /* do not cleanup -- we do not allocate here, only reference */ -+ if (p == NULL) -+ return -1; -+ -+ fprintf(f, " %s", p); -+ free(p); -+ return 0; -+} -+ - int - pkcs11_init(int interactive) - { -@@ -89,26 +132,63 @@ pkcs11_init(int interactive) +@@ -106,26 +114,63 @@ pkcs11_init(int interactive) * this is called when a provider gets unregistered. */ static void @@ -3908,7 +1798,7 @@ index 88c9d6e2..a29b4451 100644 } /* -@@ -118,12 +198,11 @@ pkcs11_provider_finalize(struct pkcs11_provider *p) +@@ -135,13 +180,11 @@ pkcs11_provider_finalize(struct pkcs11_provider *p) static void pkcs11_provider_unref(struct pkcs11_provider *p) { @@ -3917,15 +1807,15 @@ index 88c9d6e2..a29b4451 100644 if (--p->refcount <= 0) { - if (p->valid) - error("pkcs11_provider_unref: %p still valid", p); + free(p->name); - free(p->slotlist); - free(p->slotinfo); + if (p->module) + pkcs11_module_unref(p->module); -+ free(p->name); free(p); } } -@@ -141,6 +220,20 @@ pkcs11_terminate(void) +@@ -159,6 +202,20 @@ pkcs11_terminate(void) } } @@ -3946,7 +1836,7 @@ index 88c9d6e2..a29b4451 100644 /* lookup provider by name */ static struct pkcs11_provider * pkcs11_provider_lookup(char *provider_id) -@@ -155,19 +248,52 @@ pkcs11_provider_lookup(char *provider_id) +@@ -173,19 +230,52 @@ pkcs11_provider_lookup(char *provider_id) return (NULL); } @@ -3963,7 +1853,7 @@ index 88c9d6e2..a29b4451 100644 + + uri = pkcs11_uri_init(); + if (uri == NULL) -+ fatal("Failed to init PCKS#11 URI"); ++ fatal("Failed to init PKCS#11 URI"); + + if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && + strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { @@ -4001,16 +1891,72 @@ index 88c9d6e2..a29b4451 100644 + return rv; } - /* openssl callback for freeing an RSA key */ -@@ -183,6 +309,7 @@ pkcs11_rsa_finish(RSA *rsa) - if (k11->provider) - pkcs11_provider_unref(k11->provider); - free(k11->keyid); -+ free(k11->label); - free(k11); - } - return (rv); -@@ -199,8 +327,8 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, + static RSA_METHOD *rsa_method; +@@ -195,6 +285,55 @@ static EC_KEY_METHOD *ec_key_method; + static int ec_key_idx = 0; + #endif + ++/* ++ * This can't be in the ssh-pkcs11-uri, becase we can not depend on ++ * PKCS#11 structures in ssh-agent (using client-helper communication) ++ */ ++int ++pkcs11_uri_write(const struct sshkey *key, FILE *f) ++{ ++ char *p = NULL; ++ struct pkcs11_uri uri; ++ struct pkcs11_key *k11; ++ ++ /* sanity - is it a RSA key with associated app_data? */ ++ switch (key->type) { ++ case KEY_RSA: ++ k11 = RSA_get_ex_data(key->rsa, rsa_idx); ++ break; ++#ifdef HAVE_EC_KEY_METHOD_NEW ++ case KEY_ECDSA: ++ k11 = EC_KEY_get_ex_data(key->ecdsa, ec_key_idx); ++ break; ++#endif ++ default: ++ error("Unknown key type %d", key->type); ++ return -1; ++ } ++ if (k11 == NULL) { ++ error("Failed to get ex_data for key type %d", key->type); ++ return (-1); ++ } ++ ++ /* omit type -- we are looking for private-public or private-certificate pairs */ ++ uri.id = k11->keyid; ++ uri.id_len = k11->keyid_len; ++ uri.token = k11->provider->module->slotinfo[k11->slotidx].token.label; ++ uri.object = k11->label; ++ uri.module_path = k11->provider->module->module_path; ++ uri.lib_manuf = k11->provider->module->info.manufacturerID; ++ uri.manuf = k11->provider->module->slotinfo[k11->slotidx].token.manufacturerID; ++ ++ p = pkcs11_uri_get(&uri); ++ /* do not cleanup -- we do not allocate here, only reference */ ++ if (p == NULL) ++ return -1; ++ ++ fprintf(f, " %s", p); ++ free(p); ++ return 0; ++} ++ + /* release a wrapped object */ + static void + pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, +@@ -208,6 +347,7 @@ pkcs11_k11_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad, int idx, + if (k11->provider) + pkcs11_provider_unref(k11->provider); + free(k11->keyid); ++ free(k11->label); + free(k11); + } + +@@ -222,8 +362,8 @@ pkcs11_find(struct pkcs11_provider *p, CK_ULONG slotidx, CK_ATTRIBUTE *attr, CK_RV rv; int ret = -1; @@ -4021,320 +1967,550 @@ index 88c9d6e2..a29b4451 100644 if ((rv = f->C_FindObjectsInit(session, attr, nattr)) != CKR_OK) { error("C_FindObjectsInit failed (nattr %lu): %lu", nattr, rv); return (-1); -@@ -247,12 +375,13 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, - error("RSA_get_app_data failed for rsa %p", rsa); +@@ -262,12 +402,12 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, + else { + snprintf(prompt, sizeof(prompt), "Enter PIN for '%s': ", + si->token.label); +- if ((pin = read_passphrase(prompt, RP_ALLOW_EOF)) == NULL) { ++ if ((pin = read_passphrase(prompt, RP_ALLOW_EOF|RP_ALLOW_STDIN)) == NULL) { + debug("%s: no pin specified", __func__); + return (-1); /* bail out */ + } + } +- rv = provider->function_list->C_Login(si->session, type, (u_char *)pin, ++ rv = provider->module->function_list->C_Login(si->session, type, (u_char *)pin, + (pin != NULL) ? strlen(pin) : 0); + if (pin != NULL) + freezero(pin, strlen(pin)); +@@ -282,13 +422,14 @@ pkcs11_login_slot(struct pkcs11_provider *provider, struct pkcs11_slotinfo *si, + static int + pkcs11_login(struct pkcs11_key *k11, CK_USER_TYPE type) + { +- if (k11 == NULL || k11->provider == NULL || !k11->provider->valid) { ++ if (k11 == NULL || k11->provider == NULL || !k11->provider->valid || ++ k11->provider->module == NULL || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); + return (-1); + } + + return pkcs11_login_slot(k11->provider, +- &k11->provider->slotinfo[k11->slotidx], type); ++ &k11->provider->module->slotinfo[k11->slotidx], type); + } + + +@@ -304,13 +445,14 @@ pkcs11_check_obj_bool_attrib(struct pkcs11_key *k11, CK_OBJECT_HANDLE obj, + + *val = 0; + +- if (!k11->provider || !k11->provider->valid) { ++ if (!k11->provider || !k11->provider->valid || ++ !k11->provider->module || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); return (-1); } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + attr.type = type; + attr.pValue = &flag; +@@ -341,13 +483,14 @@ pkcs11_get_key(struct pkcs11_key *k11, CK_MECHANISM_TYPE mech_type) + int always_auth = 0; + int did_login = 0; + - if (!k11->provider || !k11->provider->valid) { -+ if (!k11->provider || !k11->provider->valid || !k11->provider->module -+ || !k11->provider->module->valid) { - error("no pkcs11 (valid) provider for rsa %p", rsa); ++ if (!k11->provider || !k11->provider->valid || ++ !k11->provider->module || !k11->provider->module->valid) { + error("no pkcs11 (valid) provider found"); return (-1); } + - f = k11->provider->function_list; - si = &k11->provider->slotinfo[k11->slotidx]; + f = k11->provider->module->function_list; + si = &k11->provider->module->slotinfo[k11->slotidx]; + if ((si->token.flags & CKF_LOGIN_REQUIRED) && !si->logged_in) { - if (!pkcs11_interactive) { - error("need pin entry%s", (si->token.flags & -@@ -311,7 +440,7 @@ pkcs11_rsa_private_decrypt(int flen, const u_char *from, u_char *to, RSA *rsa, + if (pkcs11_login(k11, CKU_USER) < 0) { +@@ -424,8 +567,8 @@ pkcs11_rsa_private_encrypt(int flen, const u_char *from, u_char *to, RSA *rsa, + return (-1); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + tlen = RSA_size(rsa); + + /* XXX handle CKR_BUFFER_TOO_SMALL */ +@@ -469,7 +612,7 @@ pkcs11_rsa_start_wrapper(void) /* redirect private key operations for rsa key to pkcs11 token */ static int pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - CK_ATTRIBUTE *keyid_attrib, RSA *rsa) + CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, RSA *rsa) { - struct pkcs11_key *k11; - const RSA_METHOD *def = RSA_get_default_method(); -@@ -326,6 +455,11 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, - k11->keyid = xmalloc(k11->keyid_len); - memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + struct pkcs11_key *k11; + +@@ -487,6 +630,12 @@ pkcs11_rsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + } + ++ if (label_attrib->ulValueLen > 0 ) { ++ k11->label = xmalloc(label_attrib->ulValueLen+1); ++ memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); ++ k11->label[label_attrib->ulValueLen] = 0; ++ } ++ + RSA_set_method(rsa, rsa_method); + RSA_set_ex_data(rsa, rsa_idx, k11); + return (0); +@@ -517,8 +666,8 @@ ecdsa_do_sign(const unsigned char *dgst, int dgst_len, const BIGNUM *inv, + return (NULL); + } + +- f = k11->provider->function_list; +- si = &k11->provider->slotinfo[k11->slotidx]; ++ f = k11->provider->module->function_list; ++ si = &k11->provider->module->slotinfo[k11->slotidx]; + + siglen = ECDSA_size(ec); + sig = xmalloc(siglen); +@@ -583,7 +732,7 @@ pkcs11_ecdsa_start_wrapper(void) + + static int + pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, +- CK_ATTRIBUTE *keyid_attrib, EC_KEY *ec) ++ CK_ATTRIBUTE *keyid_attrib, CK_ATTRIBUTE *label_attrib, EC_KEY *ec) + { + struct pkcs11_key *k11; + +@@ -599,6 +748,12 @@ pkcs11_ecdsa_wrap(struct pkcs11_provider *provider, CK_ULONG slotidx, + k11->keyid = xmalloc(k11->keyid_len); + memcpy(k11->keyid, keyid_attrib->pValue, k11->keyid_len); + ++ if (label_attrib->ulValueLen > 0 ) { ++ k11->label = xmalloc(label_attrib->ulValueLen+1); ++ memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); ++ k11->label[label_attrib->ulValueLen] = 0; ++ } ++ + EC_KEY_set_method(ec, ec_key_method); + EC_KEY_set_ex_data(ec, ec_key_idx, k11); + +@@ -635,8 +790,8 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, + CK_SESSION_HANDLE session; + int login_required, ret; + +- f = p->function_list; +- si = &p->slotinfo[slotidx]; ++ f = p->module->function_list; ++ si = &p->module->slotinfo[slotidx]; + + login_required = si->token.flags & CKF_LOGIN_REQUIRED; + +@@ -646,9 +801,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin, + error("pin required"); + return (-SSH_PKCS11_ERR_PIN_REQUIRED); + } +- if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| ++ if ((rv = f->C_OpenSession(p->module->slotlist[slotidx], CKF_RW_SESSION| + CKF_SERIAL_SESSION, NULL, NULL, &session)) != CKR_OK) { +- error("C_OpenSession failed: %lu", rv); ++ error("C_OpenSession failed for slot %lu: %lu", slotidx, rv); + return (-1); + } + if (login_required && pin != NULL && strlen(pin) != 0) { +@@ -684,7 +839,8 @@ static struct sshkey * + pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) + { +- CK_ATTRIBUTE key_attr[3]; ++ CK_ATTRIBUTE key_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -698,14 +854,15 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; +- key_attr[1].type = CKA_EC_POINT; +- key_attr[2].type = CKA_EC_PARAMS; ++ key_attr[1].type = CKA_LABEL; ++ key_attr[2].type = CKA_EC_POINT; ++ key_attr[3].type = CKA_EC_PARAMS; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); +@@ -717,18 +874,19 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * XXX assumes CKA_ID is always first. + */ + if (key_attr[1].ulValueLen == 0 || +- key_attr[2].ulValueLen == 0) { ++ key_attr[2].ulValueLen == 0 || ++ key_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); + } + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (key_attr[i].ulValueLen > 0) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + + /* retrieve ID, public point and curve parameters of EC key */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; +@@ -740,8 +898,8 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto fail; + } + +- attrp = key_attr[2].pValue; +- group = d2i_ECPKParameters(NULL, &attrp, key_attr[2].ulValueLen); ++ attrp = key_attr[3].pValue; ++ group = d2i_ECPKParameters(NULL, &attrp, key_attr[3].ulValueLen); + if (group == NULL) { + ossl_error("d2i_ECPKParameters failed"); + goto fail; +@@ -752,13 +910,13 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto fail; + } + +- if (key_attr[1].ulValueLen <= 2) { ++ if (key_attr[2].ulValueLen <= 2) { + error("CKA_EC_POINT too small"); + goto fail; + } + +- attrp = key_attr[1].pValue; +- octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[1].ulValueLen); ++ attrp = key_attr[2].pValue; ++ octet = d2i_ASN1_OCTET_STRING(NULL, &attrp, key_attr[2].ulValueLen); + if (octet == NULL) { + ossl_error("d2i_ASN1_OCTET_STRING failed"); + goto fail; +@@ -775,7 +933,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto fail; + } + +- if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], ec)) ++ if (pkcs11_ecdsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], ec)) + goto fail; + + key = sshkey_new(KEY_UNSPEC); +@@ -791,7 +949,7 @@ pkcs11_fetch_ecdsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + ec = NULL; /* now owned by key */ + + fail: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(key_attr[i].pValue); + if (ec) + EC_KEY_free(ec); +@@ -808,7 +966,8 @@ static struct sshkey * + pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj) + { +- CK_ATTRIBUTE key_attr[3]; ++ CK_ATTRIBUTE key_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -819,14 +978,15 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + + memset(&key_attr, 0, sizeof(key_attr)); + key_attr[0].type = CKA_ID; +- key_attr[1].type = CKA_MODULUS; +- key_attr[2].type = CKA_PUBLIC_EXPONENT; ++ key_attr[1].type = CKA_LABEL; ++ key_attr[2].type = CKA_MODULUS; ++ key_attr[3].type = CKA_PUBLIC_EXPONENT; + +- session = p->slotinfo[slotidx].session; +- f = p->function_list; ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return (NULL); +@@ -838,18 +998,19 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * XXX assumes CKA_ID is always first. + */ + if (key_attr[1].ulValueLen == 0 || +- key_attr[2].ulValueLen == 0) { ++ key_attr[2].ulValueLen == 0 || ++ key_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return (NULL); } -+ if (label_attrib->ulValueLen > 0 ) { -+ k11->label = xmalloc(label_attrib->ulValueLen+1); -+ memcpy(k11->label, label_attrib->pValue, label_attrib->ulValueLen); -+ k11->label[label_attrib->ulValueLen] = 0; -+ } - k11->orig_finish = def->finish; - memcpy(&k11->rsa_method, def, sizeof(k11->rsa_method)); - k11->rsa_method.name = "pkcs11"; -@@ -372,16 +506,16 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) - CK_SESSION_HANDLE session; - int login_required; + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (key_attr[i].ulValueLen > 0) + key_attr[i].pValue = xcalloc(1, key_attr[i].ulValueLen); + + /* retrieve ID, modulus and public exponent of RSA key */ +- rv = f->C_GetAttributeValue(session, *obj, key_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, key_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto fail; +@@ -861,8 +1022,8 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto fail; + } + +- rsa_n = BN_bin2bn(key_attr[1].pValue, key_attr[1].ulValueLen, NULL); +- rsa_e = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); ++ rsa_n = BN_bin2bn(key_attr[2].pValue, key_attr[2].ulValueLen, NULL); ++ rsa_e = BN_bin2bn(key_attr[3].pValue, key_attr[3].ulValueLen, NULL); + if (rsa_n == NULL || rsa_e == NULL) { + error("BN_bin2bn failed"); + goto fail; +@@ -871,7 +1032,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + fatal("%s: set key", __func__); + rsa_n = rsa_e = NULL; /* transferred */ + +- if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], rsa)) ++ if (pkcs11_rsa_wrap(p, slotidx, &key_attr[0], &key_attr[1], rsa)) + goto fail; + + key = sshkey_new(KEY_UNSPEC); +@@ -886,7 +1047,7 @@ pkcs11_fetch_rsa_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + rsa = NULL; /* now owned by key */ + + fail: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(key_attr[i].pValue); + RSA_free(rsa); + +@@ -897,7 +1058,8 @@ static int + pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + CK_OBJECT_HANDLE *obj, struct sshkey **keyp, char **labelp) + { +- CK_ATTRIBUTE cert_attr[3]; ++ CK_ATTRIBUTE cert_attr[4]; ++ int nattr = 4; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -921,14 +1083,15 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + + memset(&cert_attr, 0, sizeof(cert_attr)); + cert_attr[0].type = CKA_ID; +- cert_attr[1].type = CKA_SUBJECT; +- cert_attr[2].type = CKA_VALUE; ++ cert_attr[1].type = CKA_LABEL; ++ cert_attr[2].type = CKA_SUBJECT; ++ cert_attr[3].type = CKA_VALUE; + +- session = p->slotinfo[slotidx].session; - f = p->function_list; -- login_required = p->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED; ++ session = p->module->slotinfo[slotidx].session; + f = p->module->function_list; -+ login_required = p->module->slotinfo[slotidx].token.flags & CKF_LOGIN_REQUIRED; - if (pin && login_required && !strlen(pin)) { - error("pin required"); - return (-1); + + /* figure out size of the attributes */ +- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + return -1; +@@ -940,18 +1103,19 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + * XXX assumes CKA_ID is always first. + */ + if (cert_attr[1].ulValueLen == 0 || +- cert_attr[2].ulValueLen == 0) { ++ cert_attr[2].ulValueLen == 0 || ++ cert_attr[3].ulValueLen == 0) { + error("invalid attribute length"); + return -1; } -- if ((rv = f->C_OpenSession(p->slotlist[slotidx], CKF_RW_SESSION| -+ if ((rv = f->C_OpenSession(p->module->slotlist[slotidx], CKF_RW_SESSION| - CKF_SERIAL_SESSION, NULL, NULL, &session)) - != CKR_OK) { -- error("C_OpenSession failed: %lu", rv); -+ error("C_OpenSession failed for slot %lu: %lu", slotidx, rv); - return (-1); + + /* allocate buffers for attributes */ +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + if (cert_attr[i].ulValueLen > 0) + cert_attr[i].pValue = xcalloc(1, cert_attr[i].ulValueLen); + + /* retrieve ID, subject and value of certificate */ +- rv = f->C_GetAttributeValue(session, *obj, cert_attr, 3); ++ rv = f->C_GetAttributeValue(session, *obj, cert_attr, nattr); + if (rv != CKR_OK) { + error("C_GetAttributeValue failed: %lu", rv); + goto out; +@@ -965,8 +1129,8 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + subject = xstrdup("invalid subject"); + X509_NAME_free(x509_name); + +- cp = cert_attr[2].pValue; +- if ((x509 = d2i_X509(NULL, &cp, cert_attr[2].ulValueLen)) == NULL) { ++ cp = cert_attr[3].pValue; ++ if ((x509 = d2i_X509(NULL, &cp, cert_attr[3].ulValueLen)) == NULL) { + error("d2i_x509 failed"); + goto out; } - if (login_required && pin) { -@@ -393,9 +527,9 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) - error("C_CloseSession failed: %lu", rv); - return (-1); +@@ -986,7 +1150,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto out; } -- p->slotinfo[slotidx].logged_in = 1; -+ p->module->slotinfo[slotidx].logged_in = 1; - } -- p->slotinfo[slotidx].session = session; -+ p->module->slotinfo[slotidx].session = session; - return (0); - } -@@ -405,38 +539,62 @@ pkcs11_open_session(struct pkcs11_provider *p, CK_ULONG slotidx, char *pin) - * keysp points to an (possibly empty) array with *nkeys keys. - */ - static int pkcs11_fetch_keys_filter(struct pkcs11_provider *, CK_ULONG, -- CK_ATTRIBUTE [], CK_ATTRIBUTE [3], struct sshkey ***, int *) -+ CK_ATTRIBUTE [], size_t, CK_ATTRIBUTE [3], struct sshkey ***, int *) - __attribute__((__bounded__(__minbytes__,4, 3 * sizeof(CK_ATTRIBUTE)))); +- if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], rsa)) ++ if (pkcs11_rsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], rsa)) + goto out; + key = sshkey_new(KEY_UNSPEC); +@@ -1016,7 +1180,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto out; + } + +- if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], ec)) ++ if (pkcs11_ecdsa_wrap(p, slotidx, &cert_attr[0], &cert_attr[1], ec)) + goto out; + + key = sshkey_new(KEY_UNSPEC); +@@ -1036,7 +1200,7 @@ pkcs11_fetch_x509_pubkey(struct pkcs11_provider *p, CK_ULONG slotidx, + goto out; + } + out: +- for (i = 0; i < 3; i++) ++ for (i = 0; i < nattr; i++) + free(cert_attr[i].pValue); + X509_free(x509); + RSA_free(rsa); +@@ -1071,11 +1235,12 @@ have_rsa_key(const RSA *rsa) + */ static int - pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, -- struct sshkey ***keysp, int *nkeys) -+ struct sshkey ***keysp, int *nkeys, struct pkcs11_uri *uri) + pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, +- struct sshkey ***keysp, char ***labelsp, int *nkeys) ++ struct sshkey ***keysp, char ***labelsp, int *nkeys, struct pkcs11_uri *uri) { -+ size_t filter_size = 1; - CK_OBJECT_CLASS pubkey_class = CKO_PUBLIC_KEY; - CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE; - CK_ATTRIBUTE pubkey_filter[] = { -- { CKA_CLASS, NULL, sizeof(pubkey_class) } -+ { CKA_CLASS, NULL, sizeof(pubkey_class) }, -+ { CKA_ID, NULL, 0 }, -+ { CKA_LABEL, NULL, 0 } - }; - CK_ATTRIBUTE cert_filter[] = { -- { CKA_CLASS, NULL, sizeof(cert_class) } -+ { CKA_CLASS, NULL, sizeof(cert_class) }, -+ { CKA_ID, NULL, 0 }, -+ { CKA_LABEL, NULL, 0 } - }; - CK_ATTRIBUTE pubkey_attribs[] = { - { CKA_ID, NULL, 0 }, -+ { CKA_LABEL, NULL, 0 }, - { CKA_MODULUS, NULL, 0 }, - { CKA_PUBLIC_EXPONENT, NULL, 0 } - }; - CK_ATTRIBUTE cert_attribs[] = { - { CKA_ID, NULL, 0 }, -+ { CKA_LABEL, NULL, 0 }, - { CKA_SUBJECT, NULL, 0 }, - { CKA_VALUE, NULL, 0 } - }; - pubkey_filter[0].pValue = &pubkey_class; - cert_filter[0].pValue = &cert_class; + struct sshkey *key = NULL; + CK_OBJECT_CLASS key_class; +- CK_ATTRIBUTE key_attr[1]; ++ CK_ATTRIBUTE key_attr[3]; ++ int nattr = 1; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -1092,10 +1257,23 @@ pkcs11_fetch_certs(struct pkcs11_provider *p, CK_ULONG slotidx, + key_attr[0].pValue = &key_class; + key_attr[0].ulValueLen = sizeof(key_class); -- if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, pubkey_attribs, -- keysp, nkeys) < 0 || -- pkcs11_fetch_keys_filter(p, slotidx, cert_filter, cert_attribs, -- keysp, nkeys) < 0) +- session = p->slotinfo[slotidx].session; +- f = p->function_list; + if (uri->id != NULL) { -+ pubkey_filter[filter_size].pValue = uri->id; -+ pubkey_filter[filter_size].ulValueLen = uri->id_len; -+ cert_filter[filter_size].pValue = uri->id; -+ cert_filter[filter_size].ulValueLen = uri->id_len; -+ filter_size++; ++ key_attr[nattr].type = CKA_ID; ++ key_attr[nattr].pValue = uri->id; ++ key_attr[nattr].ulValueLen = uri->id_len; ++ nattr++; + } + if (uri->object != NULL) { -+ pubkey_filter[filter_size].pValue = uri->object; -+ pubkey_filter[filter_size].ulValueLen = strlen(uri->object); -+ pubkey_filter[filter_size].type = CKA_LABEL; -+ cert_filter[filter_size].pValue = uri->object; -+ cert_filter[filter_size].ulValueLen = strlen(uri->object); -+ cert_filter[filter_size].type = CKA_LABEL; -+ filter_size++; ++ key_attr[nattr].type = CKA_LABEL; ++ key_attr[nattr].pValue = uri->object; ++ key_attr[nattr].ulValueLen = strlen(uri->object); ++ nattr++; + } + -+ if (pkcs11_fetch_keys_filter(p, slotidx, pubkey_filter, filter_size, -+ pubkey_attribs, keysp, nkeys) < 0 || -+ pkcs11_fetch_keys_filter(p, slotidx, cert_filter, filter_size, -+ cert_attribs, keysp, nkeys) < 0) - return (-1); - return (0); - } -@@ -454,14 +612,15 @@ pkcs11_key_included(struct sshkey ***keysp, int *nkeys, struct sshkey *key) ++ session = p->module->slotinfo[slotidx].session; ++ f = p->module->function_list; +- rv = f->C_FindObjectsInit(session, key_attr, 1); ++ rv = f->C_FindObjectsInit(session, key_attr, nattr); + if (rv != CKR_OK) { + error("C_FindObjectsInit failed: %lu", rv); + goto fail; +@@ -1175,11 +1353,12 @@ fail: + */ static int - pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, -- CK_ATTRIBUTE filter[], CK_ATTRIBUTE attribs[3], -+ CK_ATTRIBUTE filter[], size_t filter_size, CK_ATTRIBUTE attribs[4], - struct sshkey ***keysp, int *nkeys) + pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, +- struct sshkey ***keysp, char ***labelsp, int *nkeys) ++ struct sshkey ***keysp, char ***labelsp, int *nkeys, struct pkcs11_uri *uri) { - struct sshkey *key; - RSA *rsa; - X509 *x509; -- EVP_PKEY *evp; -+ EVP_PKEY *evp = NULL; - int i; -+ int nattribs = 4; - const u_char *cp; - CK_RV rv; - CK_OBJECT_HANDLE obj; -@@ -470,16 +629,15 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, - CK_SESSION_HANDLE session; - CK_FUNCTION_LIST *f; + struct sshkey *key = NULL; + CK_OBJECT_CLASS key_class; +- CK_ATTRIBUTE key_attr[2]; ++ CK_ATTRIBUTE key_attr[3]; ++ int nattr = 1; + CK_SESSION_HANDLE session; + CK_FUNCTION_LIST *f = NULL; + CK_RV rv; +@@ -1195,10 +1374,23 @@ pkcs11_fetch_keys(struct pkcs11_provider *p, CK_ULONG slotidx, + key_attr[0].pValue = &key_class; + key_attr[0].ulValueLen = sizeof(key_class); -- f = p->function_list; - session = p->slotinfo[slotidx].session; -+ f = p->module->function_list; +- f = p->function_list; ++ if (uri->id != NULL) { ++ key_attr[nattr].type = CKA_ID; ++ key_attr[nattr].pValue = uri->id; ++ key_attr[nattr].ulValueLen = uri->id_len; ++ nattr++; ++ } ++ if (uri->object != NULL) { ++ key_attr[nattr].type = CKA_LABEL; ++ key_attr[nattr].pValue = uri->object; ++ key_attr[nattr].ulValueLen = strlen(uri->object); ++ nattr++; ++ } ++ + session = p->module->slotinfo[slotidx].session; - /* setup a filter the looks for public keys */ -- if ((rv = f->C_FindObjectsInit(session, filter, 1)) != CKR_OK) { -+ if ((rv = f->C_FindObjectsInit(session, filter, filter_size)) != CKR_OK) { ++ f = p->module->function_list; + +- rv = f->C_FindObjectsInit(session, key_attr, 1); ++ rv = f->C_FindObjectsInit(session, key_attr, nattr); + if (rv != CKR_OK) { error("C_FindObjectsInit failed: %lu", rv); - return (-1); - } - while (1) { -- /* XXX 3 attributes in attribs[] */ -- for (i = 0; i < 3; i++) { -+ for (i = 0; i < nattribs; i++) { - attribs[i].pValue = NULL; - attribs[i].ulValueLen = 0; - } -@@ -487,22 +645,22 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, - || nfound == 0) - break; - /* found a key, so figure out size of the attributes */ -- if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) -+ if ((rv = f->C_GetAttributeValue(session, obj, attribs, nattribs)) - != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); - continue; - } - /* -- * Allow CKA_ID (always first attribute) to be empty, but -- * ensure that none of the others are zero length. -+ * Allow CKA_ID (always first attribute) and CKA_LABEL (second) -+ * to be empty, but ensure that none of the others are zero length. - * XXX assumes CKA_ID is always first. - */ -- if (attribs[1].ulValueLen == 0 || -- attribs[2].ulValueLen == 0) { -+ if (attribs[2].ulValueLen == 0 || -+ attribs[3].ulValueLen == 0) { - continue; - } - /* allocate buffers for attributes */ -- for (i = 0; i < 3; i++) { -+ for (i = 0; i < nattribs; i++) { - if (attribs[i].ulValueLen > 0) { - attribs[i].pValue = xmalloc( - attribs[i].ulValueLen); -@@ -510,27 +668,27 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, - } + goto fail; +@@ -1466,16 +1658,10 @@ pkcs11_ecdsa_generate_private_key(struct pkcs11_provider *p, CK_ULONG slotidx, + } + #endif /* WITH_PKCS11_KEYGEN */ - /* -- * retrieve ID, modulus and public exponent of RSA key, -- * or ID, subject and value for certificates. -+ * retrieve ID, label, modulus and public exponent of RSA key, -+ * or ID, label, subject and value for certificates. - */ - rsa = NULL; -- if ((rv = f->C_GetAttributeValue(session, obj, attribs, 3)) -+ if ((rv = f->C_GetAttributeValue(session, obj, attribs, nattribs)) - != CKR_OK) { - error("C_GetAttributeValue failed: %lu", rv); -- } else if (attribs[1].type == CKA_MODULUS ) { -+ } else if (attribs[2].type == CKA_MODULUS ) { - if ((rsa = RSA_new()) == NULL) { - error("RSA_new failed"); - } else { -- rsa->n = BN_bin2bn(attribs[1].pValue, -- attribs[1].ulValueLen, NULL); -- rsa->e = BN_bin2bn(attribs[2].pValue, -+ rsa->n = BN_bin2bn(attribs[2].pValue, - attribs[2].ulValueLen, NULL); -+ rsa->e = BN_bin2bn(attribs[3].pValue, -+ attribs[3].ulValueLen, NULL); - } - } else { -- cp = attribs[2].pValue; -+ cp = attribs[3].pValue; - if ((x509 = X509_new()) == NULL) { - error("X509_new failed"); -- } else if (d2i_X509(&x509, &cp, attribs[2].ulValueLen) -+ } else if (d2i_X509(&x509, &cp, attribs[3].ulValueLen) - == NULL) { - error("d2i_X509 failed"); - } else if ((evp = X509_get_pubkey(x509)) == NULL || -@@ -546,9 +704,10 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, - error("RSAPublicKey_dup"); - } - X509_free(x509); -+ EVP_PKEY_free(evp); - } - if (rsa && rsa->n && rsa->e && -- pkcs11_rsa_wrap(p, slotidx, &attribs[0], rsa) == 0) { -+ pkcs11_rsa_wrap(p, slotidx, &attribs[0], &attribs[1], rsa) == 0) { - if ((key = sshkey_new(KEY_UNSPEC)) == NULL) - fatal("sshkey_new failed"); - key->rsa = rsa; -@@ -569,7 +728,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, - } else if (rsa) { - RSA_free(rsa); - } -- for (i = 0; i < 3; i++) -+ for (i = 0; i < nattribs; i++) - free(attribs[i].pValue); - } - if ((rv = f->C_FindObjectsFinal(session)) != CKR_OK) -@@ -581,126 +740,239 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx, - int - pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp) +-/* +- * register a new provider, fails if provider already exists. if +- * keyp is provided, fetch keys. +- */ + static int +-pkcs11_register_provider(char *provider_id, char *pin, +- struct sshkey ***keyp, char ***labelsp, +- struct pkcs11_provider **providerp, CK_ULONG user) ++pkcs11_initialize_provider(struct pkcs11_uri *uri, struct pkcs11_provider **providerp) { - int nkeys, need_finalize = 0; -- struct pkcs11_provider *p = NULL; -+ int rv; -+ struct pkcs11_uri *uri; -+ -+ debug("%s: called, provider_id = %s", __func__, provider_id); -+ -+ uri = pkcs11_uri_init(); -+ if (uri == NULL) -+ fatal("Failed to init PCKS#11 URI"); -+ -+ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && -+ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { -+ if (pkcs11_uri_parse(provider_id, uri) != 0) -+ fatal("Failed to parse PKCS#11 URI"); -+ } else { -+ uri->module_path = strdup(provider_id); -+ } -+ -+ rv = pkcs11_add_provider_by_uri(uri, pin, keyp); -+ pkcs11_uri_cleanup(uri); -+ return rv; -+} -+ -+struct pkcs11_provider * -+pkcs11_provider_initialize(struct pkcs11_uri *uri) -+{ + int need_finalize = 0; + int ret = -1; + struct pkcs11_provider *p = NULL; void *handle = NULL; - CK_RV (*getfunctionlist)(CK_FUNCTION_LIST **); - CK_RV rv; +@@ -1484,167 +1670,303 @@ pkcs11_register_provider(char *provider_id, char *pin, CK_FUNCTION_LIST *f = NULL; CK_TOKEN_INFO *token; CK_ULONG i; +- +- if (providerp == NULL) + char *provider_module = NULL; -+ struct pkcs11_provider *p; -+ struct pkcs11_module *m; - -- *keyp = NULL; -- if (pkcs11_provider_lookup(provider_id) != NULL) { -- debug("%s: provider already registered: %s", -- __func__, provider_id); ++ struct pkcs11_module *m = NULL; ++ + /* if no provider specified, fallback to p11-kit */ + if (uri->module_path == NULL) { +#ifdef PKCS11_DEFAULT_PROVIDER @@ -4342,15 +2518,26 @@ index 88c9d6e2..a29b4451 100644 +#else + error("%s: No module path provided", __func__); goto fail; +- *providerp = NULL; +- +- if (keyp != NULL) +- *keyp = NULL; +- if (labelsp != NULL) +- *labelsp = NULL; +#endif -+ } else ++ } else { + provider_module = strdup(uri->module_path); -+ ++ } + +- if (pkcs11_provider_lookup(provider_id) != NULL) { +- debug("%s: provider already registered: %s", +- __func__, provider_id); +- goto fail; + p = xcalloc(1, sizeof(*p)); + p->name = pkcs11_uri_get(uri); + + if ((m = pkcs11_provider_lookup_module(provider_module)) != NULL -+ && m->valid) { ++ && m->valid) { + debug("%s: provider module already initialized: %s", + __func__, provider_module); + free(provider_module); @@ -4360,14 +2547,15 @@ index 88c9d6e2..a29b4451 100644 + p->valid = 1; + TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); + p->refcount++; /* add to provider list */ -+ return p; ++ *providerp = p; ++ return 0; + } else { + m = xcalloc(1, sizeof(*m)); + p->module = m; + m->refcount++; } + - /* open shared pkcs11-libarary */ + /* open shared pkcs11-library */ - if ((handle = dlopen(provider_id, RTLD_NOW)) == NULL) { - error("dlopen %s failed: %s", provider_id, dlerror()); + if ((handle = dlopen(provider_module, RTLD_NOW)) == NULL) { @@ -4381,7 +2569,8 @@ index 88c9d6e2..a29b4451 100644 - p = xcalloc(1, sizeof(*p)); - p->name = xstrdup(provider_id); - p->handle = handle; -+ m->handle = handle; ++ ++ p->module->handle = handle; /* setup the pkcs11 callbacks */ if ((rv = (*getfunctionlist)(&f)) != CKR_OK) { error("C_GetFunctionList for provider %s failed: %lu", @@ -4442,6 +2631,7 @@ index 88c9d6e2..a29b4451 100644 debug("%s: provider %s returned no slots", __func__, - provider_id); + provider_module); + ret = -SSH_PKCS11_ERR_NO_SLOTS; goto fail; } - p->slotlist = xcalloc(p->nslots, sizeof(CK_SLOT_ID)); @@ -4455,14 +2645,13 @@ index 88c9d6e2..a29b4451 100644 goto fail; } - p->slotinfo = xcalloc(p->nslots, sizeof(struct pkcs11_slotinfo)); -+ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); -+ m->valid = 1; p->valid = 1; - nkeys = 0; - for (i = 0; i < p->nslots; i++) { - token = &p->slotinfo[i].token; - if ((rv = f->C_GetTokenInfo(p->slotlist[i], token)) -+ ++ m->slotinfo = xcalloc(m->nslots, sizeof(struct pkcs11_slotinfo)); ++ m->valid = 1; + for (i = 0; i < m->nslots; i++) { + token = &m->slotinfo[i].token; + if ((rv = f->C_GetTokenInfo(m->slotlist[i], token)) @@ -4470,18 +2659,13 @@ index 88c9d6e2..a29b4451 100644 error("C_GetTokenInfo for provider %s slot %lu " - "failed: %lu", provider_id, (unsigned long)i, rv); + "failed: %lu", provider_module, (unsigned long)i, rv); ++ token->flags = 0; continue; } - if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { -- debug2("%s: ignoring uninitialised token in " -- "provider %s slot %lu", __func__, -- provider_id, (unsigned long)i); - continue; - } - rmspace(token->label, sizeof(token->label)); - rmspace(token->manufacturerID, sizeof(token->manufacturerID)); - rmspace(token->model, sizeof(token->model)); - rmspace(token->serialNumber, sizeof(token->serialNumber)); ++ rmspace(token->label, sizeof(token->label)); ++ rmspace(token->manufacturerID, sizeof(token->manufacturerID)); ++ rmspace(token->model, sizeof(token->model)); ++ rmspace(token->serialNumber, sizeof(token->serialNumber)); + } + m->module_path = provider_module; + provider_module = NULL; @@ -4489,43 +2673,65 @@ index 88c9d6e2..a29b4451 100644 + /* insert unconditionally -- remove if there will be no keys later */ + TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); + p->refcount++; /* add to provider list */ -+ return p; ++ *providerp = p; ++ return 0; + +fail: + if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) + error("C_Finalize for provider %s failed: %lu", + provider_module, rv); + free(provider_module); -+ free(p); ++ if (m) { ++ free(m->slotlist); ++ free(m); ++ } ++ if (p) { ++ free(p->name); ++ free(p); ++ } + if (handle) + dlclose(handle); -+ return NULL; ++ return ret; +} + -+int -+pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin, struct sshkey ***keyp) ++/* ++ * register a new provider, fails if provider already exists. if ++ * keyp is provided, fetch keys. ++ */ ++static int ++pkcs11_register_provider_by_uri(struct pkcs11_uri *uri, char *pin, ++ struct sshkey ***keyp, char ***labelsp, struct pkcs11_provider **providerp, ++ CK_ULONG user) +{ + int nkeys; ++ int ret = -1; + struct pkcs11_provider *p = NULL; -+ CK_TOKEN_INFO *token; + CK_ULONG i; -+ char *provider_uri = pkcs11_uri_get(uri); ++ CK_TOKEN_INFO *token; ++ char *provider_uri = NULL; + -+ debug("%s: called, provider_uri = %s", __func__, provider_uri); ++ if (providerp == NULL) ++ goto fail; ++ *providerp = NULL; + -+ *keyp = NULL; -+ if ((p = pkcs11_provider_initialize(uri)) == NULL) { -+ debug("%s: failed to initialize provider: %s", -+ __func__, provider_uri); ++ if (keyp != NULL) ++ *keyp = NULL; ++ ++ if ((ret = pkcs11_initialize_provider(uri, &p)) != 0) { + goto fail; + } + ++ provider_uri = pkcs11_uri_get(uri); ++ if (pin == NULL && uri->pin != NULL) { ++ pin = uri->pin; ++ } + nkeys = 0; + for (i = 0; i < p->module->nslots; i++) { + token = &p->module->slotinfo[i].token; -+ if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { -+ debug2("%s: ignoring uninitialised token in " -+ "provider %s slot %lu", __func__, + if ((token->flags & CKF_TOKEN_INITIALIZED) == 0) { + debug2("%s: ignoring uninitialised token in " + "provider %s slot %lu", __func__, +- provider_id, (unsigned long)i); + provider_uri, (unsigned long)i); + continue; + } @@ -4542,73 +2748,226 @@ index 88c9d6e2..a29b4451 100644 + "manufacturerID (%s) specified by PKCS#11 URI in " + "slot %lu", __func__, + token->manufacturerID, (unsigned long)i); -+ continue; -+ } + continue; + } +- rmspace(token->label, sizeof(token->label)); +- rmspace(token->manufacturerID, sizeof(token->manufacturerID)); +- rmspace(token->model, sizeof(token->model)); +- rmspace(token->serialNumber, sizeof(token->serialNumber)); debug("provider %s slot %lu: label <%s> manufacturerID <%s> " "model <%s> serial <%s> flags 0x%lx", - provider_id, (unsigned long)i, + provider_uri, (unsigned long)i, token->label, token->manufacturerID, token->model, token->serialNumber, token->flags); -- /* open session, login with pin and retrieve public keys */ -- if (pkcs11_open_session(p, i, pin) == 0) -- pkcs11_fetch_keys(p, i, keyp, &nkeys); -+ /* open session if not yet opened, login with pin -+ * and retrieve public keys */ -+ if ((p->module->slotinfo[i].session != 0) || -+ pkcs11_open_session(p, i, pin) == 0) -+ pkcs11_fetch_keys(p, i, keyp, &nkeys, uri); - } - if (nkeys > 0) { -- TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); -- p->refcount++; /* add to provider list */ -+ free(provider_uri); - return (nkeys); + /* +- * open session, login with pin and retrieve public +- * keys (if keyp is provided) ++ * open session if not yet openend, login with pin and ++ * retrieve public keys (if keyp is provided) + */ +- if ((ret = pkcs11_open_session(p, i, pin, user)) != 0 || ++ if ((p->module->slotinfo[i].session != 0 || ++ (ret = pkcs11_open_session(p, i, pin, user)) != 0) && /* ??? */ + keyp == NULL) + continue; +- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); +- if (nkeys == 0 && !p->slotinfo[i].logged_in && ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ if (nkeys == 0 && !p->module->slotinfo[i].logged_in && + pkcs11_interactive) { + /* + * Some tokens require login before they will + * expose keys. + */ +- if (pkcs11_login_slot(p, &p->slotinfo[i], ++ debug3("%s: Trying to login as there were no keys found", ++ __func__); ++ if (pkcs11_login_slot(p, &p->module->slotinfo[i], + CKU_USER) < 0) { + error("login failed"); + continue; + } +- pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys); +- pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys); ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ } ++ if (nkeys == 0 && uri->object != NULL) { ++ debug3("%s: No keys found. Retrying without label (%s) ", ++ __func__, uri->object); ++ /* Try once more without the label filter */ ++ char *label = uri->object; ++ uri->object = NULL; /* XXX clone uri? */ ++ pkcs11_fetch_keys(p, i, keyp, labelsp, &nkeys, uri); ++ pkcs11_fetch_certs(p, i, keyp, labelsp, &nkeys, uri); ++ uri->object = label; + } } -- debug("%s: provider %s returned no keys", __func__, provider_id); -+ debug("%s: provider %s returned no keys", __func__, provider_uri); - /* don't add the provider, since it does not have any keys */ ++ pin = NULL; /* Will be cleaned up with URI */ + + /* now owned by caller */ + *providerp = p; + +- TAILQ_INSERT_TAIL(&pkcs11_providers, p, next); +- p->refcount++; /* add to provider list */ +- ++ free(provider_uri); + return (nkeys); fail: - if (need_finalize && (rv = f->C_Finalize(NULL)) != CKR_OK) - error("C_Finalize for provider %s failed: %lu", - provider_id, rv); if (p) { +- free(p->name); - free(p->slotlist); - free(p->slotinfo); - free(p); ++ TAILQ_REMOVE(&pkcs11_providers, p, next); + pkcs11_provider_unref(p); } - if (handle) - dlclose(handle); + if (ret > 0) + ret = -1; + return (ret); + } + +-/* +- * register a new provider and get number of keys hold by the token, +- * fails if provider already exists +- */ ++static int ++pkcs11_register_provider(char *provider_id, char *pin, struct sshkey ***keyp, ++ char ***labelsp, struct pkcs11_provider **providerp, CK_ULONG user) ++{ ++ struct pkcs11_uri *uri = NULL; ++ int r; ++ ++ debug("%s: called, provider_id = %s", __func__, provider_id); ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("failed to init PKCS#11 URI"); ++ ++ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { ++ if (pkcs11_uri_parse(provider_id, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI"); ++ } else { ++ uri->module_path = strdup(provider_id); ++ } ++ ++ r = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, providerp, user); ++ pkcs11_uri_cleanup(uri); ++ ++ return r; ++} ++ + int +-pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, +- char ***labelsp) ++pkcs11_add_provider_by_uri(struct pkcs11_uri *uri, char *pin, ++ struct sshkey ***keyp, char ***labelsp) + { +- struct pkcs11_provider *p = NULL; + int nkeys; ++ struct pkcs11_provider *p = NULL; ++ char *provider_uri = pkcs11_uri_get(uri); ++ ++ debug("%s: called, provider_uri = %s", __func__, provider_uri); + +- nkeys = pkcs11_register_provider(provider_id, pin, keyp, labelsp, +- &p, CKU_USER); ++ nkeys = pkcs11_register_provider_by_uri(uri, pin, keyp, labelsp, &p, CKU_USER); + + /* no keys found or some other error, de-register provider */ + if (nkeys <= 0 && p != NULL) { +@@ -1652,7 +1974,37 @@ pkcs11_add_provider(char *provider_id, char *pin, struct sshkey ***keyp, + } + if (nkeys == 0) + debug("%s: provider %s returned no keys", __func__, +- provider_id); ++ provider_uri); ++ + free(provider_uri); - return (-1); ++ return nkeys; ++} ++ ++/* ++ * register a new provider and get number of keys hold by the token, ++ * fails if provider already exists ++ */ ++int ++pkcs11_add_provider(char *provider_id, char *pin, ++ struct sshkey ***keyp, char ***labelsp) ++{ ++ struct pkcs11_uri *uri; ++ int nkeys; ++ ++ uri = pkcs11_uri_init(); ++ if (uri == NULL) ++ fatal("Failed to init PKCS#11 URI"); ++ ++ if (strlen(provider_id) >= strlen(PKCS11_URI_SCHEME) && ++ strncmp(provider_id, PKCS11_URI_SCHEME, strlen(PKCS11_URI_SCHEME)) == 0) { ++ if (pkcs11_uri_parse(provider_id, uri) != 0) ++ fatal("Failed to parse PKCS#11 URI"); ++ } else { ++ uri->module_path = strdup(provider_id); ++ } ++ ++ nkeys = pkcs11_add_provider_by_uri(uri, pin, keyp, labelsp); ++ pkcs11_uri_cleanup(uri); + + return (nkeys); } +@@ -1674,7 +2026,7 @@ pkcs11_gakp(char *provider_id, char *pin, unsigned int slotidx, char *label, + + if ((p = pkcs11_provider_lookup(provider_id)) != NULL) + debug("%s: provider \"%s\" available", __func__, provider_id); +- else if ((ret = pkcs11_register_provider(provider_id, pin, NULL, NULL, ++ else if ((rv = pkcs11_register_provider(provider_id, pin, NULL, NULL, + &p, CKU_SO)) < 0) { + debug("%s: could not register provider %s", __func__, + provider_id); +@@ -1746,8 +2098,8 @@ pkcs11_destroy_keypair(char *provider_id, char *pin, unsigned long slotidx, + if ((p = pkcs11_provider_lookup(provider_id)) != NULL) { + debug("%s: using provider \"%s\"", __func__, provider_id); +- } else if (pkcs11_register_provider(provider_id, pin, NULL, NULL, &p, +- CKU_SO) < 0) { ++ } else if ((rv = pkcs11_register_provider(provider_id, pin, NULL, NULL, ++ &p, CKU_SO)) < 0) { + debug("%s: could not register provider %s", __func__, + provider_id); + goto out; diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h -index 0ced74f2..c63a88f6 100644 +index 81f1d7c5..feaf74de 100644 --- a/ssh-pkcs11.h +++ b/ssh-pkcs11.h -@@ -14,10 +14,15 @@ - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -+ +@@ -22,10 +22,14 @@ + #define SSH_PKCS11_ERR_PIN_REQUIRED 4 + #define SSH_PKCS11_ERR_PIN_LOCKED 5 + +#include "ssh-pkcs11-uri.h" + int pkcs11_init(int); void pkcs11_terminate(void); - int pkcs11_add_provider(char *, char *, struct sshkey ***); -+int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***); + int pkcs11_add_provider(char *, char *, struct sshkey ***, char ***); ++int pkcs11_add_provider_by_uri(struct pkcs11_uri *, char *, struct sshkey ***, char ***); int pkcs11_del_provider(char *); +int pkcs11_uri_write(const struct sshkey *, FILE *); - - #if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11) - #undef ENABLE_PKCS11 + #ifdef WITH_PKCS11_KEYGEN + struct sshkey * + pkcs11_gakp(char *, char *, unsigned int, char *, unsigned int, diff --git a/ssh.c b/ssh.c -index d3619fe2..180eb2e0 100644 +index 15aee569..976844cb 100644 --- a/ssh.c +++ b/ssh.c -@@ -769,6 +769,14 @@ main(int ac, char **av) +@@ -795,6 +795,14 @@ main(int ac, char **av) options.gss_deleg_creds = 1; break; case 'i': @@ -4621,9 +2980,17 @@ index d3619fe2..180eb2e0 100644 + } +#endif p = tilde_expand_filename(optarg, getuid()); - if (stat(p, &st) < 0) + if (stat(p, &st) == -1) fprintf(stderr, "Warning: Identity file %s " -@@ -1999,6 +2007,45 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) +@@ -1603,6 +1611,7 @@ main(int ac, char **av) + free(options.certificate_files[i]); + options.certificate_files[i] = NULL; + } ++ pkcs11_terminate(); + + skip_connect: + exit_status = ssh_session2(ssh, pw); +@@ -2076,6 +2085,45 @@ ssh_session2(struct ssh *ssh, struct passwd *pw) options.escape_char : SSH_ESCAPECHAR_NONE, id); } @@ -4639,7 +3006,7 @@ index d3619fe2..180eb2e0 100644 + debug("identity file '%s' from pkcs#11", pkcs11_uri); + uri = pkcs11_uri_init(); + if (uri == NULL) -+ fatal("Failed to init PCKS#11 URI"); ++ fatal("Failed to init PKCS#11 URI"); + + if (pkcs11_uri_parse(pkcs11_uri, uri) != 0) + fatal("Failed to parse PKCS#11 URI %s", pkcs11_uri); @@ -4649,7 +3016,7 @@ index d3619fe2..180eb2e0 100644 + uri->module_path = strdup(options.pkcs11_provider); + + if (options.num_identity_files < SSH_MAX_IDENTITY_FILES && -+ (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys)) > 0) { ++ (nkeys = pkcs11_add_provider_by_uri(uri, NULL, &keys, NULL)) > 0) { + for (i = 0; i < nkeys; i++) { + if (*n_ids >= SSH_MAX_IDENTITY_FILES) { + sshkey_free(keys[i]); @@ -4669,18 +3036,19 @@ index d3619fe2..180eb2e0 100644 /* Loads all IdentityFile and CertificateFile keys */ static void load_public_identity_files(struct passwd *pw) -@@ -2011,10 +2058,6 @@ load_public_identity_files(struct passwd *pw) +@@ -2090,11 +2138,6 @@ load_public_identity_files(struct passwd *pw) char *certificate_files[SSH_MAX_CERTIFICATE_FILES]; struct sshkey *certificates[SSH_MAX_CERTIFICATE_FILES]; int certificate_file_userprovided[SSH_MAX_CERTIFICATE_FILES]; -#ifdef ENABLE_PKCS11 -- struct sshkey **keys; +- struct sshkey **keys = NULL; +- char **comments = NULL; - int nkeys; -#endif /* PKCS11 */ n_ids = n_certs = 0; memset(identity_files, 0, sizeof(identity_files)); -@@ -2023,32 +2066,46 @@ load_public_identity_files(struct passwd *pw) +@@ -2107,33 +2150,46 @@ load_public_identity_files(struct passwd *pw) sizeof(certificate_file_userprovided)); #ifdef ENABLE_PKCS11 @@ -4688,18 +3056,19 @@ index d3619fe2..180eb2e0 100644 - options.num_identity_files < SSH_MAX_IDENTITY_FILES && - (pkcs11_init(!options.batch_mode) == 0) && - (nkeys = pkcs11_add_provider(options.pkcs11_provider, NULL, -- &keys)) > 0) { +- &keys, &comments)) > 0) { - for (i = 0; i < nkeys; i++) { - if (n_ids >= SSH_MAX_IDENTITY_FILES) { - sshkey_free(keys[i]); +- free(comments[i]); - continue; - } - identity_keys[n_ids] = keys[i]; -- identity_files[n_ids] = -- xstrdup(options.pkcs11_provider); /* XXX */ +- identity_files[n_ids] = comments[i]; /* transferred */ - n_ids++; - } - free(keys); +- free(comments); + /* handle fallback from PKCS11Provider option */ + pkcs11_init(!options.batch_mode); + @@ -4708,7 +3077,7 @@ index d3619fe2..180eb2e0 100644 + + uri = pkcs11_uri_init(); + if (uri == NULL) -+ fatal("Failed to init PCKS#11 URI"); ++ fatal("Failed to init PKCS#11 URI"); + + /* Construct simple PKCS#11 URI to simplify access */ + uri->module_path = strdup(options.pkcs11_provider); @@ -4742,14 +3111,14 @@ index d3619fe2..180eb2e0 100644 + } +#endif /* ENABLE_PKCS11 */ + cp = tilde_expand_filename(name, getuid()); - filename = percent_expand(cp, "d", pw->pw_dir, - "u", pw->pw_name, "l", thishost, "h", host, - "r", options.user, (char *)NULL); + filename = default_client_percent_expand(cp, + pw->pw_dir, host, options.user, pw->pw_name); + free(cp); diff --git a/ssh_config.5 b/ssh_config.5 -index 71705cab..e0266609 100644 +index 06a32d31..4b2763bd 100644 --- a/ssh_config.5 +++ b/ssh_config.5 -@@ -919,6 +919,19 @@ may also be used in conjunction with +@@ -986,6 +986,21 @@ may also be used in conjunction with .Cm CertificateFile in order to provide any certificate also needed for authentication with the identity. @@ -4763,8 +3132,10 @@ index 71705cab..e0266609 100644 +.Cm manufacturer , +.Cm object , +.Cm token -+and query argument ++and query arguments +.Cm module-path ++and ++.Cm pin-value +). The URI can not be in quotes. .It Cm IgnoreUnknown Specifies a pattern-list of unknown options to be ignored if they are diff --git a/openssh-8.2p1-visibility.patch b/openssh-8.2p1-visibility.patch new file mode 100644 index 0000000000000000000000000000000000000000..89c35ef64de14194be1c4622c3cf77d3f98dcb6a --- /dev/null +++ b/openssh-8.2p1-visibility.patch @@ -0,0 +1,40 @@ +diff --git a/regress/misc/sk-dummy/sk-dummy.c b/regress/misc/sk-dummy/sk-dummy.c +index dca158de..afdcb1d2 100644 +--- a/regress/misc/sk-dummy/sk-dummy.c ++++ b/regress/misc/sk-dummy/sk-dummy.c +@@ -71,7 +71,7 @@ skdebug(const char *func, const char *fmt, ...) + #endif + } + +-uint32_t ++uint32_t __attribute__((visibility("default"))) + sk_api_version(void) + { + return SSH_SK_VERSION_MAJOR; +@@ -220,7 +220,7 @@ check_options(struct sk_option **options) + return 0; + } + +-int ++int __attribute__((visibility("default"))) + sk_enroll(uint32_t alg, const uint8_t *challenge, size_t challenge_len, + const char *application, uint8_t flags, const char *pin, + struct sk_option **options, struct sk_enroll_response **enroll_response) +@@ -467,7 +467,7 @@ sig_ed25519(const uint8_t *message, size_t message_len, + return ret; + } + +-int ++int __attribute__((visibility("default"))) + sk_sign(uint32_t alg, const uint8_t *data, size_t datalen, + const char *application, const uint8_t *key_handle, size_t key_handle_len, + uint8_t flags, const char *pin, struct sk_option **options, +@@ -518,7 +518,7 @@ sk_sign(uint32_t alg, const uint8_t *message, size_t message_len, + return ret; + } + +-int ++int __attribute__((visibility("default"))) + sk_load_resident_keys(const char *pin, struct sk_option **options, + struct sk_resident_key ***rks, size_t *nrks) + { diff --git a/openssh-8.3p1.tar.gz b/openssh-8.3p1.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5e94fbfd4a08bfcfe07921572f0df6cbe05e7e1c Binary files /dev/null and b/openssh-8.3p1.tar.gz differ diff --git a/openssh-8.3p1.tar.gz.asc b/openssh-8.3p1.tar.gz.asc new file mode 100644 index 0000000000000000000000000000000000000000..183d7429187234b77a1dda8abfdc3d02ee2cb3e3 --- /dev/null +++ b/openssh-8.3p1.tar.gz.asc @@ -0,0 +1,14 @@ +-----BEGIN PGP SIGNATURE----- + +iQHDBAABCgAdFiEEWcIRjtIG2SfmZ+vj0+X1a22SDTAFAl7N2TQACgkQ0+X1a22S +DTCXbAx/eycNNXxdVK3JtDQBUuSyup/eXeiuAdfTb77dKhdInk6ivaaKtVZ+3rlu +eEUwAY2Bf/majUUigI5OI/niODMqbYWBBDKRudQlDSGfH8XnRge6dRjIWXU6XvZP +MJpxVZWRorjnuCArWemlJ5QFxSds938Ae+7MFkveQ59UpRDeslYiI6twCXjRiZEL +e8lBfsfZqcOLO8KLVRvDx6sqD8EXlak8fhdjmjKdbvA4oWHLcwUcuaNT/o5I2ZWn +m2sOQcuhwt3+jm+f9SQKLURHcmGC6Hu5YXBq4+Ut7P9Qc9lAf76SDDnsrRQ8pv+Z +tLsXBO+bNe3tSkRbG/AQQRZtGEzlhM8KPyQ6oA0JqlN4Wb5XMWYFyYyJTwJ/95ZI +dluMmpwQTRVQGUNU7kVNe04TwRl+8APqvcnE3/i7MDm6EG5BHGcAneRmZfvt209F +z8yGtKQKCvZm5Rn9V0/Gm3+pq5O2sie90CPW9ebyPsajzQlrYBQPoJ1aQ+Ue4QE6 +gee5eO3TZOJJ3peTqjihGUtpKH+21w== +=lhX0 +-----END PGP SIGNATURE----- diff --git a/openssh-fix-typo-that-prevented-detection-of-Linux-V.patch b/openssh-fix-typo-that-prevented-detection-of-Linux-V.patch deleted file mode 100644 index 689fcb3630581d6a0a610f2372a5990d8d4f37a1..0000000000000000000000000000000000000000 --- a/openssh-fix-typo-that-prevented-detection-of-Linux-V.patch +++ /dev/null @@ -1,25 +0,0 @@ -From be8fcc621cfcec59a521f9a2929c98a89e5e9136 Mon Sep 17 00:00:00 2001 -From: hexiaowen -Date: Mon, 15 Jul 2019 21:25:42 +0800 -Subject: [PATCH] openssh: fix typo that prevented detection of Linux VRF - ---- - configure.ac | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/configure.ac b/configure.ac -index ed7a6bb..671819d 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -849,7 +849,7 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) - AC_DEFINE([SYS_RDOMAIN_LINUX], [1], - [Support routing domains using Linux VRF]), [], [ - #ifdef HAVE_SYS_TYPES_H --# include -+# include - #endif - ]) - AC_CHECK_HEADERS([linux/seccomp.h linux/filter.h linux/audit.h], [], --- -1.8.3.1 - diff --git a/openssh.spec b/openssh.spec index 44c30109ce0f9704134c171ed8cb1109c6cda3e2..caf7702d1a0d86166352ed9ec7660b1c14385074 100644 --- a/openssh.spec +++ b/openssh.spec @@ -1,170 +1,175 @@ %global gtk2 1 %global pie 1 + # Add option to build without GTK2 for older platforms with only GTK+. # rpm -ba|--rebuild --define 'no_gtk2 1' %{?no_gtk2:%global gtk2 0} -%global pam_ssh_agent_rel 5 - %global sshd_uid 74 -Name: openssh -Version: 7.8p1 -Release: 9 -URL: https://www.openssh.com/portable.html -License: BSD -Summary: An open source implementation of SSH protocol version 2 - -Source0: https://ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz -Source1: https://ftp://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc -Source2: sshd.pam -Source3: DJM-GPG-KEY.gpg -Source4: https://prdownloads.sourceforge.net/pamsshagentauth/pam_ssh_agent_auth/pam_ssh_agent_auth-0.10.3.tar.bz2 -Source5: pam_ssh_agent-rmheaders -Source6: ssh-keycat.pam -Source7: sshd.sysconfig -Source9: sshd@.service -Source10: sshd.socket -Source11: sshd.service -Source12: sshd-keygen@.service -Source13: sshd-keygen -Source14: sshd.tmpfiles -Source15: sshd-keygen.target - -Patch0: openssh-6.7p1-coverity.patch -#https://bugzilla.redhat.com/show_bug.cgi?id=735889 -Patch1: openssh-7.3p1-openssl-1.1.0.patch -# https://bugzilla.redhat.com/show_bug.cgi?id=1171248 -Patch2: openssh-7.6p1-audit.patch -Patch3: openssh-7.1p2-audit-race-condition.patch -Patch4: pam_ssh_agent_auth-0.9.3-build.patch -Patch5: pam_ssh_agent_auth-0.10.3-seteuid.patch -Patch6: pam_ssh_agent_auth-0.9.2-visibility.patch -Patch7: pam_ssh_agent_auth-0.9.3-agent_structure.patch -Patch8: pam_ssh_agent_auth-0.10.2-compat.patch -Patch9: pam_ssh_agent_auth-0.10.2-dereference.patch -Patch10: openssh-7.8p1-role-mls.patch -#https://bugzilla.redhat.com/show_bug.cgi?id=781634 -Patch11: openssh-6.6p1-privsep-selinux.patch -Patch12: openssh-6.7p1-ldap.patch -Patch13: openssh-6.6p1-keycat.patch -Patch14: openssh-6.6p1-allow-ip-opts.patch -Patch15: openssh-6.6p1-keyperm.patch -Patch16: openssh-5.9p1-ipv6man.patch -Patch17: openssh-5.8p2-sigpipe.patch -Patch18: openssh-7.2p2-x11.patch -Patch19: openssh-7.7p1-fips.patch -Patch20: openssh-5.1p1-askpass-progress.patch -#https://bugzilla.redhat.com/show_bug.cgi?id=198332 -Patch21: openssh-4.3p2-askpass-grab-info.patch -#patch from redhat -Patch22: openssh-7.7p1.patch -Patch23: openssh-6.2p1-vendor.patch -Patch24: openssh-7.8p1-UsePAM-warning.patch -Patch25: openssh-6.3p1-ctr-evp-fast.patch -Patch26: openssh-6.6p1-ctr-cavstest.patch -Patch27: openssh-6.7p1-kdf-cavs.patch -Patch28: openssh-7.8p1-gsskex.patch -Patch29: openssh-6.6p1-force_krb.patch -Patch30: openssh-6.6p1-GSSAPIEnablek5users.patch -# from https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=765655 -Patch31: openssh-7.1p1-gssapi-documentation.patch -Patch32: openssh-7.7p1-gssapi-new-unique.patch -Patch33: openssh-7.2p2-k5login_directory.patch -Patch34: openssh-7.5p1-gssapi-kex-with-ec.patch -Patch35: openssh-6.1p1-gssapi-canohost.patch -Patch36: openssh-6.6p1-kuserok.patch -Patch37: openssh-6.4p1-fromto-remote.patch -Patch38: openssh-6.6.1p1-selinux-contexts.patch -Patch39: openssh-6.6.1p1-log-in-chroot.patch -Patch40: openssh-6.6.1p1-scp-non-existing-directory.patch -Patch41: openssh-7.8p1-ip-port-config-parser.patch -Patch42: openssh-6.8p1-sshdT-output.patch -Patch43: openssh-6.7p1-sftp-force-permission.patch -Patch44: openssh-6.9p1-permit-root-login.patch -Patch45: openssh-7.0p1-gssKexAlgorithms.patch -Patch46: openssh-7.2p2-s390-closefrom.patch -Patch47: openssh-7.3p1-x11-max-displays.patch -Patch48: openssh-7.4p1-systemd.patch -Patch49: openssh-7.6p1-cleanup-selinux.patch -Patch50: openssh-7.5p1-sandbox.patch -Patch51: openssh-7.6p1-pkcs11-uri.patch -Patch52: openssh-7.6p1-pkcs11-ecdsa.patch -Patch53: openssh-7.8p1-scp-ipv6.patch -Patch54: Initial-len-for-the-fmt-NULL-case.patch -Patch55: upstream-fix-build-with-DEBUG_PK-enabled.patch -Patch56: upstream-fix-misplaced-parenthesis-inside-if-clause..patch -Patch57: delete-the-correct-thing-kexfuzz-binary.patch -Patch58: upstream-When-choosing-a-prime-from-the-moduli-file-.patch -Patch59: upstream-fix-ssh-Q-sig-to-show-correct-signature-alg.patch -Patch60: in-pick_salt-avoid-dereference-of-NULL-passwords.patch -Patch61: check-for-NULL-return-from-shadow_pw.patch -Patch62: check-pw_passwd-NULL-here-too.patch -Patch63: upstream-typo-in-plain-RSA-algorithm-counterpart-nam.patch -Patch64: upstream-correct-local-variable-name-from-yawang-AT-.patch -Patch65: upstream-typo-in-error-message-caught-by-Debian-lint.patch -Patch66: upstream-fix-bug-in-HostbasedAcceptedKeyTypes-and.patch -Patch67: upstream-fix-bug-in-client-that-was-keeping-a-redund.patch -Patch68: upstream-disallow-empty-incoming-filename-or-ones-th.patch -Patch69: upstream-make-grandparent-parent-child-sshbuf-chains.patch -Patch70: Move-RANDOM_SEED_SIZE-outside-ifdef.patch -Patch71: upstream-don-t-truncate-user-or-host-name-in-user-ho.patch -Patch72: upstream-don-t-attempt-to-connect-to-empty-SSH_AUTH_.patch -Patch73: upstream-only-consider-the-ext-info-c-extension-duri.patch -Patch74: upstream-fix-memory-leak-of-ciphercontext-when-rekey.patch -Patch75: upstream-Fix-BN_is_prime_-calls-in-SSH-the-API-retur.patch -Patch76: upstream-Always-initialize-2nd-arg-to-hpdelim2.-It-p.patch -Patch77: Cygwin-Change-service-name-to-cygsshd.patch -Patch78: openssh-fix-typo-that-prevented-detection-of-Linux-V.patch -Patch79: CVE-2019-6109-1.patch -Patch80: CVE-2019-6109-2.patch -Patch81: CVE-2019-6111-1.patch -Patch82: CVE-2019-6111-2.patch -Patch83: CVE-2019-16905.patch -Patch84: upstream-fix-sshd-T-without-C.patch -Patch85: bugfix-sftp-when-parse_user_host_path-empty-path-should-be-allowed.patch -Patch86: bugfix-openssh-6.6p1-log-usepam-no.patch -Patch87: bugfix-openssh-add-option-check-username-splash.patch -Patch88: feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch -Patch89: bugfix-supply-callback-to-PEM-read-bio-PrivateKey.patch -Patch90: bugfix-openssh-fix-sftpserver.patch -Patch91: bugfix-CVE-2018-15919.patch -Patch92: CVE-2020-12062-1.patch -Patch93: CVE-2020-12062-2.patch -Patch94: upstream-expose-vasnmprintf.patch - -Requires: /sbin/nologin libselinux >= 2.3-5 audit-libs >= 1.0.8 -Requires: fipscheck-lib >= 1.3.0 -Requires(pre): /usr/sbin/useradd -Requires(pre): shadow-utils -Requires: pam >= 1.0.1-3 -Requires: fipscheck-lib >= 1.3.0 -Requires: crypto-policies >= 20180306-1 - -Obsoletes: openssh-clients-fips openssh-server-fips openssh-server-sysvinit openssh-cavs openssh-askpass-gnome -Obsoletes: openssh-clients openssh-server openssh-ldap openssh-keycat openssh-askpass -Provides: openssh-clients openssh-server openssh-ldap openssh-keycat openssh-askpass openssh-cavs openssh-askpass-gnome - -BuildRequires: gtk2-devel libX11-devel openldap-devel autoconf automake perl-interpreter perl-generators -BuildRequires: zlib-devel audit-libs-devel >= 2.0.5 util-linux groff pam-devel fipscheck-devel >= 1.3.0 -BuildRequires: openssl-devel >= 0.9.8j perl-podlators systemd-devel gcc p11-kit-devel krb5-devel -BuildRequires: libedit-devel ncurses-devel libselinux-devel >= 2.3-5 audit-libs >= 1.0.8 xauth gnupg2 - +Name: openssh +Version: 8.3p1 +Release: 1 +URL: http://www.openssh.com/portable.html +License: BSD +Summary: An open source implementation of SSH protocol version 2 + +Source0: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz +Source1: https://ftp.openbsd.org/pub/OpenBSD/OpenSSH/portable/openssh-%{version}.tar.gz.asc +Source2: sshd.pam +Source4: http://prdownloads.sourceforge.net/pamsshagentauth/pam_ssh_agent_auth/pam_ssh_agent_auth-0.10.3.tar.bz2 +Source5: pam_ssh_agent-rmheaders +Source6: ssh-keycat.pam +Source7: sshd.sysconfig +Source9: sshd@.service +Source10: sshd.socket +Source11: sshd.service +Source12: sshd-keygen@.service +Source13: sshd-keygen +Source14: sshd.tmpfiles +Source15: sshd-keygen.target +Patch100: openssh-6.7p1-coverity.patch +Patch200: openssh-7.6p1-audit.patch +Patch201: openssh-7.1p2-audit-race-condition.patch +Patch300: pam_ssh_agent_auth-0.9.3-build.patch +Patch301: pam_ssh_agent_auth-0.10.3-seteuid.patch +Patch302: pam_ssh_agent_auth-0.9.2-visibility.patch +Patch305: pam_ssh_agent_auth-0.9.3-agent_structure.patch +Patch306: pam_ssh_agent_auth-0.10.2-compat.patch +Patch307: pam_ssh_agent_auth-0.10.2-dereference.patch +Patch400: openssh-7.8p1-role-mls.patch +Patch404: openssh-6.6p1-privsep-selinux.patch +Patch501: openssh-6.7p1-ldap.patch +Patch502: openssh-6.6p1-keycat.patch +Patch601: openssh-6.6p1-allow-ip-opts.patch +Patch604: openssh-6.6p1-keyperm.patch +Patch606: openssh-5.9p1-ipv6man.patch +Patch607: openssh-5.8p2-sigpipe.patch +Patch609: openssh-7.2p2-x11.patch +Patch700: openssh-7.7p1-fips.patch +Patch702: openssh-5.1p1-askpass-progress.patch +Patch703: openssh-4.3p2-askpass-grab-info.patch +Patch707: openssh-7.7p1.patch +Patch711: openssh-7.8p1-UsePAM-warning.patch +Patch712: openssh-6.3p1-ctr-evp-fast.patch +Patch713: openssh-6.6p1-ctr-cavstest.patch +Patch714: openssh-6.7p1-kdf-cavs.patch +Patch800: openssh-8.0p1-gssapi-keyex.patch +Patch801: openssh-6.6p1-force_krb.patch +Patch802: openssh-6.6p1-GSSAPIEnablek5users.patch +Patch804: openssh-7.7p1-gssapi-new-unique.patch +Patch805: openssh-7.2p2-k5login_directory.patch +Patch901: openssh-6.6p1-kuserok.patch +Patch906: openssh-6.4p1-fromto-remote.patch +Patch916: openssh-6.6.1p1-selinux-contexts.patch +Patch918: openssh-6.6.1p1-log-in-chroot.patch +Patch919: openssh-6.6.1p1-scp-non-existing-directory.patch +Patch922: openssh-6.8p1-sshdT-output.patch +Patch926: openssh-6.7p1-sftp-force-permission.patch +Patch939: openssh-7.2p2-s390-closefrom.patch +Patch944: openssh-7.3p1-x11-max-displays.patch +Patch948: openssh-7.4p1-systemd.patch +Patch949: openssh-7.6p1-cleanup-selinux.patch +Patch950: openssh-7.5p1-sandbox.patch +Patch951: openssh-8.0p1-pkcs11-uri.patch +Patch953: openssh-7.8p1-scp-ipv6.patch +Patch958: openssh-7.9p1-ssh-copy-id.patch +Patch962: openssh-8.0p1-crypto-policies.patch +Patch963: openssh-8.0p1-openssl-evp.patch +Patch964: openssh-8.0p1-openssl-kdf.patch +Patch965: openssh-8.2p1-visibility.patch + +Patch9004: bugfix-sftp-when-parse_user_host_path-empty-path-should-be-allowed.patch +Patch9005: bugfix-openssh-6.6p1-log-usepam-no.patch +Patch9006: bugfix-openssh-add-option-check-username-splash.patch +Patch9007: feature-openssh-7.4-hima-sftpserver-oom-and-fix.patch +Patch9009: bugfix-openssh-fix-sftpserver.patch +Patch9010: bugfix-debug3-to-verbose-in-command.patch +Patch9011: set-sshd-config.patch + +Requires: /sbin/nologin +Requires: libselinux >= 2.3-5 audit-libs >= 1.0.8 +Requires: openssh-server = %{version}-%{release} + +BuildRequires: gtk2-devel libX11-devel openldap-devel autoconf automake perl-interpreter perl-generators +BuildRequires: zlib-devel audit-libs-devel >= 2.0.5 util-linux groff pam-devel fipscheck-devel >= 1.3.0 +BuildRequires: openssl-devel >= 0.9.8j perl-podlators systemd-devel gcc p11-kit-devel krb5-devel +BuildRequires: libedit-devel ncurses-devel libselinux-devel >= 2.3-5 audit-libs >= 1.0.8 xauth gnupg2 + +Recommends: p11-kit + +%package clients +Summary: An open source SSH client applications +Requires: openssh = %{version}-%{release} +Requires: fipscheck-lib%{_isa} >= 1.3.0 +Requires: crypto-policies >= 20180306-1 + +%package server +Summary: An open source SSH server daemon +Requires: openssh = %{version}-%{release} +Requires(pre): shadow +Requires: pam >= 1.0.1-3 +Requires: fipscheck-lib%{_isa} >= 1.3.0 +Requires: crypto-policies >= 20180306-1 %{?systemd_requires} -Recommends: p11-kit +%package ldap +Summary: A LDAP support for open source SSH server daemon +Requires: openssh = %{version}-%{release} + +%package keycat +Summary: A mls keycat backend for openssh +Requires: openssh = %{version}-%{release} + +%package askpass +Summary: A passphrase dialog for OpenSSH and X +Requires: openssh = %{version}-%{release} +Obsoletes: openssh-askpass-gnome +Provides: openssh-askpass-gnome + +%package cavs +Summary: CAVS tests for FIPS validation +Requires: openssh = %{version}-%{release} + +%package -n pam_ssh_agent_auth +Summary: PAM module for authentication with ssh-agent +Version: 0.10.3 +Release: 9.1 +License: BSD %description -penSSH is the premier connectivity tool for remote login with the SSH protocol. \ +OpenSSH is the premier connectivity tool for remote login with the SSH protocol. \ It encrypts all traffic to eliminate eavesdropping, connection hijacking, and \ other attacks. In addition, OpenSSH provides a large suite of secure tunneling \ capabilities, several authentication methods, and sophisticated configuration options. -%package -n pam_ssh_agent_auth -Summary: PAM module for the use of authentication with ssh-agent -Version: 0.10.3 -Release: %{pam_ssh_agent_rel}.4 -License: BSD +%description clients +OpenSSH is a free version of SSH (Secure SHell), a program for logging +into and executing commands on a remote machine. This package includes +the clients necessary to make encrypted connections to SSH servers. + +%description server +OpenSSH is a free version of SSH (Secure SHell), a program for logging +into and executing commands on a remote machine. This package contains +the secure shell daemon (sshd). The sshd daemon allows SSH clients to +securely connect to your SSH server. + +%description ldap +OpenSSH LDAP backend is a way how to distribute the authorized tokens +among the servers in the network. + +%description keycat +OpenSSH mls keycat is backend for using the authorized keys in the +openssh in the mls mode. + +%description askpass +OpenSSH is a free version of SSH (Secure SHell), a program for logging +into and executing commands on a remote machine. This package contains +an X11 passphrase dialog for OpenSSH. + +%description cavs +This package contains test binaries and scripts to make FIPS validation +easier. Now contains CTR and KDF CAVS test driver. %description -n pam_ssh_agent_auth Provides PAM module for the use of authentication with ssh-agent. Through the use of the\ @@ -174,7 +179,6 @@ instance. The module is most useful for su and sudo service stacks. %package_help %prep -gpgv2 --quiet --keyring %{SOURCE3} %{SOURCE1} %{SOURCE0} %setup -q -a 4 pushd pam_ssh_agent_auth-0.10.3 @@ -188,95 +192,58 @@ pushd pam_ssh_agent_auth-0.10.3 rm -f $(cat %{SOURCE5}) popd -%patch10 -p1 -b .role-mls -%patch11 -p1 -b .privsep-selinux -%patch12 -p1 -b .ldap -%patch13 -p1 -b .keycat -%patch14 -p1 -b .ip-opts -%patch15 -p1 -b .keyperm -%patch16 -p1 -b .ipv6man -%patch17 -p1 -b .sigpipe -%patch18 -p1 -b .x11 -%patch20 -p1 -b .progress -%patch21 -p1 -b .grab-info -%patch22 -p1 -%patch23 -p1 -b .vendor -%patch24 -p1 -b .log-usepam-no -%patch25 -p1 -b .evp-ctr -%patch26 -p1 -b .ctr-cavs -%patch27 -p1 -b .kdf-cavs -%patch28 -p1 -b .gsskex -%patch29 -p1 -b .force_krb -%patch31 -p1 -b .gss-docs -%patch32 -p1 -b .ccache_name -%patch33 -p1 -b .k5login -%patch35 -p1 -b .canohost -%patch36 -p1 -b .kuserok -%patch37 -p1 -b .fromto-remote -%patch38 -p1 -b .contexts -%patch39 -p1 -b .log-in-chroot -%patch40 -p1 -b .scp -%patch41 -p1 -b .config -%patch30 -p1 -b .GSSAPIEnablek5users -%patch42 -p1 -b .sshdt -%patch43 -p1 -b .sftp-force-mode -%patch44 -p1 -b .root-login -%patch45 -p1 -b .gsskexalg -%patch46 -p1 -b .s390-dev -%patch47 -p1 -b .x11max -%patch48 -p1 -b .systemd -%patch34 -p1 -b .gsskex-ec -%patch49 -p1 -b .refactor -%patch50 -p1 -b .sandbox -%patch51 -p1 -b .pkcs11-uri -%patch52 -p1 -b .pkcs11-ecdsa -%patch53 -p1 -b .scp-ipv6 -%patch2 -p1 -b .audit -%patch3 -p1 -b .audit-race -%patch19 -p1 -b .fips -%patch0 -p1 -b .coverity -%patch1 -p1 -b .openssl -%patch54 -p1 -%patch55 -p1 -%patch56 -p1 -%patch57 -p1 -%patch58 -p1 -%patch59 -p1 -%patch60 -p1 -%patch61 -p1 -%patch62 -p1 -%patch63 -p1 -%patch64 -p1 -%patch65 -p1 -%patch66 -p1 -%patch67 -p1 -%patch68 -p1 -%patch69 -p1 -%patch70 -p1 -%patch71 -p1 -%patch72 -p1 -%patch73 -p1 -%patch74 -p1 -%patch75 -p1 -%patch76 -p1 -%patch77 -p1 -%patch78 -p1 -%patch79 -p1 -%patch80 -p1 -%patch81 -p1 -%patch82 -p1 -%patch83 -p1 -%patch85 -p1 -%patch86 -p1 -%patch87 -p1 -%patch88 -p1 -%patch89 -p1 -%patch90 -p1 -%patch84 -p1 -%patch91 -p1 -%patch92 -p1 -%patch93 -p1 -%patch94 -p1 +%patch400 -p1 -b .role-mls +%patch404 -p1 -b .privsep-selinux +%patch501 -p1 -b .ldap +%patch502 -p1 -b .keycat +%patch601 -p1 -b .ip-opts +%patch604 -p1 -b .keyperm +%patch606 -p1 -b .ipv6man +%patch607 -p1 -b .sigpipe +%patch609 -p1 -b .x11 +%patch702 -p1 -b .progress +%patch703 -p1 -b .grab-info +%patch707 -p1 +%patch711 -p1 -b .log-usepam-no +%patch712 -p1 -b .evp-ctr +%patch713 -p1 -b .ctr-cavs +%patch714 -p1 -b .kdf-cavs +%patch800 -p1 -b .gsskex +%patch801 -p1 -b .force_krb +%patch804 -p1 -b .ccache_name +%patch805 -p1 -b .k5login +%patch901 -p1 -b .kuserok +%patch906 -p1 -b .fromto-remote +%patch916 -p1 -b .contexts +%patch918 -p1 -b .log-in-chroot +%patch919 -p1 -b .scp +%patch802 -p1 -b .GSSAPIEnablek5users +%patch922 -p1 -b .sshdt +%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 +%patch958 -p1 -b .ssh-copy-id +%patch962 -p1 -b .crypto-policies +%patch963 -p1 -b .openssl-evp +%patch964 -p1 -b .openssl-kdf +%patch965 -p1 -b .visibility +%patch200 -p1 -b .audit +%patch201 -p1 -b .audit-race +%patch700 -p1 -b .fips +%patch100 -p1 -b .coverity + +%patch9004 -p1 +%patch9005 -p1 +%patch9006 -p1 +%patch9007 -p1 +%patch9009 -p1 +%patch9010 -p1 +%patch9011 -p1 autoreconf pushd pam_ssh_agent_auth-0.10.3 @@ -286,6 +253,7 @@ popd %build CFLAGS="$RPM_OPT_FLAGS -fvisibility=hidden"; export CFLAGS +CFLAGS="$CFLAGS -Os" %ifarch s390 s390x sparc sparcv9 sparc64 CFLAGS="$CFLAGS -fPIC" %else @@ -298,51 +266,48 @@ export CFLAGS export LDFLAGS if test -r /etc/profile.d/krb5-devel.sh ; then - source /etc/profile.d/krb5-devel.sh + source /etc/profile.d/krb5-devel.sh fi krb5_prefix=`krb5-config --prefix` if test "$krb5_prefix" != "%{_prefix}" ; then - CPPFLAGS="$CPPFLAGS -I${krb5_prefix}/include -I${krb5_prefix}/include/gssapi"; export CPPFLAGS - CFLAGS="$CFLAGS -I${krb5_prefix}/include -I${krb5_prefix}/include/gssapi" - LDFLAGS="$LDFLAGS -L${krb5_prefix}/%{_lib}"; export LDFLAGS + CPPFLAGS="$CPPFLAGS -I${krb5_prefix}/include -I${krb5_prefix}/include/gssapi"; export CPPFLAGS + CFLAGS="$CFLAGS -I${krb5_prefix}/include -I${krb5_prefix}/include/gssapi" + LDFLAGS="$LDFLAGS -L${krb5_prefix}/%{_lib}"; export LDFLAGS else - krb5_prefix= - CPPFLAGS="-I%{_includedir}/gssapi"; export CPPFLAGS - CFLAGS="$CFLAGS -I%{_includedir}/gssapi" + krb5_prefix= + CPPFLAGS="-I%{_includedir}/gssapi"; export CPPFLAGS + CFLAGS="$CFLAGS -I%{_includedir}/gssapi" fi %configure \ - --sysconfdir=%{_sysconfdir}/ssh --libexecdir=%{_libexecdir}/openssh \ - --datadir=%{_datadir}/openssh --with-default-path=/usr/local/bin:/usr/bin \ - --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \ - --with-privsep-path=%{_var}/empty/sshd -disable-strip \ - --enable-vendor-patchlevel="FC-7.8p1-3" \ - --without-zlib-version-check --with-ssl-engine --with-ipaddr-display \ - --with-pie=no --without-hardening --with-systemd --with-default-pkcs11-provider=yes \ - --with-ldap --with-pam --with-selinux --with-audit=linux \ -%ifnarch riscv64 - --with-sandbox=seccomp_filter \ -%endif - --with-kerberos5${krb5_prefix:+=${krb5_prefix}} --with-libedit + --sysconfdir=%{_sysconfdir}/ssh --libexecdir=%{_libexecdir}/openssh \ + --datadir=%{_datadir}/openssh --with-default-path=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin \ + --with-superuser-path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin \ + --with-privsep-path=%{_var}/empty/sshd --disable-strip \ + --without-zlib-version-check --with-ssl-engine --with-ipaddr-display \ + --with-pie=no --without-hardening --with-systemd --with-default-pkcs11-provider=yes \ + --with-ldap --with-pam --with-selinux --with-audit=linux --with-sandbox=seccomp_filter \ + --with-kerberos5${krb5_prefix:+=${krb5_prefix}} --with-libedit make gtk2=yes pushd contrib if [ $gtk2 = yes ] ; then - CFLAGS="$CFLAGS %{?__global_ldflags}" \ - make gnome-ssh-askpass2 - mv gnome-ssh-askpass2 gnome-ssh-askpass + CFLAGS="$CFLAGS %{?__global_ldflags}" \ + make gnome-ssh-askpass2 + mv gnome-ssh-askpass2 gnome-ssh-askpass else - CFLAGS="$CFLAGS %{?__global_ldflags}" - make gnome-ssh-askpass1 - mv gnome-ssh-askpass1 gnome-ssh-askpass + CFLAGS="$CFLAGS %{?__global_ldflags}" + make gnome-ssh-askpass1 + mv gnome-ssh-askpass1 gnome-ssh-askpass fi popd pushd pam_ssh_agent_auth-0.10.3 LDFLAGS="$SAVE_LDFLAGS" -%configure --with-selinux --libexecdir=/%{_libdir}/security --with-mantype=man +%configure --with-selinux --libexecdir=/%{_libdir}/security --with-mantype=man \ + --without-openssl-header-check make popd @@ -367,10 +332,10 @@ mkdir -p -m755 $RPM_BUILD_ROOT%{_var}/empty/sshd rm -f $RPM_BUILD_ROOT%{_sysconfdir}/ssh/ldap.conf -mkdir -p $RPM_BUILD_ROOT/etc/pam.d/ -mkdir -p $RPM_BUILD_ROOT/etc/sysconfig/ -mkdir -p $RPM_BUILD_ROOT%{_libexecdir}/openssh -mkdir -p $RPM_BUILD_ROOT%{_libdir}/fipscheck +install -d $RPM_BUILD_ROOT/etc/pam.d/ +install -d $RPM_BUILD_ROOT/etc/sysconfig/ +install -d $RPM_BUILD_ROOT%{_libexecdir}/openssh +install -d $RPM_BUILD_ROOT%{_libdir}/fipscheck install -m644 %{SOURCE2} $RPM_BUILD_ROOT/etc/pam.d/sshd install -m644 %{SOURCE6} $RPM_BUILD_ROOT/etc/pam.d/ssh-keycat install -m644 %{SOURCE7} $RPM_BUILD_ROOT/etc/sysconfig/sshd @@ -400,60 +365,85 @@ popd %pre getent group ssh_keys >/dev/null || groupadd -r ssh_keys || : + +%pre server getent group sshd >/dev/null || groupadd -g %{sshd_uid} -r sshd || : getent passwd sshd >/dev/null || \ useradd -c "Privilege-separated SSH" -u %{sshd_uid} -g sshd \ -s /sbin/nologin -r -d /var/empty/sshd sshd 2> /dev/null || : -%post +%post server %systemd_post sshd.service sshd.socket -%preun +%preun server %systemd_preun sshd.service sshd.socket -%postun +%postun server %systemd_postun_with_restart sshd.service %files -%defattr(-,root,root) -%doc CREDITS INSTALL README.platform %license LICENCE -%dir %attr(0711,root,root) %{_var}/empty/sshd -%attr(0644,root,root) %{_tmpfilesdir}/openssh.conf -%attr(0644,root,root) %config(noreplace) /etc/pam.d/ssh* -%attr(0640,root,root) %config(noreplace) /etc/sysconfig/sshd +%doc CREDITS README.platform %attr(0755,root,root) %dir %{_sysconfdir}/ssh %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/moduli +%attr(0755,root,root) %{_bindir}/ssh-keygen +%attr(0755,root,root) %dir %{_libexecdir}/openssh +%attr(2555,root,ssh_keys) %{_libexecdir}/openssh/ssh-keysign + +%files clients +%attr(0755,root,root) %{_bindir}/ssh +%attr(0644,root,root) %{_libdir}/fipscheck/ssh.hmac +%attr(0755,root,root) %{_bindir}/scp %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config -%dir %attr(0755,root,root) %{_sysconfdir}/ssh/ssh_config.d/ %attr(0644,root,root) %config(noreplace) %{_sysconfdir}/ssh/ssh_config.d/05-redhat.conf -%attr(0644,root,root) %{_sysconfdir}/profile.d/gnome-ssh-askpass.* -%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config -%attr(0755,root,root) %{_sbindir}/sshd -%attr(0755,root,root) %{_bindir}/ssh* -%attr(0755,root,root) %{_bindir}/scp +%attr(0755,root,root) %{_bindir}/ssh-agent +%attr(0755,root,root) %{_bindir}/ssh-add +%attr(0755,root,root) %{_bindir}/ssh-keyscan %attr(0755,root,root) %{_bindir}/sftp -%attr(0644,root,root) %{_libdir}/fipscheck/ssh*.hmac -%attr(0755,root,root) %dir %{_libexecdir}/openssh -%attr(2555,root,ssh_keys) %{_libexecdir}/openssh/ssh-keysign -%attr(0755,root,root) %{_libexecdir}/openssh/ctr-cavstest -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-cavs* +%attr(0755,root,root) %{_bindir}/ssh-copy-id %attr(0755,root,root) %{_libexecdir}/openssh/ssh-pkcs11-helper -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-ldap-* -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-keycat -%attr(0755,root,root) %{_libexecdir}/openssh/ssh-askpass +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-sk-helper + +%files server +%dir %attr(0711,root,root) %{_var}/empty/sshd +%attr(0755,root,root) %{_sbindir}/sshd +%attr(0644,root,root) %{_libdir}/fipscheck/sshd.hmac %attr(0755,root,root) %{_libexecdir}/openssh/sftp-server %attr(0755,root,root) %{_libexecdir}/openssh/sshd-keygen +%attr(0600,root,root) %config(noreplace) %{_sysconfdir}/ssh/sshd_config +%attr(0644,root,root) %config(noreplace) /etc/pam.d/sshd +%attr(0640,root,root) %config(noreplace) /etc/sysconfig/sshd +%attr(0644,root,root) %{_unitdir}/sshd.service +%attr(0644,root,root) %{_unitdir}/sshd@.service +%attr(0644,root,root) %{_unitdir}/sshd.socket +%attr(0644,root,root) %{_unitdir}/sshd-keygen@.service +%attr(0644,root,root) %{_unitdir}/sshd-keygen.target +%attr(0644,root,root) %{_tmpfilesdir}/openssh.conf + +%files ldap +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-ldap-helper +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-ldap-wrapper + +%files keycat +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-keycat +%attr(0644,root,root) %config(noreplace) /etc/pam.d/ssh-keycat + +%files askpass +%attr(0644,root,root) %{_sysconfdir}/profile.d/gnome-ssh-askpass.* %attr(0755,root,root) %{_libexecdir}/openssh/gnome-ssh-askpass -%attr(0644,root,root) %{_unitdir}/sshd* +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-askpass + +%files cavs +%attr(0755,root,root) %{_libexecdir}/openssh/ctr-cavstest +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-cavs +%attr(0755,root,root) %{_libexecdir}/openssh/ssh-cavs_driver.pl %files -n pam_ssh_agent_auth -%defattr(-,root,root) %license pam_ssh_agent_auth-0.10.3/OPENSSH_LICENSE %attr(0755,root,root) %{_libdir}/security/pam_ssh_agent_auth.so +%attr(0644,root,root) %{_mandir}/man8/pam_ssh_agent_auth.8* %files help -%defattr(-,root,root) %doc ChangeLog OVERVIEW PROTOCOL* README README.privsep README.tun README.dns TODO openssh-lpk-openldap.schema %doc openssh-lpk-sun.schema ldap.conf openssh-lpk-openldap.ldif openssh-lpk-sun.ldif HOWTO.ssh-keycat HOWTO.ldap-keys %attr(0644,root,root) %{_mandir}/man1/scp.1* @@ -466,14 +456,65 @@ getent passwd sshd >/dev/null || \ %attr(0644,root,root) %{_mandir}/man8/sftp-server.8* %changelog -* Fri Jul 03 2020 zhouyihang - 7.8P1-9 +* Wed Jul 22 2020 yuboyun - 8.3P1-1 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:update to 8.3P1 + +* Tue Jun 9 2020 openEuler Buildteam - 8.2P1-4 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:add requires for openssh-server in openssh + +* Wed May 6 2020 openEuler Buildteam - 8.2P1-3 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix update problem + +* Sat Apr 18 2020 openEuler Buildteam - 8.2P1-2 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:fix pre problem + +* Thu Apr 16 2020 openEuler Buildteam - 8.2P1-1 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:update to 8.2P1 + +* Mon Mar 30 2020 openEuler Buildteam - 7.8P1-12 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:move sshd.service in %post server + +* Wed Mar 18 2020 openEuler Buildteam - 7.8P1-11 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:reduction of authority + +* Fri Mar 13 2020 openEuler Buildteam - 7.8P1-10 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:separate package + +* Thu Mar 5 2020 openEuler Buildteam - 7.8P1-9 - Type:cves -- ID:CVE-2020-12062 +- ID:CVE-2018-15919 - SUG:NA -- DESC:Fix CVE-2020-12062 +- DESC:Fix CVE-2018-15919 -* Wed Mar 18 2020 songnannan - 7.8P1-8 -- bugfix CVE-2018-15919 +* Thu Mar 5 2020 openEuler Buildteam - 7.8P1-8 +- Type:bugfix +- ID:NA +- SUG:NA +- DESC:debug3 to verbose in command line * Tue Jan 21 2020 openEuler Buildteam - 7.8P1-7 - Type:bugfix diff --git a/pam_ssh_agent_auth-0.10.2-compat.patch b/pam_ssh_agent_auth-0.10.2-compat.patch index 6352bfaf1cb179075cb1c4ee55a5acd1aeb6b7f8..d1d4f59eff74080c3062448e558a224dda200fac 100644 --- a/pam_ssh_agent_auth-0.10.2-compat.patch +++ b/pam_ssh_agent_auth-0.10.2-compat.patch @@ -1,6 +1,6 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c --- openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c 2018-08-24 10:22:56.281930322 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c 2020-02-07 10:43:05.011757956 +0100 @@ -27,6 +27,7 @@ * or implied, of Jamie Beverly. */ @@ -34,7 +34,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/get_command_line.c.psaa-compat openss diff -up openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/identity.h --- openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/identity.h 2018-08-24 10:18:05.009393312 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/identity.h 2020-02-07 10:43:05.011757956 +0100 @@ -30,8 +30,8 @@ #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" @@ -56,8 +56,8 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/identity.h.psaa-compat openssh/pam_ss int tried; int isprivate; /* key points to the private key */ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c ---- openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat 2018-08-24 10:18:05.007393297 +0200 -+++ openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2018-08-24 10:18:32.937612513 +0200 +--- openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat 2020-02-07 10:43:05.009757925 +0100 ++++ openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c 2020-02-07 10:43:05.012757972 +0100 @@ -36,8 +36,8 @@ #include "openbsd-compat/sys-queue.h" #include "xmalloc.h" @@ -119,7 +119,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat const char * ruser, const char * servicename) { u_char *cookie = NULL; -@@ -114,22 +116,23 @@ pamsshagentauth_session_id2_gen(Buffer * +@@ -114,22 +120,23 @@ pamsshagentauth_session_id2_gen(Buffer * char ** reported_argv = NULL; size_t count = 0; char * action_logbuf = NULL; @@ -147,13 +147,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat } cookie[i] = (u_char) rnd; rnd >>= 8; -@@ -139,12 +141,13 @@ pamsshagentauth_session_id2_gen(Buffer * - if (count > 0) { - free_logbuf = 1; - action_logbuf = log_action(reported_argv, count); -- agent_action(&action_agentbuf, reported_argv, count); -+ agent_action(&action_agentbuf, reported_argv, count); - pamsshagentauth_free_command_line(reported_argv, count); +@@ -144,7 +151,8 @@ pamsshagentauth_session_id2_gen(Buffer * } else { action_logbuf = "unknown on this platform"; @@ -163,7 +157,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat } /* -@@ -161,35 +163,39 @@ pamsshagentauth_session_id2_gen(Buffer * +@@ -161,35 +169,39 @@ pamsshagentauth_session_id2_gen(Buffer * retc = getcwd(pwd, sizeof(pwd) - 1); time(&ts); @@ -207,6 +201,14 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat - pamsshagentauth_buffer_free(&action_agentbuf); + free(action_logbuf); + sshbuf_free(action_agentbuf); ++ } ++ /* debug3("hostname: %s", hostname); */ ++ if (reti >= 0) { ++ if ((r = sshbuf_put_cstring(*session_id2, hostname)) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); ++ } else { ++ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0) ++ fatal("%s: buffer error: %s", __func__, ssh_err(r)); } - /* pamsshagentauth_debug3("hostname: %s", hostname); */ - if(reti >= 0) @@ -215,21 +217,13 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat - pamsshagentauth_buffer_put_cstring(session_id2, ""); - /* pamsshagentauth_debug3("ts: %ld", ts); */ - pamsshagentauth_buffer_put_int64(session_id2, (uint64_t) ts); -+ /* debug3("hostname: %s", hostname); */ -+ if (reti >= 0) { -+ if ((r = sshbuf_put_cstring(*session_id2, hostname)) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } else { -+ if ((r = sshbuf_put_cstring(*session_id2, "")) != 0) -+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); -+ } + /* debug3("ts: %ld", ts); */ + if ((r = sshbuf_put_u64(*session_id2, (uint64_t) ts)) != 0) + fatal("%s: buffer error: %s", __func__, ssh_err(r)); free(cookie); return; -@@ -278,7 +280,8 @@ ssh_get_authentication_connection_for_ui +@@ -278,7 +290,8 @@ ssh_get_authentication_connection_for_ui auth = xmalloc(sizeof(*auth)); auth->fd = sock; @@ -239,7 +233,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat auth->howmany = 0; return auth; -@@ -287,43 +289,42 @@ ssh_get_authentication_connection_for_ui +@@ -287,9 +300,9 @@ ssh_get_authentication_connection_for_ui int pamsshagentauth_find_authorized_keys(const char * user, const char * ruser, const char * servicename) { @@ -251,11 +245,8 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat AuthenticationConnection *ac; char *comment; uint8_t retval = 0; - uid_t uid = getpwnam(ruser)->pw_uid; - - OpenSSL_add_all_digests(); -- pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); -+ pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); +@@ -299,31 +312,30 @@ pamsshagentauth_find_authorized_keys(con + pamsshagentauth_session_id2_gen(&session_id2, user, ruser, servicename); if ((ac = ssh_get_authentication_connection_for_uid(uid))) { - pamsshagentauth_verbose("Contacted ssh-agent of user %s (%u)", ruser, uid); @@ -295,8 +286,8 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/iterate_ssh_agent_keys.c.psaa-compat return retval; } diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c ---- openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c.psaa-compat 2018-08-24 10:18:05.008393305 +0200 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c 2018-08-24 10:18:05.009393312 +0200 +--- openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c.psaa-compat 2020-02-07 10:43:05.010757940 +0100 ++++ openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c 2020-02-07 10:43:05.012757972 +0100 @@ -104,7 +104,7 @@ pam_sm_authenticate(pam_handle_t * pamh, * a patch 8-) */ @@ -386,7 +377,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_ssh_agent_auth.c.psaa-compat open cleanexit: diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c --- openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c 2018-08-24 10:18:05.009393312 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c 2020-02-07 10:43:05.012757972 +0100 @@ -66,8 +66,8 @@ #include "xmalloc.h" #include "match.h" @@ -453,7 +444,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.c.psaa-compa pamsshagentauth_user_key_allowed2(getpwuid(authorized_keys_file_allowed_owner_uid), diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h --- openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h 2018-08-24 10:18:05.010393320 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h 2020-02-07 10:43:05.012757972 +0100 @@ -32,7 +32,7 @@ #define _PAM_USER_KEY_ALLOWED_H @@ -465,7 +456,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_authorized_keys.h.psaa-compa #endif diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c --- openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c 2018-08-24 10:18:05.010393320 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c 2020-02-07 10:43:05.012757972 +0100 @@ -45,44 +45,46 @@ #include "xmalloc.h" #include "ssh.h" @@ -742,7 +733,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.c.psaa-compat o } diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h --- openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h 2018-08-24 10:18:05.010393320 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h 2020-02-07 10:43:05.012757972 +0100 @@ -32,7 +32,7 @@ #define _PAM_USER_KEY_ALLOWED_H @@ -755,7 +746,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/pam_user_key_allowed2.h.psaa-compat o #endif diff -up openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c --- openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c 2018-08-24 10:18:05.010393320 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c 2020-02-07 10:43:05.012757972 +0100 @@ -53,8 +53,8 @@ #include "xmalloc.h" #include "match.h" @@ -799,7 +790,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/secure_filename.c.psaa-compat openssh } diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c --- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c 2018-08-24 10:22:13.202657025 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c 2020-02-07 10:43:23.520048960 +0100 @@ -37,10 +37,11 @@ #include "xmalloc.h" #include "ssh.h" @@ -814,7 +805,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat #include "pathnames.h" #include "misc.h" #include "secure_filename.h" -@@ -48,54 +48,59 @@ +@@ -48,54 +49,59 @@ #include "identity.h" #include "pam_user_authorized_keys.h" @@ -833,8 +824,8 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat char *pkalg = NULL; u_char *pkblob = NULL, *sig = NULL; - u_int blen = 0, slen = 0; -+ size_t blen = 0, slen = 0; - int authenticated = 0; ++ size_t blen = 0, slen = 0; + int r, authenticated = 0; - pkalg = (char *) key_ssh_name(id->key); @@ -879,7 +870,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat /* test for correct signature */ - if(pamsshagentauth_key_verify(id->key, sig, slen, pamsshagentauth_buffer_ptr(&b), pamsshagentauth_buffer_len(&b)) == 1) -+ if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0) == 0) ++ if (sshkey_verify(id->key, sig, slen, sshbuf_ptr(b), sshbuf_len(b), NULL, 0, NULL) == 0) authenticated = 1; user_auth_clean_exit: @@ -898,7 +889,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.c.psaa-compat } diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h --- openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h 2018-08-24 10:18:05.010393320 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h 2020-02-07 10:43:05.013757988 +0100 @@ -31,7 +31,7 @@ #ifndef _USERAUTH_PUBKEY_FROM_ID_H #define _USERAUTH_PUBKEY_FROM_ID_H @@ -911,7 +902,7 @@ diff -up openssh/pam_ssh_agent_auth-0.10.3/userauth_pubkey_from_id.h.psaa-compat #endif diff -up openssh/pam_ssh_agent_auth-0.10.3/uuencode.c.psaa-compat openssh/pam_ssh_agent_auth-0.10.3/uuencode.c --- openssh/pam_ssh_agent_auth-0.10.3/uuencode.c.psaa-compat 2016-11-13 04:24:32.000000000 +0100 -+++ openssh/pam_ssh_agent_auth-0.10.3/uuencode.c 2018-08-24 10:18:05.010393320 +0200 ++++ openssh/pam_ssh_agent_auth-0.10.3/uuencode.c 2020-02-07 10:43:05.013757988 +0100 @@ -56,7 +56,7 @@ pamsshagentauth_uudecode(const char *src /* and remove trailing whitespace because __b64_pton needs this */ *p = '\0'; diff --git a/pam_ssh_agent_auth-0.9.3-build.patch b/pam_ssh_agent_auth-0.9.3-build.patch index f269b9799367c7ad33714de4552621e5d6ba9e7c..bb9a94d035a10ee0a24600e04d3469cba29079df 100644 --- a/pam_ssh_agent_auth-0.9.3-build.patch +++ b/pam_ssh_agent_auth-0.9.3-build.patch @@ -159,15 +159,17 @@ diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build openssh- LIBS=@LIBS@ AR=@AR@ AWK=@AWK@ -@@ -61,7 +61,7 @@ INSTALL=@INSTALL@ +@@ -61,8 +61,8 @@ INSTALL=@INSTALL@ PERL=@PERL@ SED=@SED@ ENT=@ENT@ -LDFLAGS=-L. -Lopenbsd-compat/ @LDFLAGS@ +-LDFLAGS_SHARED = @LDFLAGS_SHARED@ +LDFLAGS=-L.. -L../openbsd-compat/ @LDFLAGS@ - LDFLAGS_SHARED = @LDFLAGS_SHARED@ ++LDFLAGS_SHARED =-Wl,-z,defs @LDFLAGS_SHARED@ EXEEXT=@EXEEXT@ + INSTALL_SSH_PRNG_CMDS=@INSTALL_SSH_PRNG_CMDS@ @@ -74,7 +74,7 @@ SSHOBJS=xmalloc.o atomicio.o authfd.o bu ED25519OBJS=ed25519-donna/ed25519.o @@ -189,8 +191,8 @@ diff -up openssh-7.4p1/pam_ssh_agent_auth-0.10.3/Makefile.in.psaa-build openssh- -pam_ssh_agent_auth.so: $(LIBCOMPAT) $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o - $(LD) $(LDFLAGS_SHARED) -o $@ $(SSHOBJS) $(ED25519OBJS) $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lopenbsd-compat pam_ssh_agent_auth.o $(LIBS) -lpam -+pam_ssh_agent_auth.so: $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o ../uidswap.o -+ $(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) $(LDFLAGS) -lssh -lopenbsd-compat pam_ssh_agent_auth.o ../uidswap.o $(LIBS) -lpam ++pam_ssh_agent_auth.so: $(PAM_SSH_AGENT_AUTH_OBJS) pam_ssh_agent_auth.o ../uidswap.o ../ssh-sk-client.o ++ $(LD) $(LDFLAGS_SHARED) -o $@ $(PAM_SSH_AGENT_AUTH_OBJS) ../ssh-sk-client.o $(LDFLAGS) -lssh -lopenbsd-compat pam_ssh_agent_auth.o ../uidswap.o $(LIBS) -lpam $(MANPAGES): $(MANPAGES_IN) pod2man --section=8 --release=v0.10.3 --name=pam_ssh_agent_auth --official --center "PAM" pam_ssh_agent_auth.pod > pam_ssh_agent_auth.8 diff --git a/set-sshd-config.patch b/set-sshd-config.patch new file mode 100644 index 0000000000000000000000000000000000000000..9fe193dd40280007afb428bfb951047733b8ece9 --- /dev/null +++ b/set-sshd-config.patch @@ -0,0 +1,104 @@ +From 8f2d1c4f30dd88e36ed4c9b5771c92c878378125 Mon Sep 17 00:00:00 2001 +From: m00525086 +Date: Thu, 16 Apr 2020 19:25:27 +0800 +Subject: [PATCH] sshd_config + +--- + sshd_config | 28 ++++++++++++++++++---------- + 1 file changed, 18 insertions(+), 10 deletions(-) + +diff --git a/sshd_config b/sshd_config +index b121450..e8e6299 100644 +--- a/sshd_config ++++ b/sshd_config +@@ -19,21 +19,22 @@ + #ListenAddress 0.0.0.0 + #ListenAddress :: + +-#HostKey /etc/ssh/ssh_host_rsa_key +-#HostKey /etc/ssh/ssh_host_ecdsa_key +-#HostKey /etc/ssh/ssh_host_ed25519_key ++HostKey /etc/ssh/ssh_host_rsa_key ++HostKey /etc/ssh/ssh_host_ecdsa_key ++HostKey /etc/ssh/ssh_host_ed25519_key + + # Ciphers and keying + #RekeyLimit default none + + # Logging + #SyslogFacility AUTH ++SyslogFacility AUTHPRIV + #LogLevel INFO + + # Authentication: + + #LoginGraceTime 2m +-#PermitRootLogin prohibit-password ++PermitRootLogin yes + #StrictModes yes + #MaxAuthTries 6 + #MaxSessions 10 +@@ -60,9 +61,11 @@ AuthorizedKeysFile .ssh/authorized_keys + # To disable tunneled clear text passwords, change to no here! + #PasswordAuthentication yes + #PermitEmptyPasswords no ++PasswordAuthentication yes + + # Change to no to disable s/key passwords + #ChallengeResponseAuthentication yes ++ChallengeResponseAuthentication no + + # Kerberos options + #KerberosAuthentication no +@@ -72,8 +75,8 @@ AuthorizedKeysFile .ssh/authorized_keys + #KerberosUseKuserok yes + + # GSSAPI options +-#GSSAPIAuthentication no +-#GSSAPICleanupCredentials yes ++GSSAPIAuthentication yes ++GSSAPICleanupCredentials no + #GSSAPIStrictAcceptorCheck yes + #GSSAPIKeyExchange no + #GSSAPIEnablek5users no +@@ -89,16 +92,16 @@ AuthorizedKeysFile .ssh/authorized_keys + # and ChallengeResponseAuthentication to 'no'. + # WARNING: 'UsePAM no' is not supported in openEuler and may cause several + # problems. +-#UsePAM no ++UsePAM yes + + #AllowAgentForwarding yes + #AllowTcpForwarding yes + #GatewayPorts no +-#X11Forwarding no ++X11Forwarding yes + #X11DisplayOffset 10 + #X11UseLocalhost yes + #PermitTTY yes +-#PrintMotd yes ++PrintMotd no + #PrintLastLog yes + #TCPKeepAlive yes + #PermitUserEnvironment no +@@ -115,6 +118,11 @@ AuthorizedKeysFile .ssh/authorized_keys + # no default banner path + #Banner none + ++AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES ++AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT ++AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE ++AcceptEnv XMODIFIERS ++ + # override default of no subsystems + Subsystem sftp /usr/libexec/sftp-server + +@@ -129,4 +137,4 @@ Subsystem sftp /usr/libexec/sftp-server + + # To modify the system-wide ssh configuration, create a *.conf file under + # /etc/ssh/sshd_config.d/ which will be automatically included below +-Include /etc/ssh/sshd_config.d/*.conf ++#Include /etc/ssh/sshd_config.d/*.conf +-- +2.19.1 + diff --git a/sshd-keygen b/sshd-keygen index 141814c5947c179a2e8337be7ca1012d23e8d01c..efd876c99aa7c6a854f603889d32617b4f550a49 100644 --- a/sshd-keygen +++ b/sshd-keygen @@ -31,8 +31,8 @@ fi # sanitize permissions /usr/bin/chgrp ssh_keys $KEY -/usr/bin/chmod 640 $KEY -/usr/bin/chmod 644 $KEY.pub +/usr/bin/chmod 400 $KEY +/usr/bin/chmod 400 $KEY.pub if [[ -x /usr/sbin/restorecon ]]; then /usr/sbin/restorecon $KEY{,.pub} fi diff --git a/sshd.service b/sshd.service index f9a12a81a9831fc45b487b6ec993847de22b93cc..8f3dbd65651fa7795e58c3c30266689d67717d33 100644 --- a/sshd.service +++ b/sshd.service @@ -7,8 +7,9 @@ Wants=sshd-keygen.target [Service] Type=notify EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config +EnvironmentFile=-/etc/sysconfig/sshd-permitrootlogin EnvironmentFile=-/etc/sysconfig/sshd -ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY +ExecStart=/usr/sbin/sshd -D $OPTIONS $CRYPTO_POLICY $PERMITROOTLOGIN ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure diff --git a/sshd.sysconfig b/sshd.sysconfig index 7d2ea2a236779fa1be445951972562bdb3287308..6c2bff94717f1768942410769049d6b48484ded2 100644 --- a/sshd.sysconfig +++ b/sshd.sysconfig @@ -8,4 +8,4 @@ # System-wide crypto policy: # To opt-out, uncomment the following line -CRYPTO_POLICY= +# CRYPTO_POLICY= diff --git a/sshd@.service b/sshd@.service index 9b8e012e4aac16fb08cc048a5dec475a8670830b..e4fd7f4eb1b7cade22e4db4df56bf84fa92ef162 100644 --- a/sshd@.service +++ b/sshd@.service @@ -6,6 +6,7 @@ After=sshd-keygen.target [Service] EnvironmentFile=-/etc/crypto-policies/back-ends/opensshserver.config +EnvironmentFile=-/etc/sysconfig/sshd-permitrootlogin EnvironmentFile=-/etc/sysconfig/sshd -ExecStart=-/usr/sbin/sshd -i $OPTIONS $CRYPTO_POLICY +ExecStart=-/usr/sbin/sshd -i $OPTIONS $CRYPTO_POLICY $PERMITROOTLOGIN StandardInput=socket diff --git a/upstream-Always-initialize-2nd-arg-to-hpdelim2.-It-p.patch b/upstream-Always-initialize-2nd-arg-to-hpdelim2.-It-p.patch deleted file mode 100644 index d21ea52260ac33e67861c54626693fa8f47b53b0..0000000000000000000000000000000000000000 --- a/upstream-Always-initialize-2nd-arg-to-hpdelim2.-It-p.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 7f9fc6a467c030ab36fba3a99377ed4330545a1d Mon Sep 17 00:00:00 2001 -From: guoxiaoqi -Date: Tue, 5 Mar 2019 12:01:44 +0000 -Subject: [PATCH] upstream-Always-initialize-2nd-arg-to-hpdelim2.-It-p - ---- - servconf.c | 7 ++++--- - 1 file changed, 4 insertions(+), 3 deletions(-) - -diff --git a/servconf.c b/servconf.c -index 67a71ba..434f0bc 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -927,6 +927,7 @@ process_permitopen_list(struct ssh *ssh, ServerOpCodes opcode, - /* Otherwise treat it as a list of permitted host:port */ - for (i = 0; i < num_opens; i++) { - oarg = arg = xstrdup(opens[i]); -+ ch = '\0'; - host = hpdelim2(&arg, &ch); - if (host == NULL || ch == '/') - fatal("%s: missing host in %s", __func__, what); -@@ -1246,7 +1247,7 @@ process_server_config_line(ServerOptions *options, char *line, - const char *filename, int linenum, int *activep, - struct connection_info *connectinfo) - { -- char *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; -+ char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; - int cmdline = 0, *intptr, value, value2, n, port; - SyslogFacility *log_facility_ptr; - LogLevel *log_level_ptr; -@@ -1349,8 +1350,8 @@ process_server_config_line(ServerOptions *options, char *line, - port = 0; - p = arg; - } else { -- char ch; - arg2 = NULL; -+ ch = '\0'; - p = hpdelim2(&arg, &ch); - if (p == NULL || ch == '/') - fatal("%s line %d: bad address:port usage", -@@ -2014,8 +2015,8 @@ process_server_config_line(ServerOptions *options, char *line, - */ - xasprintf(&arg2, "*:%s", arg); - } else { -- char ch; - arg2 = xstrdup(arg); -+ ch = '\0'; - p = hpdelim2(&arg, &ch); - if (p == NULL || ch == '/') { - fatal("%s line %d: missing host in %s", --- -1.8.3.1 - diff --git a/upstream-Fix-BN_is_prime_-calls-in-SSH-the-API-retur.patch b/upstream-Fix-BN_is_prime_-calls-in-SSH-the-API-retur.patch deleted file mode 100644 index 36f82e05abac26ad5302230612aa76b45e8d4eaf..0000000000000000000000000000000000000000 --- a/upstream-Fix-BN_is_prime_-calls-in-SSH-the-API-retur.patch +++ /dev/null @@ -1,75 +0,0 @@ -From a36b0b14a12971086034d53c0c3dfbad07665abe Mon Sep 17 00:00:00 2001 -From: "tb@openbsd.org" -Date: Sun, 20 Jan 2019 02:01:59 +0000 -Subject: [PATCH 185/294] upstream: Fix BN_is_prime_* calls in SSH, the API - returns -1 on - -error. - -Found thanks to BoringSSL's commit 53409ee3d7595ed37da472bc73b010cd2c8a5ffd -by David Benjamin. - -ok djm, dtucker - -OpenBSD-Commit-ID: 1ee832be3c44b1337f76b8562ec6d203f3b072f8 ---- - moduli.c | 19 ++++++++++++++----- - 1 file changed, 14 insertions(+), 5 deletions(-) - -diff --git a/moduli.c b/moduli.c -index 233cba8..48150da 100644 ---- a/moduli.c -+++ b/moduli.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: moduli.c,v 1.32 2017/12/08 03:45:52 deraadt Exp $ */ -+/* $OpenBSD: moduli.c,v 1.33 2019/01/20 02:01:59 tb Exp $ */ - /* - * Copyright 1994 Phil Karn - * Copyright 1996-1998, 2003 William Allen Simpson -@@ -582,7 +582,7 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, - u_int32_t generator_known, in_tests, in_tries, in_type, in_size; - unsigned long last_processed = 0, end_lineno; - time_t time_start, time_stop; -- int res; -+ int res, is_prime; - - if (trials < TRIAL_MINIMUM) { - error("Minimum primality trials is %d", TRIAL_MINIMUM); -@@ -753,7 +753,10 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, - * that p is also prime. A single pass will weed out the - * vast majority of composite q's. - */ -- if (BN_is_prime_ex(q, 1, ctx, NULL) <= 0) { -+ is_prime = BN_is_prime_ex(q, 1, ctx, NULL); -+ if (is_prime < 0) -+ fatal("BN_is_prime_ex failed"); -+ if (is_prime == 0) { - debug("%10u: q failed first possible prime test", - count_in); - continue; -@@ -766,14 +769,20 @@ prime_test(FILE *in, FILE *out, u_int32_t trials, u_int32_t generator_wanted, - * will show up on the first Rabin-Miller iteration so it - * doesn't hurt to specify a high iteration count. - */ -- if (!BN_is_prime_ex(p, trials, ctx, NULL)) { -+ is_prime = BN_is_prime_ex(p, trials, ctx, NULL); -+ if (is_prime < 0) -+ fatal("BN_is_prime_ex failed"); -+ if (is_prime == 0) { - debug("%10u: p is not prime", count_in); - continue; - } - debug("%10u: p is almost certainly prime", count_in); - - /* recheck q more rigorously */ -- if (!BN_is_prime_ex(q, trials - 1, ctx, NULL)) { -+ is_prime = BN_is_prime_ex(q, trials - 1, ctx, NULL); -+ if (is_prime < 0) -+ fatal("BN_is_prime_ex failed"); -+ if (is_prime == 0) { - debug("%10u: q is not prime", count_in); - continue; - } --- -1.8.3.1 - diff --git a/upstream-When-choosing-a-prime-from-the-moduli-file-.patch b/upstream-When-choosing-a-prime-from-the-moduli-file-.patch deleted file mode 100644 index 3ae7f1d2150bf0448e6dae3439637a6b7665b299..0000000000000000000000000000000000000000 --- a/upstream-When-choosing-a-prime-from-the-moduli-file-.patch +++ /dev/null @@ -1,62 +0,0 @@ -From 5e532320e9e51de720d5f3cc2596e95d29f6e98f Mon Sep 17 00:00:00 2001 -From: "millert@openbsd.org" -Date: Mon, 17 Sep 2018 15:40:14 +0000 -Subject: [PATCH 037/294] upstream: When choosing a prime from the moduli file, - avoid - -re-using the linenum variable for something that is not a line number to -avoid the confusion that resulted in the bug in rev. 1.64. This also lets us -pass the actual linenum to parse_prime() so the error messages include the -correct line number. OK markus@ some time ago. - -OpenBSD-Commit-ID: 4d8e5d3e924d6e8eb70053e3defa23c151a00084 ---- - dh.c | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - -diff --git a/dh.c b/dh.c -index f3ed388..657b32d 100644 ---- a/dh.c -+++ b/dh.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: dh.c,v 1.66 2018/08/04 00:55:06 djm Exp $ */ -+/* $OpenBSD: dh.c,v 1.68 2018/09/17 15:40:14 millert Exp $ */ - /* - * Copyright (c) 2000 Niels Provos. All rights reserved. - * -@@ -188,15 +188,17 @@ choose_dh(int min, int wantbits, int max) - logit("WARNING: no suitable primes in %s", _PATH_DH_MODULI); - return (dh_new_group_fallback(max)); - } -+ which = arc4random_uniform(bestcount); - - linenum = 0; -- which = arc4random_uniform(bestcount); -+ bestcount = 0; - while (getline(&line, &linesize, f) != -1) { -+ linenum++; - if (!parse_prime(linenum, line, &dhg)) - continue; - if ((dhg.size > max || dhg.size < min) || - dhg.size != best || -- linenum++ != which) { -+ bestcount++ != which) { - BN_clear_free(dhg.g); - BN_clear_free(dhg.p); - continue; -@@ -206,9 +208,9 @@ choose_dh(int min, int wantbits, int max) - free(line); - line = NULL; - fclose(f); -- if (linenum != which+1) { -- logit("WARNING: line %d disappeared in %s, giving up", -- which, _PATH_DH_MODULI); -+ if (bestcount != which + 1) { -+ logit("WARNING: selected prime disappeared in %s, giving up", -+ _PATH_DH_MODULI); - return (dh_new_group_fallback(max)); - } - --- -1.8.3.1 - diff --git a/upstream-correct-local-variable-name-from-yawang-AT-.patch b/upstream-correct-local-variable-name-from-yawang-AT-.patch deleted file mode 100644 index fea27fad08db88338459e6d486615f51019af89d..0000000000000000000000000000000000000000 --- a/upstream-correct-local-variable-name-from-yawang-AT-.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 81f1620c836e6c79c0823ba44acca605226a80f1 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 9 Nov 2018 02:56:22 +0000 -Subject: [PATCH 106/294] upstream: correct local variable name; from yawang AT - microsoft.com - -OpenBSD-Commit-ID: a0c228390856a215bb66319c89cb3959d3af8c87 ---- - dh.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/dh.c b/dh.c -index 657b32d..a98d39e 100644 ---- a/dh.c -+++ b/dh.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: dh.c,v 1.68 2018/09/17 15:40:14 millert Exp $ */ -+/* $OpenBSD: dh.c,v 1.69 2018/11/09 02:56:22 djm Exp $ */ - /* - * Copyright (c) 2000 Niels Provos. All rights reserved. - * -@@ -406,7 +406,7 @@ dh_new_group16(void) - DH * - dh_new_group18(void) - { -- static char *gen = "2", *group16 = -+ static char *gen = "2", *group18 = - "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" - "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" - "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" -@@ -451,7 +451,7 @@ dh_new_group18(void) - "9558E447" "5677E9AA" "9E3050E2" "765694DF" "C81F56E8" "80B96E71" - "60C980DD" "98EDD3DF" "FFFFFFFF" "FFFFFFFF"; - -- return (dh_new_group_asc(gen, group16)); -+ return (dh_new_group_asc(gen, group18)); - } - - /* Select fallback group used by DH-GEX if moduli file cannot be read. */ --- -1.8.3.1 - diff --git a/upstream-disallow-empty-incoming-filename-or-ones-th.patch b/upstream-disallow-empty-incoming-filename-or-ones-th.patch deleted file mode 100644 index 1daa84f7c8efc5a0c341805c2f6b9603bebd12d8..0000000000000000000000000000000000000000 --- a/upstream-disallow-empty-incoming-filename-or-ones-th.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 6010c0303a422a9c5fa8860c061bf7105eb7f8b2 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 16 Nov 2018 03:03:10 +0000 -Subject: [PATCH 112/294] upstream: disallow empty incoming filename or ones - that refer to the - -current directory; based on report/patch from Harry Sintonen - -OpenBSD-Commit-ID: f27651b30eaee2df49540ab68d030865c04f6de9 ---- - scp.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/scp.c b/scp.c -index 60682c6..4f3fdcd 100644 ---- a/scp.c -+++ b/scp.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: scp.c,v 1.197 2018/06/01 04:31:48 dtucker Exp $ */ -+/* $OpenBSD: scp.c,v 1.198 2018/11/16 03:03:10 djm Exp $ */ - /* - * scp - secure remote copy. This is basically patched BSD rcp which - * uses ssh to do the data transfer (instead of using rcmd). -@@ -1106,7 +1106,8 @@ sink(int argc, char **argv) - SCREWUP("size out of range"); - size = (off_t)ull; - -- if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) { -+ if (*cp == '\0' || strchr(cp, '/') != NULL || -+ strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) { - run_err("error: unexpected filename: %s", cp); - exit(1); - } --- -1.8.3.1 - diff --git a/upstream-don-t-attempt-to-connect-to-empty-SSH_AUTH_.patch b/upstream-don-t-attempt-to-connect-to-empty-SSH_AUTH_.patch deleted file mode 100644 index e373633635b088d1095bff17a15bd613f61a809b..0000000000000000000000000000000000000000 --- a/upstream-don-t-attempt-to-connect-to-empty-SSH_AUTH_.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 87d6cf1cbc91df6815db8fe0acc7c910bc3d18e4 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 30 Nov 2018 02:24:52 +0000 -Subject: [PATCH 135/294] upstream: don't attempt to connect to empty - SSH_AUTH_SOCK; bz#293 - -OpenBSD-Commit-ID: 0e8fc8f19f14b21adef7109e0faa583d87c0e929 ---- - authfd.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/authfd.c b/authfd.c -index ecdd869..cc9c650 100644 ---- a/authfd.c -+++ b/authfd.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: authfd.c,v 1.111 2018/07/09 21:59:10 markus Exp $ */ -+/* $OpenBSD: authfd.c,v 1.112 2018/11/30 02:24:52 djm Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -94,7 +94,7 @@ ssh_get_authentication_socket(int *fdp) - *fdp = -1; - - authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); -- if (!authsocket) -+ if (authsocket == NULL || *authsocket == '\0') - return SSH_ERR_AGENT_NOT_PRESENT; - - memset(&sunaddr, 0, sizeof(sunaddr)); --- -1.8.3.1 - diff --git a/upstream-don-t-truncate-user-or-host-name-in-user-ho.patch b/upstream-don-t-truncate-user-or-host-name-in-user-ho.patch deleted file mode 100644 index b9f0652f4c94e44dcc0d697f859c6a469d6d82d4..0000000000000000000000000000000000000000 --- a/upstream-don-t-truncate-user-or-host-name-in-user-ho.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 91b19198c3f604f5eef2c56dbe36f29478243141 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Wed, 28 Nov 2018 06:00:38 +0000 -Subject: [PATCH 134/294] upstream: don't truncate user or host name in - "user@host's - -OpenBSD-Commit-ID: e6ca01a8d58004b7f2cac0b1b7ce8f87e425e360 ---- - sshconnect2.c | 9 ++++----- - 1 file changed, 4 insertions(+), 5 deletions(-) - -diff --git a/sshconnect2.c b/sshconnect2.c -index 200e07d..6186ca7 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -1193,8 +1193,7 @@ userauth_passwd(Authctxt *authctxt) - { - struct ssh *ssh = active_state; /* XXX */ - static int attempt = 0; -- char prompt[256]; -- char *password; -+ char *password, *prompt = NULL; - const char *host = options.host_key_alias ? options.host_key_alias : - authctxt->host; - int r; -@@ -1205,8 +1204,7 @@ userauth_passwd(Authctxt *authctxt) - if (attempt != 1) - error("Permission denied, please try again."); - -- snprintf(prompt, sizeof(prompt), "%.30s@%.128s's password: ", -- authctxt->server_user, host); -+ xasprintf(&prompt, "%s@%s's password: ", authctxt->server_user, host); - password = read_passphrase(prompt, 0); - if ((r = sshpkt_start(ssh, SSH2_MSG_USERAUTH_REQUEST)) != 0 || - (r = sshpkt_put_cstring(ssh, authctxt->server_user)) != 0 || -@@ -1218,7 +1216,8 @@ userauth_passwd(Authctxt *authctxt) - (r = sshpkt_send(ssh)) != 0) - fatal("%s: %s", __func__, ssh_err(r)); - -- if (password) -+ free(prompt); -+ if (password != NULL) - freezero(password, strlen(password)); - - ssh_dispatch_set(ssh, SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ, --- -1.8.3.1 - diff --git a/upstream-fix-bug-in-HostbasedAcceptedKeyTypes-and.patch b/upstream-fix-bug-in-HostbasedAcceptedKeyTypes-and.patch deleted file mode 100644 index 9ddbb01bed4c9076ec6f25d508a701706fa875f6..0000000000000000000000000000000000000000 --- a/upstream-fix-bug-in-HostbasedAcceptedKeyTypes-and.patch +++ /dev/null @@ -1,80 +0,0 @@ -From e76135e3007f1564427b2956c628923d8dc2f75a Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 16 Nov 2018 02:43:56 +0000 -Subject: [PATCH 110/294] upstream: fix bug in HostbasedAcceptedKeyTypes and - -PubkeyAcceptedKeyTypes options. If only RSA-SHA2 siganture types were -specified, then authentication would always fail for RSA keys as the monitor -checks only the base key (not the signature algorithm) type against -*AcceptedKeyTypes. bz#2746; reported by Jakub Jelen; ok dtucker - -OpenBSD-Commit-ID: 117bc3dc54578dbdb515a1d3732988cb5b00461b ---- - monitor.c | 37 +++++++++++++++++++++++++++++++++---- - 1 file changed, 33 insertions(+), 4 deletions(-) - -diff --git a/monitor.c b/monitor.c -index f56ea85..553e4aa 100644 ---- a/monitor.c -+++ b/monitor.c -@@ -912,6 +912,35 @@ mm_answer_authrole(int sock, struct sshbuf *m) - } - #endif - -+/* -+ * Check that the key type appears in the supplied pattern list, ignoring -+ * mismatches in the signature algorithm. (Signature algorithm checks are -+ * performed in the unprivileged authentication code). -+ * Returns 1 on success, 0 otherwise. -+ */ -+static int -+key_base_type_match(const char *method, const struct sshkey *key, -+ const char *list) -+{ -+ char *s, *l, *ol = xstrdup(list); -+ int found = 0; -+ -+ l = ol; -+ for ((s = strsep(&l, ",")); s && *s != '\0'; (s = strsep(&l, ","))) { -+ if (sshkey_type_from_name(s) == key->type) { -+ found = 1; -+ break; -+ } -+ } -+ if (!found) { -+ error("%s key type %s is not in permitted list %s", method, -+ sshkey_ssh_name(key), list); -+ } -+ -+ free(ol); -+ return found; -+} -+ - int - mm_answer_authpassword(int sock, struct sshbuf *m) - { -@@ -1217,8 +1246,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m) - break; - if (auth2_key_already_used(authctxt, key)) - break; -- if (match_pattern_list(sshkey_ssh_name(key), -- options.pubkey_key_types, 0) != 1) -+ if (!key_base_type_match(auth_method, key, -+ options.pubkey_key_types)) - break; - allowed = user_key_allowed(ssh, authctxt->pw, key, - pubkey_auth_attempt, &opts); -@@ -1229,8 +1258,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m) - break; - if (auth2_key_already_used(authctxt, key)) - break; -- if (match_pattern_list(sshkey_ssh_name(key), -- options.hostbased_key_types, 0) != 1) -+ if (!key_base_type_match(auth_method, key, -+ options.hostbased_key_types)) - break; - allowed = hostbased_key_allowed(authctxt->pw, - cuser, chost, key); --- -1.8.3.1 - diff --git a/upstream-fix-bug-in-client-that-was-keeping-a-redund.patch b/upstream-fix-bug-in-client-that-was-keeping-a-redund.patch deleted file mode 100644 index 3f2a12e03972ed7e9e6d2c61a9a1df643b59e4c6..0000000000000000000000000000000000000000 --- a/upstream-fix-bug-in-client-that-was-keeping-a-redund.patch +++ /dev/null @@ -1,49 +0,0 @@ -From aaed635e3a401cfcc4cc97f33788179c458901c3 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 16 Nov 2018 02:46:20 +0000 -Subject: [PATCH 111/294] upstream: fix bug in client that was keeping a - redundant ssh-agent - -socket around for the life of the connection; bz#2912; reported by Simon -Tatham; ok dtucker@ - -OpenBSD-Commit-ID: 4ded588301183d343dce3e8c5fc1398e35058478 ---- - sshconnect2.c | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/sshconnect2.c b/sshconnect2.c -index 1e894e8..ff450e5 100644 ---- a/sshconnect2.c -+++ b/sshconnect2.c -@@ -583,7 +583,6 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, - - /* setup authentication context */ - memset(&authctxt, 0, sizeof(authctxt)); -- pubkey_prepare(&authctxt); - authctxt.server_user = server_user; - authctxt.local_user = local_user; - authctxt.host = host; -@@ -596,6 +595,7 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host, - authctxt.active_ktype = authctxt.oktypes = authctxt.ktypes = NULL; - authctxt.info_req_seen = 0; - authctxt.agent_fd = -1; -+ pubkey_prepare(&authctxt); - if (authctxt.method == NULL) - fatal("ssh_userauth2: internal error: cannot send userauth none request"); - -@@ -1849,8 +1849,10 @@ pubkey_cleanup(Authctxt *authctxt) - { - Identity *id; - -- if (authctxt->agent_fd != -1) -+ if (authctxt->agent_fd != -1) { - ssh_close_authentication_socket(authctxt->agent_fd); -+ authctxt->agent_fd = -1; -+ } - for (id = TAILQ_FIRST(&authctxt->keys); id; - id = TAILQ_FIRST(&authctxt->keys)) { - TAILQ_REMOVE(&authctxt->keys, id, next); --- -1.8.3.1 - diff --git a/upstream-fix-build-with-DEBUG_PK-enabled.patch b/upstream-fix-build-with-DEBUG_PK-enabled.patch deleted file mode 100644 index 54d291eabf80698ba27ff4833e8e4c5fd27befef..0000000000000000000000000000000000000000 --- a/upstream-fix-build-with-DEBUG_PK-enabled.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 086cc614f550b7d4f100c95e472a6b6b823938ab Mon Sep 17 00:00:00 2001 -From: "mestre@openbsd.org" -Date: Tue, 28 Aug 2018 12:17:45 +0000 -Subject: [PATCH 005/294] upstream: fix build with DEBUG_PK enabled - -OK dtucker@ - -OpenBSD-Commit-ID: ec1568cf27726e9638a0415481c20c406e7b441c ---- - auth2-hostbased.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/auth2-hostbased.c b/auth2-hostbased.c -index 3593932..73944bc 100644 ---- a/auth2-hostbased.c -+++ b/auth2-hostbased.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: auth2-hostbased.c,v 1.36 2018/07/31 03:10:27 djm Exp $ */ -+/* $OpenBSD: auth2-hostbased.c,v 1.37 2018/08/28 12:17:45 mestre Exp $ */ - /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * -@@ -79,7 +79,7 @@ userauth_hostbased(struct ssh *ssh) - cuser, chost, pkalg, slen); - #ifdef DEBUG_PK - debug("signature:"); -- sshbuf_dump_data(sig, siglen, stderr); -+ sshbuf_dump_data(sig, slen, stderr); - #endif - pktype = sshkey_type_from_name(pkalg); - if (pktype == KEY_UNSPEC) { --- -1.8.3.1 - diff --git a/upstream-fix-memory-leak-of-ciphercontext-when-rekey.patch b/upstream-fix-memory-leak-of-ciphercontext-when-rekey.patch deleted file mode 100644 index 291d165ee70af44eedce6e50b6d4a8df0e4a6617..0000000000000000000000000000000000000000 --- a/upstream-fix-memory-leak-of-ciphercontext-when-rekey.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 8a8183474c41bd6cebaa917346b549af2239ba2f Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 4 Jan 2019 03:23:00 +0000 -Subject: [PATCH 148/294] upstream: fix memory leak of ciphercontext when - rekeying; bz#2942 - -Patch from Markus Schmidt; ok markus@ - -OpenBSD-Commit-ID: 7877f1b82e249986f1ef98d0ae76ce987d332bdd ---- - packet.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/packet.c b/packet.c -index 89063f2..046e03f 100644 ---- a/packet.c -+++ b/packet.c -@@ -874,8 +874,6 @@ ssh_set_newkeys(struct ssh *ssh, int mode) - (unsigned long long)state->p_send.bytes, - (unsigned long long)state->p_send.blocks); - audit_session_key_free(mode); -- cipher_free(*ccp); -- *ccp = NULL; - kex_free_newkeys(state->newkeys[mode]); - state->newkeys[mode] = NULL; - } -@@ -894,6 +892,8 @@ ssh_set_newkeys(struct ssh *ssh, int mode) - } - mac->enabled = 1; - DBG(debug("cipher_init_context: %d", mode)); -+ cipher_free(*ccp); -+ *ccp = NULL; - if ((r = cipher_init(ccp, enc->cipher, enc->key, enc->key_len, - enc->iv, enc->iv_len, crypt_type)) != 0) - return r; --- -1.8.3.1 - diff --git a/upstream-fix-misplaced-parenthesis-inside-if-clause..patch b/upstream-fix-misplaced-parenthesis-inside-if-clause..patch deleted file mode 100644 index 29922bfab97156f2f65129d2bd959b103a22e806..0000000000000000000000000000000000000000 --- a/upstream-fix-misplaced-parenthesis-inside-if-clause..patch +++ /dev/null @@ -1,38 +0,0 @@ -From db8bb80e3ac1bcb3e1305d846cd98c6b869bf03f Mon Sep 17 00:00:00 2001 -From: "mestre@openbsd.org" -Date: Tue, 28 Aug 2018 12:25:53 +0000 -Subject: [PATCH 006/294] upstream: fix misplaced parenthesis inside if-clause. - it's harmless - -and the only issue is showing an unknown error (since it's not defined) -during fatal(), if it ever an error occurs inside that condition. - -OK deraadt@ markus@ djm@ - -OpenBSD-Commit-ID: acb0a8e6936bfbe590504752d01d1d251a7101d8 ---- - auth2-pubkey.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/auth2-pubkey.c b/auth2-pubkey.c -index 3d9f9af..f9e4e2e 100644 ---- a/auth2-pubkey.c -+++ b/auth2-pubkey.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: auth2-pubkey.c,v 1.84 2018/08/23 03:01:08 djm Exp $ */ -+/* $OpenBSD: auth2-pubkey.c,v 1.85 2018/08/28 12:25:53 mestre Exp $ */ - /* - * Copyright (c) 2000 Markus Friedl. All rights reserved. - * -@@ -177,7 +177,7 @@ userauth_pubkey(struct ssh *ssh) - (r = sshbuf_put_cstring(b, authctxt->service)) != 0 || - (r = sshbuf_put_cstring(b, "publickey")) != 0 || - (r = sshbuf_put_u8(b, have_sig)) != 0 || -- (r = sshbuf_put_cstring(b, pkalg) != 0) || -+ (r = sshbuf_put_cstring(b, pkalg)) != 0 || - (r = sshbuf_put_string(b, pkblob, blen)) != 0) - fatal("%s: build packet failed: %s", - __func__, ssh_err(r)); --- -1.8.3.1 - diff --git a/upstream-fix-ssh-Q-sig-to-show-correct-signature-alg.patch b/upstream-fix-ssh-Q-sig-to-show-correct-signature-alg.patch deleted file mode 100644 index a0a04e104e99067435a108837afc5bb7154ffad4..0000000000000000000000000000000000000000 --- a/upstream-fix-ssh-Q-sig-to-show-correct-signature-alg.patch +++ /dev/null @@ -1,29 +0,0 @@ -From aa083aa9624ea7b764d5a81c4c676719a1a3e42b Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Thu, 20 Sep 2018 03:31:49 +0000 -Subject: [PATCH 041/294] upstream: fix "ssh -Q sig" to show correct signature - algorithm list - -(it was erroneously showing certificate algorithms); prompted by markus@ - -OpenBSD-Commit-ID: 1cdee002f2f0c21456979deeb887fc889afb154d ---- - ssh.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ssh.c b/ssh.c -index 1101ab2..34301c3 100644 ---- a/ssh.c -+++ b/ssh.c -@@ -750,7 +750,7 @@ main(int ac, char **av) - else if (strcmp(optarg, "key-cert") == 0) - cp = sshkey_alg_list(1, 0, 0, '\n'); - else if (strcmp(optarg, "key-plain") == 0) -- cp = sshkey_alg_list(0, 1, 0, '\n'); -+ cp = sshkey_alg_list(0, 1, 1, '\n'); - else if (strcmp(optarg, "protocol-version") == 0) { - cp = xstrdup("2"); - } --- -1.8.3.1 - diff --git a/upstream-fix-sshd-T-without-C.patch b/upstream-fix-sshd-T-without-C.patch deleted file mode 100644 index a53dbc0df59ebaa70e90b40c5716e0f34ffc9eb6..0000000000000000000000000000000000000000 --- a/upstream-fix-sshd-T-without-C.patch +++ /dev/null @@ -1,168 +0,0 @@ -From: Darren Tucker -Date: 2019-04-18 19:42:28 EST -Subject: [PATCH] ssh-T - ---- - regress/cfgmatch.sh | 47 +++++++++++++++++++++++++++++++++++++++++++-- - servconf.c | 14 ++++++++------ - servconf.h | 2 ++ - sshd.c | 1 + - 4 files changed, 56 insertions(+), 8 deletions(-) - -diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh -index dd11e40..37fe6f8 100644 ---- a/regress/cfgmatch.sh -+++ b/regress/cfgmatch.sh -@@ -51,9 +51,10 @@ echo "AuthorizedKeysFile /dev/null $OBJ/authorized_keys_%u" >>$OBJ/sshd_proxy - echo "Match Address 127.0.0.1" >>$OBJ/sshd_proxy - echo "PermitOpen 127.0.0.1:2 127.0.0.1:3 127.0.0.1:$PORT" >>$OBJ/sshd_proxy - --start_sshd -+${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \ -+ fail "config w/match fails config test" - --#set -x -+start_sshd - - # Test Match + PermitOpen in sshd_config. This should be permitted - trace "match permitopen localhost" -@@ -113,3 +114,45 @@ start_client -F $OBJ/ssh_proxy - ${SSH} -q -p $fwdport -F $OBJ/ssh_config somehost true || \ - fail "nomatch override permitopen" - stop_client -+ -+ -+# Test parsing of available Match criteria (with the exception of Group which -+# requires knowledge of actual group memberships user running the test). -+params="user:user:u1 host:host:h1 address:addr:1.2.3.4 \ -+ localaddress:laddr:5.6.7.8 rdomain:rdomain:rdom1" -+cp $OBJ/sshd_proxy_bak $OBJ/sshd_config -+echo 'Banner /nomatch' >>$OBJ/sshd_config -+for i in $params; do -+ config=`echo $i | cut -f1 -d:` -+ criteria=`echo $i | cut -f2 -d:` -+ value=`echo $i | cut -f3 -d:` -+ cat >>$OBJ/sshd_config </dev/null || \ -+ fail "validate config for w/out spec" -+ -+# Test matching each criteria. -+for i in $params; do -+ testcriteria=`echo $i | cut -f2 -d:` -+ expected=/`echo $i | cut -f3 -d:` -+ spec="" -+ for j in $params; do -+ config=`echo $j | cut -f1 -d:` -+ criteria=`echo $j | cut -f2 -d:` -+ value=`echo $j | cut -f3 -d:` -+ if [ "$criteria" = "$testcriteria" ]; then -+ spec="$criteria=$value,$spec" -+ else -+ spec="$criteria=1$value,$spec" -+ fi -+ done -+ trace "test spec $spec" -+ result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \ -+ awk '$1=="banner"{print $2}'` -+ if [ "$result" != "$expected" ]; then -+ fail "match $config expected $expected got $result" -+ fi -+done -diff --git a/servconf.c b/servconf.c -index 434f0bc..9f363c9 100644 ---- a/servconf.c -+++ b/servconf.c -@@ -1075,7 +1075,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - return -1; - } - if (strcasecmp(attrib, "user") == 0) { -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->user == NULL)) { - result = 0; - continue; - } -@@ -1087,7 +1087,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - debug("user %.100s matched 'User %.100s' at " - "line %d", ci->user, arg, line); - } else if (strcasecmp(attrib, "group") == 0) { -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->user == NULL)) { - result = 0; - continue; - } -@@ -1100,7 +1100,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - result = 0; - } - } else if (strcasecmp(attrib, "host") == 0) { -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->host == NULL)) { - result = 0; - continue; - } -@@ -1112,7 +1112,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - debug("connection from %.100s matched 'Host " - "%.100s' at line %d", ci->host, arg, line); - } else if (strcasecmp(attrib, "address") == 0) { -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->address == NULL)) { - result = 0; - continue; - } -@@ -1131,7 +1131,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - return -1; - } - } else if (strcasecmp(attrib, "localaddress") == 0){ -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->laddress == NULL)) { - result = 0; - continue; - } -@@ -1157,7 +1157,7 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - arg); - return -1; - } -- if (ci == NULL) { -+ if (ci == NULL || (ci->test && ci->lport == -1)) { - result = 0; - continue; - } -@@ -1175,6 +1175,8 @@ match_cfg_line(char **condition, int line, struct connection_info *ci) - result = 0; - continue; - } -+ if (ci->rdomain == NULL) -+ match_test_missing_fatal("RDomain", "rdomain"); - if (match_pattern_list(ci->rdomain, arg, 0) != 1) - result = 0; - else -diff --git a/servconf.h b/servconf.h -index fdbae24..381ed25 100644 ---- a/servconf.h -+++ b/servconf.h -@@ -231,6 +231,8 @@ struct connection_info { - const char *laddress; /* local address */ - int lport; /* local port */ - const char *rdomain; /* routing domain if available */ -+ int test; /* test mode, allow some attributes to be -+ * unspecified */ - }; - - -diff --git a/sshd.c b/sshd.c -index 6d081e4..a00b1af 100644 ---- a/sshd.c -+++ b/sshd.c -@@ -2001,6 +2001,7 @@ main(int ac, char **av) - */ - if (connection_info == NULL) - connection_info = get_connection_info(0, 0); -+ connection_info->test = 1; - parse_server_match_config(&options, connection_info); - dump_config(&options); - } --- -2.19.1 diff --git a/upstream-make-grandparent-parent-child-sshbuf-chains.patch b/upstream-make-grandparent-parent-child-sshbuf-chains.patch deleted file mode 100644 index 5ece0ce86bfd9a01f5c2885ce8024a33919c1406..0000000000000000000000000000000000000000 --- a/upstream-make-grandparent-parent-child-sshbuf-chains.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 15182fd96845a03216d7ac5a2cf31c4e77e406e3 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 16 Nov 2018 06:10:29 +0000 -Subject: [PATCH 115/294] upstream: make grandparent-parent-child sshbuf chains - robust to - -use-after-free faults if the ancestors are freed before the descendents. -Nothing in OpenSSH uses this deallocation pattern. Reported by Jann Horn - -OpenBSD-Commit-ID: d93501d1d2734245aac802a252b9bb2eccdba0f2 ---- - sshbuf.c | 17 ++++++++++------- - 1 file changed, 10 insertions(+), 7 deletions(-) - -diff --git a/sshbuf.c b/sshbuf.c -index 20ddf9e..adfddf7 100644 ---- a/sshbuf.c -+++ b/sshbuf.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: sshbuf.c,v 1.12 2018/07/09 21:56:06 markus Exp $ */ -+/* $OpenBSD: sshbuf.c,v 1.13 2018/11/16 06:10:29 djm Exp $ */ - /* - * Copyright (c) 2011 Damien Miller - * -@@ -143,12 +143,7 @@ sshbuf_free(struct sshbuf *buf) - */ - if (sshbuf_check_sanity(buf) != 0) - return; -- /* -- * If we are a child, the free our parent to decrement its reference -- * count and possibly free it. -- */ -- sshbuf_free(buf->parent); -- buf->parent = NULL; -+ - /* - * If we are a parent with still-extant children, then don't free just - * yet. The last child's call to sshbuf_free should decrement our -@@ -157,6 +152,14 @@ sshbuf_free(struct sshbuf *buf) - buf->refcount--; - if (buf->refcount > 0) - return; -+ -+ /* -+ * If we are a child, the free our parent to decrement its reference -+ * count and possibly free it. -+ */ -+ sshbuf_free(buf->parent); -+ buf->parent = NULL; -+ - if (!buf->readonly) { - explicit_bzero(buf->d, buf->alloc); - free(buf->d); --- -1.8.3.1 - diff --git a/upstream-only-consider-the-ext-info-c-extension-duri.patch b/upstream-only-consider-the-ext-info-c-extension-duri.patch deleted file mode 100644 index 93e8d03393e2cf747ee5458b683c0b949cebbddc..0000000000000000000000000000000000000000 --- a/upstream-only-consider-the-ext-info-c-extension-duri.patch +++ /dev/null @@ -1,74 +0,0 @@ -From a6a0788cbbe8dfce2819ee43b09c80725742e21c Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 7 Dec 2018 03:39:40 +0000 -Subject: [PATCH 141/294] upstream: only consider the ext-info-c extension - during the initial - -KEX. It shouldn't be sent in subsequent ones, but if it is present we should -ignore it. - -This prevents sshd from sending a SSH_MSG_EXT_INFO for REKEX for buggy -these clients. Reported by Jakub Jelen via bz2929; ok dtucker@ - -OpenBSD-Commit-ID: 91564118547f7807030ec537480303e2371902f9 ---- - kex.c | 6 ++++-- - kex.h | 3 ++- - 2 files changed, 6 insertions(+), 3 deletions(-) - -diff --git a/kex.c b/kex.c -index 25f9f66..3823a95 100644 ---- a/kex.c -+++ b/kex.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: kex.c,v 1.141 2018/07/09 13:37:10 sf Exp $ */ -+/* $OpenBSD: kex.c,v 1.142 2018/12/07 03:39:40 djm Exp $ */ - /* - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. - * -@@ -487,6 +487,7 @@ kex_input_newkeys(int type, u_int32_t seq, struct ssh *ssh) - if ((r = ssh_set_newkeys(ssh, MODE_IN)) != 0) - return r; - kex->done = 1; -+ kex->flags &= ~KEX_INITIAL; - sshbuf_reset(kex->peer); - /* sshbuf_reset(kex->my); */ - kex->flags &= ~KEX_INIT_SENT; -@@ -594,6 +595,7 @@ kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp) - if ((r = kex_prop2buf(kex->my, proposal)) != 0) - goto out; - kex->done = 0; -+ kex->flags = KEX_INITIAL; - kex_reset_dispatch(ssh); - ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit); - r = 0; -@@ -839,7 +841,7 @@ kex_choose_conf(struct ssh *ssh) - } - - /* Check whether client supports ext_info_c */ -- if (kex->server) { -+ if (kex->server && (kex->flags & KEX_INITIAL)) { - char *ext; - - ext = match_list("ext-info-c", peer[PROPOSAL_KEX_ALGS], NULL); -diff --git a/kex.h b/kex.h -index 593de12..0f67f58 100644 ---- a/kex.h -+++ b/kex.h -@@ -1,4 +1,4 @@ --/* $OpenBSD: kex.h,v 1.91 2018/07/11 18:53:29 markus Exp $ */ -+/* $OpenBSD: kex.h,v 1.92 2018/12/07 03:39:40 djm Exp $ */ - - /* - * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. -@@ -104,6 +104,7 @@ enum kex_exchange { - }; - - #define KEX_INIT_SENT 0x0001 -+#define KEX_INITIAL 0x0002 - - struct sshenc { - char *name; --- -1.8.3.1 - diff --git a/upstream-typo-in-error-message-caught-by-Debian-lint.patch b/upstream-typo-in-error-message-caught-by-Debian-lint.patch deleted file mode 100644 index 7654663a084161df845040558c4020d0f2ca205c..0000000000000000000000000000000000000000 --- a/upstream-typo-in-error-message-caught-by-Debian-lint.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 960e7c672dc106f3b759c081de3edb4d1138b36e Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Fri, 9 Nov 2018 02:57:58 +0000 -Subject: [PATCH 107/294] upstream: typo in error message; caught by Debian - lintian, via - -Colin Watson - -OpenBSD-Commit-ID: bff614c7bd1f4ca491a84e9b5999f848d0d66758 ---- - ssh-agent.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ssh-agent.c b/ssh-agent.c -index d8a8260..cb55246 100644 ---- a/ssh-agent.c -+++ b/ssh-agent.c -@@ -1,4 +1,4 @@ --/* $OpenBSD: ssh-agent.c,v 1.231 2018/05/11 03:38:51 djm Exp $ */ -+/* $OpenBSD: ssh-agent.c,v 1.232 2018/11/09 02:57:58 djm Exp $ */ - /* - * Author: Tatu Ylonen - * Copyright (c) 1995 Tatu Ylonen , Espoo, Finland -@@ -1199,7 +1199,7 @@ main(int ac, char **av) - */ - #define SSH_AGENT_MIN_FDS (3+1+1+1+4) - if (rlim.rlim_cur < SSH_AGENT_MIN_FDS) -- fatal("%s: file descriptior rlimit %lld too low (minimum %u)", -+ fatal("%s: file descriptor rlimit %lld too low (minimum %u)", - __progname, (long long)rlim.rlim_cur, SSH_AGENT_MIN_FDS); - maxfds = rlim.rlim_cur - SSH_AGENT_MIN_FDS; - --- -1.8.3.1 - diff --git a/upstream-typo-in-plain-RSA-algorithm-counterpart-nam.patch b/upstream-typo-in-plain-RSA-algorithm-counterpart-nam.patch deleted file mode 100644 index b81835f5887a0fe2a67d6442531756bc5e4c61c9..0000000000000000000000000000000000000000 --- a/upstream-typo-in-plain-RSA-algorithm-counterpart-nam.patch +++ /dev/null @@ -1,32 +0,0 @@ -From ebfafd9c7a5b2a7fb515ee95dbe0e44e11d0a663 Mon Sep 17 00:00:00 2001 -From: "djm@openbsd.org" -Date: Thu, 11 Oct 2018 00:52:46 +0000 -Subject: [PATCH 069/294] upstream: typo in plain RSA algorithm counterpart - names for - -certificates; spotted by Adam Eijdenberg; ok dtucker@ - -OpenBSD-Commit-ID: bfcdeb6f4fc9e7607f5096574c8f118f2e709e00 ---- - sshkey.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/sshkey.c b/sshkey.c -index ed57d30..5807627 100644 ---- a/sshkey.c -+++ b/sshkey.c -@@ -118,9 +118,9 @@ static const struct keytype keytypes[] = { - { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, - KEY_RSA_CERT, 0, 1, 0 }, - { "rsa-sha2-256-cert-v01@openssh.com", "RSA-CERT", -- "ssh-rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 }, -+ "rsa-sha2-256", KEY_RSA_CERT, 0, 1, 1 }, - { "rsa-sha2-512-cert-v01@openssh.com", "RSA-CERT", -- "ssh-rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 }, -+ "rsa-sha2-512", KEY_RSA_CERT, 0, 1, 1 }, - { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", NULL, - KEY_DSA_CERT, 0, 1, 0 }, - { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", NULL, --- -1.8.3.1 -