summaryrefslogtreecommitdiff
path: root/debian/patches
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2019-06-05 06:41:44 +0100
committerColin Watson <cjwatson@debian.org>2019-06-09 22:09:07 +0100
commit865a97e05b6aab1619e1c8eeb33ccb8f9a9e48d3 (patch)
tree7bb2128eb663180bacfabca88f26d26bf0733824 /debian/patches
parentba627ba172d6649919baedff5ba2789610da382a (diff)
parent7d50f9e5be88179325983a1f58c9d51bb58f025a (diff)
New upstream release (8.0p1)
Diffstat (limited to 'debian/patches')
-rw-r--r--debian/patches/authorized-keys-man-symlink.patch6
-rw-r--r--debian/patches/check-filenames-in-scp-client.patch187
-rw-r--r--debian/patches/conch-old-privkey-format.patch8
-rw-r--r--debian/patches/debian-banner.patch94
-rw-r--r--debian/patches/debian-config.patch22
-rw-r--r--debian/patches/dnssec-sshfp.patch2
-rw-r--r--debian/patches/doc-hash-tab-completion.patch6
-rw-r--r--debian/patches/fix-key-type-check.patch88
-rw-r--r--debian/patches/gnome-ssh-askpass2-icon.patch2
-rw-r--r--debian/patches/gssapi.patch2539
-rw-r--r--debian/patches/have-progressmeter-force-update-at-beginning-and-end-transfer.patch120
-rw-r--r--debian/patches/keepalive-extensions.patch24
-rw-r--r--debian/patches/mention-ssh-keygen-on-keychange.patch8
-rw-r--r--debian/patches/no-openssl-version-status.patch4
-rw-r--r--debian/patches/openbsd-docs.patch18
-rw-r--r--debian/patches/package-versioning.patch54
-rw-r--r--debian/patches/request-rsa-sha2-cert-signatures.patch39
-rw-r--r--debian/patches/restore-authorized_keys2.patch2
-rw-r--r--debian/patches/restore-tcp-wrappers.patch16
-rw-r--r--debian/patches/revert-ipqos-defaults.patch18
-rw-r--r--debian/patches/sanitize-scp-filenames-via-snmprintf.patch276
-rw-r--r--debian/patches/scp-disallow-dot-or-empty-filename.patch32
-rw-r--r--debian/patches/scp-handle-braces.patch353
-rw-r--r--debian/patches/scp-quoting.patch6
-rw-r--r--debian/patches/seccomp-s390-flock-ipc.patch2
-rw-r--r--debian/patches/seccomp-s390-ioctl-ep11-crypto.patch2
-rw-r--r--debian/patches/selinux-role.patch98
-rw-r--r--debian/patches/series7
-rw-r--r--debian/patches/shell-path.patch8
-rw-r--r--debian/patches/ssh-agent-setgid.patch2
-rw-r--r--debian/patches/ssh-argv0.patch6
-rw-r--r--debian/patches/ssh-vulnkey-compat.patch10
-rw-r--r--debian/patches/syslog-level-silent.patch6
-rw-r--r--debian/patches/systemd-readiness.patch12
-rw-r--r--debian/patches/user-group-modes.patch34
35 files changed, 1891 insertions, 2220 deletions
diff --git a/debian/patches/authorized-keys-man-symlink.patch b/debian/patches/authorized-keys-man-symlink.patch
index c895e63db..3e5fac6e1 100644
--- a/debian/patches/authorized-keys-man-symlink.patch
+++ b/debian/patches/authorized-keys-man-symlink.patch
@@ -1,4 +1,4 @@
1From 67a6cbb29f77920718884e783238f4a00fe64001 Mon Sep 17 00:00:00 2001 1From f9a76ef65bfb6c17d613ab3db2bf39db5087adfc Mon Sep 17 00:00:00 2001
2From: Tomas Pospisek <tpo_deb@sourcepole.ch> 2From: Tomas Pospisek <tpo_deb@sourcepole.ch>
3Date: Sun, 9 Feb 2014 16:10:07 +0000 3Date: Sun, 9 Feb 2014 16:10:07 +0000
4Subject: Install authorized_keys(5) as a symlink to sshd(8) 4Subject: Install authorized_keys(5) as a symlink to sshd(8)
@@ -13,10 +13,10 @@ Patch-Name: authorized-keys-man-symlink.patch
13 1 file changed, 1 insertion(+) 13 1 file changed, 1 insertion(+)
14 14
15diff --git a/Makefile.in b/Makefile.in 15diff --git a/Makefile.in b/Makefile.in
16index 70050ffb6..ee166114d 100644 16index c31821acc..0960a6a03 100644
17--- a/Makefile.in 17--- a/Makefile.in
18+++ b/Makefile.in 18+++ b/Makefile.in
19@@ -356,6 +356,7 @@ install-files: 19@@ -357,6 +357,7 @@ install-files:
20 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 20 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
21 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 21 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
22 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 22 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
diff --git a/debian/patches/check-filenames-in-scp-client.patch b/debian/patches/check-filenames-in-scp-client.patch
deleted file mode 100644
index 519358ce6..000000000
--- a/debian/patches/check-filenames-in-scp-client.patch
+++ /dev/null
@@ -1,187 +0,0 @@
1From 125924e47db3713a85a70e0f8d6c23818d2ea054 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Sat, 26 Jan 2019 22:41:28 +0000
4Subject: upstream: check in scp client that filenames sent during
5
6remote->local directory copies satisfy the wildcard specified by the user.
7
8This checking provides some protection against a malicious server
9sending unexpected filenames, but it comes at a risk of rejecting wanted
10files due to differences between client and server wildcard expansion rules.
11
12For this reason, this also adds a new -T flag to disable the check.
13
14reported by Harry Sintonen
15fix approach suggested by markus@;
16has been in snaps for ~1wk courtesy deraadt@
17
18OpenBSD-Commit-ID: 00f44b50d2be8e321973f3c6d014260f8f7a8eda
19
20CVE-2019-6111
21
22Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=391ffc4b9d31fa1f4ad566499fef9176ff8a07dc
23Last-Update: 2019-02-08
24
25Patch-Name: check-filenames-in-scp-client.patch
26---
27 scp.1 | 12 +++++++++++-
28 scp.c | 37 +++++++++++++++++++++++++++++--------
29 2 files changed, 40 insertions(+), 9 deletions(-)
30
31diff --git a/scp.1 b/scp.1
32index 0e5cc1b2d..397e77091 100644
33--- a/scp.1
34+++ b/scp.1
35@@ -18,7 +18,7 @@
36 .Nd secure copy (remote file copy program)
37 .Sh SYNOPSIS
38 .Nm scp
39-.Op Fl 346BCpqrv
40+.Op Fl 346BCpqrTv
41 .Op Fl c Ar cipher
42 .Op Fl F Ar ssh_config
43 .Op Fl i Ar identity_file
44@@ -208,6 +208,16 @@ to use for the encrypted connection.
45 The program must understand
46 .Xr ssh 1
47 options.
48+.It Fl T
49+Disable strict filename checking.
50+By default when copying files from a remote host to a local directory
51+.Nm
52+checks that the received filenames match those requested on the command-line
53+to prevent the remote end from sending unexpected or unwanted files.
54+Because of differences in how various operating systems and shells interpret
55+filename wildcards, these checks may cause wanted files to be rejected.
56+This option disables these checks at the expense of fully trusting that
57+the server will not send unexpected filenames.
58 .It Fl v
59 Verbose mode.
60 Causes
61diff --git a/scp.c b/scp.c
62index 1971c80cd..035037bcc 100644
63--- a/scp.c
64+++ b/scp.c
65@@ -94,6 +94,7 @@
66 #include <dirent.h>
67 #include <errno.h>
68 #include <fcntl.h>
69+#include <fnmatch.h>
70 #include <limits.h>
71 #include <locale.h>
72 #include <pwd.h>
73@@ -383,14 +384,14 @@ void verifydir(char *);
74 struct passwd *pwd;
75 uid_t userid;
76 int errs, remin, remout;
77-int pflag, iamremote, iamrecursive, targetshouldbedirectory;
78+int Tflag, pflag, iamremote, iamrecursive, targetshouldbedirectory;
79
80 #define CMDNEEDS 64
81 char cmd[CMDNEEDS]; /* must hold "rcp -r -p -d\0" */
82
83 int response(void);
84 void rsource(char *, struct stat *);
85-void sink(int, char *[]);
86+void sink(int, char *[], const char *);
87 void source(int, char *[]);
88 void tolocal(int, char *[]);
89 void toremote(int, char *[]);
90@@ -429,8 +430,9 @@ main(int argc, char **argv)
91 addargs(&args, "-oRemoteCommand=none");
92 addargs(&args, "-oRequestTTY=no");
93
94- fflag = tflag = 0;
95- while ((ch = getopt(argc, argv, "dfl:prtvBCc:i:P:q12346S:o:F:")) != -1)
96+ fflag = Tflag = tflag = 0;
97+ while ((ch = getopt(argc, argv,
98+ "dfl:prtTvBCc:i:P:q12346S:o:F:")) != -1) {
99 switch (ch) {
100 /* User-visible flags. */
101 case '1':
102@@ -509,9 +511,13 @@ main(int argc, char **argv)
103 setmode(0, O_BINARY);
104 #endif
105 break;
106+ case 'T':
107+ Tflag = 1;
108+ break;
109 default:
110 usage();
111 }
112+ }
113 argc -= optind;
114 argv += optind;
115
116@@ -542,7 +548,7 @@ main(int argc, char **argv)
117 }
118 if (tflag) {
119 /* Receive data. */
120- sink(argc, argv);
121+ sink(argc, argv, NULL);
122 exit(errs != 0);
123 }
124 if (argc < 2)
125@@ -800,7 +806,7 @@ tolocal(int argc, char **argv)
126 continue;
127 }
128 free(bp);
129- sink(1, argv + argc - 1);
130+ sink(1, argv + argc - 1, src);
131 (void) close(remin);
132 remin = remout = -1;
133 }
134@@ -976,7 +982,7 @@ rsource(char *name, struct stat *statp)
135 (sizeof(type) != 4 && sizeof(type) != 8))
136
137 void
138-sink(int argc, char **argv)
139+sink(int argc, char **argv, const char *src)
140 {
141 static BUF buffer;
142 struct stat stb;
143@@ -992,6 +998,7 @@ sink(int argc, char **argv)
144 unsigned long long ull;
145 int setimes, targisdir, wrerrno = 0;
146 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
147+ char *src_copy = NULL, *restrict_pattern = NULL;
148 struct timeval tv[2];
149
150 #define atime tv[0]
151@@ -1016,6 +1023,17 @@ sink(int argc, char **argv)
152 (void) atomicio(vwrite, remout, "", 1);
153 if (stat(targ, &stb) == 0 && S_ISDIR(stb.st_mode))
154 targisdir = 1;
155+ if (src != NULL && !iamrecursive && !Tflag) {
156+ /*
157+ * Prepare to try to restrict incoming filenames to match
158+ * the requested destination file glob.
159+ */
160+ if ((src_copy = strdup(src)) == NULL)
161+ fatal("strdup failed");
162+ if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
163+ *restrict_pattern++ = '\0';
164+ }
165+ }
166 for (first = 1;; first = 0) {
167 cp = buf;
168 if (atomicio(read, remin, cp, 1) != 1)
169@@ -1120,6 +1138,9 @@ sink(int argc, char **argv)
170 run_err("error: unexpected filename: %s", cp);
171 exit(1);
172 }
173+ if (restrict_pattern != NULL &&
174+ fnmatch(restrict_pattern, cp, 0) != 0)
175+ SCREWUP("filename does not match request");
176 if (targisdir) {
177 static char *namebuf;
178 static size_t cursize;
179@@ -1157,7 +1178,7 @@ sink(int argc, char **argv)
180 goto bad;
181 }
182 vect[0] = xstrdup(np);
183- sink(1, vect);
184+ sink(1, vect, src);
185 if (setimes) {
186 setimes = 0;
187 if (utimes(vect[0], tv) < 0)
diff --git a/debian/patches/conch-old-privkey-format.patch b/debian/patches/conch-old-privkey-format.patch
index 90bb3e995..40fe32898 100644
--- a/debian/patches/conch-old-privkey-format.patch
+++ b/debian/patches/conch-old-privkey-format.patch
@@ -1,4 +1,4 @@
1From 1d2a55436d4b556269f42ad5f7e16608b5a8ed74 Mon Sep 17 00:00:00 2001 1From 9c01e0ae9889c05bfe68b2f1f1c5e5019e63ff0b Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Thu, 30 Aug 2018 00:58:56 +0100 3Date: Thu, 30 Aug 2018 00:58:56 +0100
4Subject: Work around conch interoperability failure 4Subject: Work around conch interoperability failure
@@ -18,7 +18,7 @@ Patch-Name: conch-old-privkey-format.patch
18 3 files changed, 16 insertions(+), 3 deletions(-) 18 3 files changed, 16 insertions(+), 3 deletions(-)
19 19
20diff --git a/regress/Makefile b/regress/Makefile 20diff --git a/regress/Makefile b/regress/Makefile
21index 647b4a049..6e462a4f6 100644 21index 925edf71a..6fdfcc8ca 100644
22--- a/regress/Makefile 22--- a/regress/Makefile
23+++ b/regress/Makefile 23+++ b/regress/Makefile
24@@ -110,8 +110,9 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \ 24@@ -110,8 +110,9 @@ CLEANFILES= *.core actual agent-key.* authorized_keys_${USERNAME} \
@@ -47,10 +47,10 @@ index 199d863a0..c7df19fd4 100644
47 127.0.0.1 "cat ${DATA}" 2>/dev/null | cat > ${COPY} 47 127.0.0.1 "cat ${DATA}" 2>/dev/null | cat > ${COPY}
48 if [ $? -ne 0 ]; then 48 if [ $? -ne 0 ]; then
49diff --git a/regress/test-exec.sh b/regress/test-exec.sh 49diff --git a/regress/test-exec.sh b/regress/test-exec.sh
50index 40d46e3cd..1bbd47f25 100644 50index b8e2009de..08338121b 100644
51--- a/regress/test-exec.sh 51--- a/regress/test-exec.sh
52+++ b/regress/test-exec.sh 52+++ b/regress/test-exec.sh
53@@ -504,6 +504,18 @@ REGRESS_INTEROP_CONCH=no 53@@ -500,6 +500,18 @@ REGRESS_INTEROP_CONCH=no
54 if test -x "$CONCH" ; then 54 if test -x "$CONCH" ; then
55 REGRESS_INTEROP_CONCH=yes 55 REGRESS_INTEROP_CONCH=yes
56 fi 56 fi
diff --git a/debian/patches/debian-banner.patch b/debian/patches/debian-banner.patch
index 7963b03ed..61e58e553 100644
--- a/debian/patches/debian-banner.patch
+++ b/debian/patches/debian-banner.patch
@@ -1,4 +1,4 @@
1From a18385c6866da4d69f46b64626ae5d60b4cf4a66 Mon Sep 17 00:00:00 2001 1From 085c44daefaee16df97e1b2a0967b2140cc86de0 Mon Sep 17 00:00:00 2001
2From: Kees Cook <kees@debian.org> 2From: Kees Cook <kees@debian.org>
3Date: Sun, 9 Feb 2014 16:10:06 +0000 3Date: Sun, 9 Feb 2014 16:10:06 +0000
4Subject: Add DebianBanner server configuration option 4Subject: Add DebianBanner server configuration option
@@ -8,21 +8,60 @@ initial protocol handshake, for those scared by package-versioning.patch.
8 8
9Bug-Debian: http://bugs.debian.org/562048 9Bug-Debian: http://bugs.debian.org/562048
10Forwarded: not-needed 10Forwarded: not-needed
11Last-Update: 2018-10-19 11Last-Update: 2019-06-05
12 12
13Patch-Name: debian-banner.patch 13Patch-Name: debian-banner.patch
14--- 14---
15 kex.c | 5 +++--
16 kex.h | 2 +-
15 servconf.c | 9 +++++++++ 17 servconf.c | 9 +++++++++
16 servconf.h | 2 ++ 18 servconf.h | 2 ++
19 sshconnect.c | 2 +-
17 sshd.c | 3 ++- 20 sshd.c | 3 ++-
18 sshd_config.5 | 5 +++++ 21 sshd_config.5 | 5 +++++
19 4 files changed, 18 insertions(+), 1 deletion(-) 22 7 files changed, 23 insertions(+), 5 deletions(-)
20 23
24diff --git a/kex.c b/kex.c
25index be354206d..bbb7a2340 100644
26--- a/kex.c
27+++ b/kex.c
28@@ -1168,7 +1168,7 @@ send_error(struct ssh *ssh, char *msg)
29 */
30 int
31 kex_exchange_identification(struct ssh *ssh, int timeout_ms,
32- const char *version_addendum)
33+ int debian_banner, const char *version_addendum)
34 {
35 int remote_major, remote_minor, mismatch;
36 size_t len, i, n;
37@@ -1186,7 +1186,8 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
38 if (version_addendum != NULL && *version_addendum == '\0')
39 version_addendum = NULL;
40 if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n",
41- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_RELEASE,
42+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2,
43+ debian_banner ? SSH_RELEASE : SSH_RELEASE_MINIMUM,
44 version_addendum == NULL ? "" : " ",
45 version_addendum == NULL ? "" : version_addendum)) != 0) {
46 error("%s: sshbuf_putf: %s", __func__, ssh_err(r));
47diff --git a/kex.h b/kex.h
48index 2d5f1d4ed..39f67bbc1 100644
49--- a/kex.h
50+++ b/kex.h
51@@ -195,7 +195,7 @@ char *kex_names_cat(const char *, const char *);
52 int kex_assemble_names(char **, const char *, const char *);
53 int kex_gss_names_valid(const char *);
54
55-int kex_exchange_identification(struct ssh *, int, const char *);
56+int kex_exchange_identification(struct ssh *, int, int, const char *);
57
58 struct kex *kex_new(void);
59 int kex_ready(struct ssh *, char *[PROPOSAL_MAX]);
21diff --git a/servconf.c b/servconf.c 60diff --git a/servconf.c b/servconf.c
22index 6caf1db38..c5dd617ef 100644 61index c01e0690e..8d2bced52 100644
23--- a/servconf.c 62--- a/servconf.c
24+++ b/servconf.c 63+++ b/servconf.c
25@@ -182,6 +182,7 @@ initialize_server_options(ServerOptions *options) 64@@ -184,6 +184,7 @@ initialize_server_options(ServerOptions *options)
26 options->fingerprint_hash = -1; 65 options->fingerprint_hash = -1;
27 options->disable_forwarding = -1; 66 options->disable_forwarding = -1;
28 options->expose_userauth_info = -1; 67 options->expose_userauth_info = -1;
@@ -30,7 +69,7 @@ index 6caf1db38..c5dd617ef 100644
30 } 69 }
31 70
32 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */ 71 /* Returns 1 if a string option is unset or set to "none" or 0 otherwise. */
33@@ -417,6 +418,8 @@ fill_default_server_options(ServerOptions *options) 72@@ -437,6 +438,8 @@ fill_default_server_options(ServerOptions *options)
34 options->disable_forwarding = 0; 73 options->disable_forwarding = 0;
35 if (options->expose_userauth_info == -1) 74 if (options->expose_userauth_info == -1)
36 options->expose_userauth_info = 0; 75 options->expose_userauth_info = 0;
@@ -39,7 +78,7 @@ index 6caf1db38..c5dd617ef 100644
39 78
40 assemble_algorithms(options); 79 assemble_algorithms(options);
41 80
42@@ -504,6 +507,7 @@ typedef enum { 81@@ -523,6 +526,7 @@ typedef enum {
43 sStreamLocalBindMask, sStreamLocalBindUnlink, 82 sStreamLocalBindMask, sStreamLocalBindUnlink,
44 sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding, 83 sAllowStreamLocalForwarding, sFingerprintHash, sDisableForwarding,
45 sExposeAuthInfo, sRDomain, 84 sExposeAuthInfo, sRDomain,
@@ -47,7 +86,7 @@ index 6caf1db38..c5dd617ef 100644
47 sDeprecated, sIgnore, sUnsupported 86 sDeprecated, sIgnore, sUnsupported
48 } ServerOpCodes; 87 } ServerOpCodes;
49 88
50@@ -661,6 +665,7 @@ static struct { 89@@ -682,6 +686,7 @@ static struct {
51 { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL }, 90 { "exposeauthinfo", sExposeAuthInfo, SSHCFG_ALL },
52 { "rdomain", sRDomain, SSHCFG_ALL }, 91 { "rdomain", sRDomain, SSHCFG_ALL },
53 { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL }, 92 { "casignaturealgorithms", sCASignatureAlgorithms, SSHCFG_ALL },
@@ -55,7 +94,7 @@ index 6caf1db38..c5dd617ef 100644
55 { NULL, sBadOption, 0 } 94 { NULL, sBadOption, 0 }
56 }; 95 };
57 96
58@@ -2173,6 +2178,10 @@ process_server_config_line(ServerOptions *options, char *line, 97@@ -2211,6 +2216,10 @@ process_server_config_line(ServerOptions *options, char *line,
59 *charptr = xstrdup(arg); 98 *charptr = xstrdup(arg);
60 break; 99 break;
61 100
@@ -67,10 +106,10 @@ index 6caf1db38..c5dd617ef 100644
67 case sIgnore: 106 case sIgnore:
68 case sUnsupported: 107 case sUnsupported:
69diff --git a/servconf.h b/servconf.h 108diff --git a/servconf.h b/servconf.h
70index 3b76da816..4e3c54042 100644 109index a476d5220..986093ffa 100644
71--- a/servconf.h 110--- a/servconf.h
72+++ b/servconf.h 111+++ b/servconf.h
73@@ -212,6 +212,8 @@ typedef struct { 112@@ -214,6 +214,8 @@ typedef struct {
74 int fingerprint_hash; 113 int fingerprint_hash;
75 int expose_userauth_info; 114 int expose_userauth_info;
76 u_int64_t timing_secret; 115 u_int64_t timing_secret;
@@ -79,22 +118,35 @@ index 3b76da816..4e3c54042 100644
79 } ServerOptions; 118 } ServerOptions;
80 119
81 /* Information about the incoming connection as used by Match */ 120 /* Information about the incoming connection as used by Match */
121diff --git a/sshconnect.c b/sshconnect.c
122index 0b6f6af4b..1183ffe0e 100644
123--- a/sshconnect.c
124+++ b/sshconnect.c
125@@ -1287,7 +1287,7 @@ ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
126 lowercase(host);
127
128 /* Exchange protocol version identification strings with the server. */
129- if (kex_exchange_identification(ssh, timeout_ms, NULL) != 0)
130+ if (kex_exchange_identification(ssh, timeout_ms, 1, NULL) != 0)
131 cleanup_exit(255); /* error already logged */
132
133 /* Put the connection into non-blocking mode. */
82diff --git a/sshd.c b/sshd.c 134diff --git a/sshd.c b/sshd.c
83index 9481272fc..d7e77d343 100644 135index e3e96426e..1e7ece588 100644
84--- a/sshd.c 136--- a/sshd.c
85+++ b/sshd.c 137+++ b/sshd.c
86@@ -384,7 +384,8 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out) 138@@ -2160,7 +2160,8 @@ main(int ac, char **av)
87 char remote_version[256]; /* Must be at least as big as buf. */ 139 if (!debug_flag)
140 alarm(options.login_grace_time);
88 141
89 xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n", 142- if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0)
90- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_RELEASE, 143+ if (kex_exchange_identification(ssh, -1, options.debian_banner,
91+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, 144+ options.version_addendum) != 0)
92+ options.debian_banner ? SSH_RELEASE : SSH_RELEASE_MINIMUM, 145 cleanup_exit(255); /* error already logged */
93 *options.version_addendum == '\0' ? "" : " ",
94 options.version_addendum);
95 146
147 ssh_packet_set_nonblocking(ssh);
96diff --git a/sshd_config.5 b/sshd_config.5 148diff --git a/sshd_config.5 b/sshd_config.5
97index e7e55dd71..37e6be38f 100644 149index 2ef671d1b..addea54a0 100644
98--- a/sshd_config.5 150--- a/sshd_config.5
99+++ b/sshd_config.5 151+++ b/sshd_config.5
100@@ -543,6 +543,11 @@ or 152@@ -543,6 +543,11 @@ or
diff --git a/debian/patches/debian-config.patch b/debian/patches/debian-config.patch
index 4866d52ad..0d47f6706 100644
--- a/debian/patches/debian-config.patch
+++ b/debian/patches/debian-config.patch
@@ -1,4 +1,4 @@
1From a433d9baa031d7136a8cf3e3807ebff83a3a8634 Mon Sep 17 00:00:00 2001 1From ebd590550bb09fe129b103994d53143788683d05 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:18 +0000 3Date: Sun, 9 Feb 2014 16:10:18 +0000
4Subject: Various Debian-specific configuration changes 4Subject: Various Debian-specific configuration changes
@@ -39,10 +39,10 @@ Patch-Name: debian-config.patch
39 6 files changed, 77 insertions(+), 9 deletions(-) 39 6 files changed, 77 insertions(+), 9 deletions(-)
40 40
41diff --git a/readconf.c b/readconf.c 41diff --git a/readconf.c b/readconf.c
42index 6b01f20d2..661b8bf40 100644 42index cd60007f8..f35bde6e6 100644
43--- a/readconf.c 43--- a/readconf.c
44+++ b/readconf.c 44+++ b/readconf.c
45@@ -2000,7 +2000,7 @@ fill_default_options(Options * options) 45@@ -2028,7 +2028,7 @@ fill_default_options(Options * options)
46 if (options->forward_x11 == -1) 46 if (options->forward_x11 == -1)
47 options->forward_x11 = 0; 47 options->forward_x11 = 0;
48 if (options->forward_x11_trusted == -1) 48 if (options->forward_x11_trusted == -1)
@@ -52,10 +52,10 @@ index 6b01f20d2..661b8bf40 100644
52 options->forward_x11_timeout = 1200; 52 options->forward_x11_timeout = 1200;
53 /* 53 /*
54diff --git a/ssh.1 b/ssh.1 54diff --git a/ssh.1 b/ssh.1
55index ad1ed0f86..1bcc8edab 100644 55index 8d2b08a29..4e298cb56 100644
56--- a/ssh.1 56--- a/ssh.1
57+++ b/ssh.1 57+++ b/ssh.1
58@@ -782,6 +782,16 @@ directive in 58@@ -795,6 +795,16 @@ directive in
59 .Xr ssh_config 5 59 .Xr ssh_config 5
60 for more information. 60 for more information.
61 .Pp 61 .Pp
@@ -72,7 +72,7 @@ index ad1ed0f86..1bcc8edab 100644
72 .It Fl x 72 .It Fl x
73 Disables X11 forwarding. 73 Disables X11 forwarding.
74 .Pp 74 .Pp
75@@ -790,6 +800,17 @@ Enables trusted X11 forwarding. 75@@ -803,6 +813,17 @@ Enables trusted X11 forwarding.
76 Trusted X11 forwardings are not subjected to the X11 SECURITY extension 76 Trusted X11 forwardings are not subjected to the X11 SECURITY extension
77 controls. 77 controls.
78 .Pp 78 .Pp
@@ -91,7 +91,7 @@ index ad1ed0f86..1bcc8edab 100644
91 Send log information using the 91 Send log information using the
92 .Xr syslog 3 92 .Xr syslog 3
93diff --git a/ssh_config b/ssh_config 93diff --git a/ssh_config b/ssh_config
94index bcb9f153d..1b676fb2c 100644 94index 1ff999b68..6dd6ecf87 100644
95--- a/ssh_config 95--- a/ssh_config
96+++ b/ssh_config 96+++ b/ssh_config
97@@ -17,9 +17,10 @@ 97@@ -17,9 +17,10 @@
@@ -106,7 +106,7 @@ index bcb9f153d..1b676fb2c 100644
106 # PasswordAuthentication yes 106 # PasswordAuthentication yes
107 # HostbasedAuthentication no 107 # HostbasedAuthentication no
108 # GSSAPIAuthentication no 108 # GSSAPIAuthentication no
109@@ -46,3 +47,6 @@ 109@@ -45,3 +46,6 @@
110 # VisualHostKey no 110 # VisualHostKey no
111 # ProxyCommand ssh -q -W %h:%p gateway.example.com 111 # ProxyCommand ssh -q -W %h:%p gateway.example.com
112 # RekeyLimit 1G 1h 112 # RekeyLimit 1G 1h
@@ -114,7 +114,7 @@ index bcb9f153d..1b676fb2c 100644
114+ HashKnownHosts yes 114+ HashKnownHosts yes
115+ GSSAPIAuthentication yes 115+ GSSAPIAuthentication yes
116diff --git a/ssh_config.5 b/ssh_config.5 116diff --git a/ssh_config.5 b/ssh_config.5
117index a91355726..1a8e24bd1 100644 117index 39535c4f8..a27631ae9 100644
118--- a/ssh_config.5 118--- a/ssh_config.5
119+++ b/ssh_config.5 119+++ b/ssh_config.5
120@@ -71,6 +71,22 @@ Since the first obtained value for each parameter is used, more 120@@ -71,6 +71,22 @@ Since the first obtained value for each parameter is used, more
@@ -140,7 +140,7 @@ index a91355726..1a8e24bd1 100644
140 The file contains keyword-argument pairs, one per line. 140 The file contains keyword-argument pairs, one per line.
141 Lines starting with 141 Lines starting with
142 .Ql # 142 .Ql #
143@@ -699,11 +715,12 @@ elapsed. 143@@ -717,11 +733,12 @@ elapsed.
144 .It Cm ForwardX11Trusted 144 .It Cm ForwardX11Trusted
145 If this option is set to 145 If this option is set to
146 .Cm yes , 146 .Cm yes ,
@@ -204,7 +204,7 @@ index 2c48105f8..ed8272f6d 100644
204 # Example of overriding settings on a per-user basis 204 # Example of overriding settings on a per-user basis
205 #Match User anoncvs 205 #Match User anoncvs
206diff --git a/sshd_config.5 b/sshd_config.5 206diff --git a/sshd_config.5 b/sshd_config.5
207index 23f71fd1d..ba50a30f1 100644 207index f995e4ab0..c0c4ebd66 100644
208--- a/sshd_config.5 208--- a/sshd_config.5
209+++ b/sshd_config.5 209+++ b/sshd_config.5
210@@ -56,6 +56,28 @@ Arguments may optionally be enclosed in double quotes 210@@ -56,6 +56,28 @@ Arguments may optionally be enclosed in double quotes
diff --git a/debian/patches/dnssec-sshfp.patch b/debian/patches/dnssec-sshfp.patch
index e2acdf1a2..6879e11ba 100644
--- a/debian/patches/dnssec-sshfp.patch
+++ b/debian/patches/dnssec-sshfp.patch
@@ -1,4 +1,4 @@
1From 0ee33d93c5c7a5fbb8b027aa24e7c9668125fda9 Mon Sep 17 00:00:00 2001 1From 13a16baaf467fae5d507cdb17e3bc753639bca4f Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:01 +0000 3Date: Sun, 9 Feb 2014 16:10:01 +0000
4Subject: Force use of DNSSEC even if "options edns0" isn't in resolv.conf 4Subject: Force use of DNSSEC even if "options edns0" isn't in resolv.conf
diff --git a/debian/patches/doc-hash-tab-completion.patch b/debian/patches/doc-hash-tab-completion.patch
index c6bc43299..60ded7c30 100644
--- a/debian/patches/doc-hash-tab-completion.patch
+++ b/debian/patches/doc-hash-tab-completion.patch
@@ -1,4 +1,4 @@
1From 1d0c41a7e0b2426733ddb598248d0488c9c00a8b Mon Sep 17 00:00:00 2001 1From 099b0bdc57b9a21842c457d83ff9488fa814c9c4 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:11 +0000 3Date: Sun, 9 Feb 2014 16:10:11 +0000
4Subject: Document that HashKnownHosts may break tab-completion 4Subject: Document that HashKnownHosts may break tab-completion
@@ -13,10 +13,10 @@ Patch-Name: doc-hash-tab-completion.patch
13 1 file changed, 3 insertions(+) 13 1 file changed, 3 insertions(+)
14 14
15diff --git a/ssh_config.5 b/ssh_config.5 15diff --git a/ssh_config.5 b/ssh_config.5
16index 7d55fa820..a91355726 100644 16index bd1e9311d..39535c4f8 100644
17--- a/ssh_config.5 17--- a/ssh_config.5
18+++ b/ssh_config.5 18+++ b/ssh_config.5
19@@ -793,6 +793,9 @@ Note that existing names and addresses in known hosts files 19@@ -836,6 +836,9 @@ Note that existing names and addresses in known hosts files
20 will not be converted automatically, 20 will not be converted automatically,
21 but may be manually hashed using 21 but may be manually hashed using
22 .Xr ssh-keygen 1 . 22 .Xr ssh-keygen 1 .
diff --git a/debian/patches/fix-key-type-check.patch b/debian/patches/fix-key-type-check.patch
deleted file mode 100644
index 846df5768..000000000
--- a/debian/patches/fix-key-type-check.patch
+++ /dev/null
@@ -1,88 +0,0 @@
1From 5e021158aa22cc64da4fca1618ee0bfd2d031049 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Fri, 16 Nov 2018 02:43:56 +0000
4Subject: upstream: fix bug in HostbasedAcceptedKeyTypes and
5
6PubkeyAcceptedKeyTypes options. If only RSA-SHA2 siganture types were
7specified, then authentication would always fail for RSA keys as the monitor
8checks only the base key (not the signature algorithm) type against
9*AcceptedKeyTypes. bz#2746; reported by Jakub Jelen; ok dtucker
10
11OpenBSD-Commit-ID: 117bc3dc54578dbdb515a1d3732988cb5b00461b
12
13Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=cd9467318b56e6e93ff9575c906ff8350af9b8a2
14Last-Update: 2019-02-28
15
16Patch-Name: fix-key-type-check.patch
17---
18 monitor.c | 39 ++++++++++++++++++++++++++++++++++-----
19 1 file changed, 34 insertions(+), 5 deletions(-)
20
21diff --git a/monitor.c b/monitor.c
22index 08fddabd7..037d6d333 100644
23--- a/monitor.c
24+++ b/monitor.c
25@@ -1,4 +1,4 @@
26-/* $OpenBSD: monitor.c,v 1.186 2018/07/20 03:46:34 djm Exp $ */
27+/* $OpenBSD: monitor.c,v 1.188 2018/11/16 02:43:56 djm Exp $ */
28 /*
29 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
30 * Copyright 2002 Markus Friedl <markus@openbsd.org>
31@@ -892,6 +892,35 @@ mm_answer_authrole(int sock, struct sshbuf *m)
32 return (0);
33 }
34
35+/*
36+ * Check that the key type appears in the supplied pattern list, ignoring
37+ * mismatches in the signature algorithm. (Signature algorithm checks are
38+ * performed in the unprivileged authentication code).
39+ * Returns 1 on success, 0 otherwise.
40+ */
41+static int
42+key_base_type_match(const char *method, const struct sshkey *key,
43+ const char *list)
44+{
45+ char *s, *l, *ol = xstrdup(list);
46+ int found = 0;
47+
48+ l = ol;
49+ for ((s = strsep(&l, ",")); s && *s != '\0'; (s = strsep(&l, ","))) {
50+ if (sshkey_type_from_name(s) == key->type) {
51+ found = 1;
52+ break;
53+ }
54+ }
55+ if (!found) {
56+ error("%s key type %s is not in permitted list %s", method,
57+ sshkey_ssh_name(key), list);
58+ }
59+
60+ free(ol);
61+ return found;
62+}
63+
64 int
65 mm_answer_authpassword(int sock, struct sshbuf *m)
66 {
67@@ -1197,8 +1226,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m)
68 break;
69 if (auth2_key_already_used(authctxt, key))
70 break;
71- if (match_pattern_list(sshkey_ssh_name(key),
72- options.pubkey_key_types, 0) != 1)
73+ if (!key_base_type_match(auth_method, key,
74+ options.pubkey_key_types))
75 break;
76 allowed = user_key_allowed(ssh, authctxt->pw, key,
77 pubkey_auth_attempt, &opts);
78@@ -1209,8 +1238,8 @@ mm_answer_keyallowed(int sock, struct sshbuf *m)
79 break;
80 if (auth2_key_already_used(authctxt, key))
81 break;
82- if (match_pattern_list(sshkey_ssh_name(key),
83- options.hostbased_key_types, 0) != 1)
84+ if (!key_base_type_match(auth_method, key,
85+ options.hostbased_key_types))
86 break;
87 allowed = hostbased_key_allowed(authctxt->pw,
88 cuser, chost, key);
diff --git a/debian/patches/gnome-ssh-askpass2-icon.patch b/debian/patches/gnome-ssh-askpass2-icon.patch
index b6d4f1239..35f3327df 100644
--- a/debian/patches/gnome-ssh-askpass2-icon.patch
+++ b/debian/patches/gnome-ssh-askpass2-icon.patch
@@ -1,4 +1,4 @@
1From df56506f727e37c13346259bdcd5975e257a259d Mon Sep 17 00:00:00 2001 1From 601332e5cc1198d6dabddc8168249a81c5dc822a Mon Sep 17 00:00:00 2001
2From: Vincent Untz <vuntz@ubuntu.com> 2From: Vincent Untz <vuntz@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:10:16 +0000 3Date: Sun, 9 Feb 2014 16:10:16 +0000
4Subject: Give the ssh-askpass-gnome window a default icon 4Subject: Give the ssh-askpass-gnome window a default icon
diff --git a/debian/patches/gssapi.patch b/debian/patches/gssapi.patch
index f62bf6672..45d131d27 100644
--- a/debian/patches/gssapi.patch
+++ b/debian/patches/gssapi.patch
@@ -1,4 +1,4 @@
1From 72b1d308e6400194ef6e4e7dd45bfa48fa39b5e6 Mon Sep 17 00:00:00 2001 1From 7ce79be85036c4b36937f1b1ba85f6094068412c Mon Sep 17 00:00:00 2001
2From: Simon Wilkinson <simon@sxw.org.uk> 2From: Simon Wilkinson <simon@sxw.org.uk>
3Date: Sun, 9 Feb 2014 16:09:48 +0000 3Date: Sun, 9 Feb 2014 16:09:48 +0000
4Subject: GSSAPI key exchange support 4Subject: GSSAPI key exchange support
@@ -16,185 +16,69 @@ have it merged into the main openssh package rather than having separate
16-krb5 packages (as we used to have). It seems to have a generally good 16-krb5 packages (as we used to have). It seems to have a generally good
17security history. 17security history.
18 18
19Origin: other, https://github.com/openssh-gsskex/openssh-gsskex/commits/debian/master
19Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242 20Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242
20Last-Updated: 2018-10-20 21Last-Updated: 2019-06-05
21 22
22Patch-Name: gssapi.patch 23Patch-Name: gssapi.patch
23--- 24---
24 ChangeLog.gssapi | 113 ++++++++++++++++ 25 Makefile.in | 3 +-
25 Makefile.in | 3 +- 26 auth-krb5.c | 17 +-
26 auth-krb5.c | 17 ++- 27 auth.c | 96 +-------
27 auth.c | 96 +------------ 28 auth2-gss.c | 56 ++++-
28 auth2-gss.c | 54 +++++++- 29 auth2.c | 2 +
29 auth2.c | 2 + 30 canohost.c | 93 ++++++++
30 canohost.c | 93 +++++++++++++ 31 canohost.h | 3 +
31 canohost.h | 3 + 32 clientloop.c | 15 +-
32 clientloop.c | 15 ++- 33 configure.ac | 24 ++
33 config.h.in | 6 + 34 gss-genr.c | 300 +++++++++++++++++++++++-
34 configure.ac | 24 ++++ 35 gss-serv-krb5.c | 85 ++++++-
35 gss-genr.c | 280 +++++++++++++++++++++++++++++++++++++- 36 gss-serv.c | 186 +++++++++++++--
36 gss-serv-krb5.c | 85 +++++++++++- 37 hmac.c | 1 +
37 gss-serv.c | 184 +++++++++++++++++++++++-- 38 kex.c | 66 +++++-
38 kex.c | 19 +++ 39 kex.h | 29 +++
39 kex.h | 14 ++ 40 kexdh.c | 10 +
40 kexgssc.c | 341 +++++++++++++++++++++++++++++++++++++++++++++++ 41 kexgen.c | 2 +-
41 kexgsss.c | 300 +++++++++++++++++++++++++++++++++++++++++ 42 kexgssc.c | 606 ++++++++++++++++++++++++++++++++++++++++++++++++
42 monitor.c | 122 +++++++++++++++-- 43 kexgsss.c | 474 +++++++++++++++++++++++++++++++++++++
43 monitor.h | 3 + 44 mac.c | 1 +
44 monitor_wrap.c | 53 +++++++- 45 monitor.c | 139 ++++++++++-
45 monitor_wrap.h | 4 +- 46 monitor.h | 2 +
46 opacket.c | 2 +- 47 monitor_wrap.c | 57 ++++-
47 opacket.h | 2 +- 48 monitor_wrap.h | 4 +-
48 readconf.c | 43 ++++++ 49 readconf.c | 70 ++++++
49 readconf.h | 5 + 50 readconf.h | 6 +
50 servconf.c | 26 ++++ 51 servconf.c | 47 ++++
51 servconf.h | 2 + 52 servconf.h | 3 +
52 ssh-gss.h | 41 +++++- 53 session.c | 10 +-
53 ssh_config | 2 + 54 ssh-gss.h | 50 +++-
54 ssh_config.5 | 32 +++++ 55 ssh.1 | 8 +
55 sshconnect2.c | 133 +++++++++++++++++- 56 ssh.c | 4 +-
56 sshd.c | 110 +++++++++++++++ 57 ssh_config | 2 +
57 sshd_config | 2 + 58 ssh_config.5 | 57 +++++
58 sshd_config.5 | 10 ++ 59 sshconnect2.c | 140 ++++++++++-
59 sshkey.c | 3 +- 60 sshd.c | 120 +++++++++-
60 sshkey.h | 1 + 61 sshd_config | 2 +
61 37 files changed, 2099 insertions(+), 146 deletions(-) 62 sshd_config.5 | 30 +++
62 create mode 100644 ChangeLog.gssapi 63 sshkey.c | 3 +-
64 sshkey.h | 1 +
65 40 files changed, 2664 insertions(+), 160 deletions(-)
63 create mode 100644 kexgssc.c 66 create mode 100644 kexgssc.c
64 create mode 100644 kexgsss.c 67 create mode 100644 kexgsss.c
65 68
66diff --git a/ChangeLog.gssapi b/ChangeLog.gssapi
67new file mode 100644
68index 000000000..f117a336a
69--- /dev/null
70+++ b/ChangeLog.gssapi
71@@ -0,0 +1,113 @@
72+20110101
73+ - Finally update for OpenSSH 5.6p1
74+ - Add GSSAPIServerIdentity option from Jim Basney
75+
76+20100308
77+ - [ Makefile.in, key.c, key.h ]
78+ Updates for OpenSSH 5.4p1
79+ - [ servconf.c ]
80+ Include GSSAPI options in the sshd -T configuration dump, and flag
81+ some older configuration options as being unsupported. Thanks to Colin
82+ Watson.
83+ -
84+
85+20100124
86+ - [ sshconnect2.c ]
87+ Adapt to deal with additional element in Authmethod structure. Thanks to
88+ Colin Watson
89+
90+20090615
91+ - [ gss-genr.c gss-serv.c kexgssc.c kexgsss.c monitor.c sshconnect2.c
92+ sshd.c ]
93+ Fix issues identified by Greg Hudson following a code review
94+ Check return value of gss_indicate_mechs
95+ Protect GSSAPI calls in monitor, so they can only be used if enabled
96+ Check return values of bignum functions in key exchange
97+ Use BN_clear_free to clear other side's DH value
98+ Make ssh_gssapi_id_kex more robust
99+ Only configure kex table pointers if GSSAPI is enabled
100+ Don't leak mechanism list, or gss mechanism list
101+ Cast data.length before printing
102+ If serverkey isn't provided, use an empty string, rather than NULL
103+
104+20090201
105+ - [ gss-genr.c gss-serv.c kex.h kexgssc.c readconf.c readconf.h ssh-gss.h
106+ ssh_config.5 sshconnet2.c ]
107+ Add support for the GSSAPIClientIdentity option, which allows the user
108+ to specify which GSSAPI identity to use to contact a given server
109+
110+20080404
111+ - [ gss-serv.c ]
112+ Add code to actually implement GSSAPIStrictAcceptCheck, which had somehow
113+ been omitted from a previous version of this patch. Reported by Borislav
114+ Stoichkov
115+
116+20070317
117+ - [ gss-serv-krb5.c ]
118+ Remove C99ism, where new_ccname was being declared in the middle of a
119+ function
120+
121+20061220
122+ - [ servconf.c ]
123+ Make default for GSSAPIStrictAcceptorCheck be Yes, to match previous, and
124+ documented, behaviour. Reported by Dan Watson.
125+
126+20060910
127+ - [ gss-genr.c kexgssc.c kexgsss.c kex.h monitor.c sshconnect2.c sshd.c
128+ ssh-gss.h ]
129+ add support for gss-group14-sha1 key exchange mechanisms
130+ - [ gss-serv.c servconf.c servconf.h sshd_config sshd_config.5 ]
131+ Add GSSAPIStrictAcceptorCheck option to allow the disabling of
132+ acceptor principal checking on multi-homed machines.
133+ <Bugzilla #928>
134+ - [ sshd_config ssh_config ]
135+ Add settings for GSSAPIKeyExchange and GSSAPITrustDNS to the sample
136+ configuration files
137+ - [ kexgss.c kegsss.c sshconnect2.c sshd.c ]
138+ Code cleanup. Replace strlen/xmalloc/snprintf sequences with xasprintf()
139+ Limit length of error messages displayed by client
140+
141+20060909
142+ - [ gss-genr.c gss-serv.c ]
143+ move ssh_gssapi_acquire_cred() and ssh_gssapi_server_ctx to be server
144+ only, where they belong
145+ <Bugzilla #1225>
146+
147+20060829
148+ - [ gss-serv-krb5.c ]
149+ Fix CCAPI credentials cache name when creating KRB5CCNAME environment
150+ variable
151+
152+20060828
153+ - [ gss-genr.c ]
154+ Avoid Heimdal context freeing problem
155+ <Fixed upstream 20060829>
156+
157+20060818
158+ - [ gss-genr.c ssh-gss.h sshconnect2.c ]
159+ Make sure that SPENGO is disabled
160+ <Bugzilla #1218 - Fixed upstream 20060818>
161+
162+20060421
163+ - [ gssgenr.c, sshconnect2.c ]
164+ a few type changes (signed versus unsigned, int versus size_t) to
165+ fix compiler errors/warnings
166+ (from jbasney AT ncsa.uiuc.edu)
167+ - [ kexgssc.c, sshconnect2.c ]
168+ fix uninitialized variable warnings
169+ (from jbasney AT ncsa.uiuc.edu)
170+ - [ gssgenr.c ]
171+ pass oid to gss_display_status (helpful when using GSSAPI mechglue)
172+ (from jbasney AT ncsa.uiuc.edu)
173+ <Bugzilla #1220 >
174+ - [ gss-serv-krb5.c ]
175+ #ifdef HAVE_GSSAPI_KRB5 should be #ifdef HAVE_GSSAPI_KRB5_H
176+ (from jbasney AT ncsa.uiuc.edu)
177+ <Fixed upstream 20060304>
178+ - [ readconf.c, readconf.h, ssh_config.5, sshconnect2.c
179+ add client-side GssapiKeyExchange option
180+ (from jbasney AT ncsa.uiuc.edu)
181+ - [ sshconnect2.c ]
182+ add support for GssapiTrustDns option for gssapi-with-mic
183+ (from jbasney AT ncsa.uiuc.edu)
184+ <gssapi-with-mic support is Bugzilla #1008>
185diff --git a/Makefile.in b/Makefile.in 69diff --git a/Makefile.in b/Makefile.in
186index 126b2c742..70050ffb6 100644 70index 6f001bb36..c31821acc 100644
187--- a/Makefile.in 71--- a/Makefile.in
188+++ b/Makefile.in 72+++ b/Makefile.in
189@@ -100,6 +100,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \ 73@@ -100,6 +100,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
190 kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \ 74 kex.o kexdh.o kexgex.o kexecdh.o kexc25519.o \
191 kexdhc.o kexgexc.o kexecdhc.o kexc25519c.o \ 75 kexgexc.o kexgexs.o \
192 kexdhs.o kexgexs.o kexecdhs.o kexc25519s.o \ 76 sntrup4591761.o kexsntrup4591761x25519.o kexgen.o \
193+ kexgssc.o \ 77+ kexgssc.o \
194 platform-pledge.o platform-tracing.o platform-misc.o 78 platform-pledge.o platform-tracing.o platform-misc.o
195 79
196 SSHOBJS= ssh.o readconf.o clientloop.o sshtty.o \ 80
197@@ -113,7 +114,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \ 81@@ -114,7 +115,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o \
198 auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \ 82 auth-bsdauth.o auth2-hostbased.o auth2-kbdint.o \
199 auth2-none.o auth2-passwd.o auth2-pubkey.o \ 83 auth2-none.o auth2-passwd.o auth2-pubkey.o \
200 monitor.o monitor_wrap.o auth-krb5.o \ 84 monitor.o monitor_wrap.o auth-krb5.o \
@@ -255,7 +139,7 @@ index 3096f1c8e..204752e1b 100644
255 return (krb5_cc_resolve(ctx, ccname, ccache)); 139 return (krb5_cc_resolve(ctx, ccname, ccache));
256 } 140 }
257diff --git a/auth.c b/auth.c 141diff --git a/auth.c b/auth.c
258index 3ca3762cc..d8e6b4a3d 100644 142index 8696f258e..f7a23afba 100644
259--- a/auth.c 143--- a/auth.c
260+++ b/auth.c 144+++ b/auth.c
261@@ -399,7 +399,8 @@ auth_root_allowed(struct ssh *ssh, const char *method) 145@@ -399,7 +399,8 @@ auth_root_allowed(struct ssh *ssh, const char *method)
@@ -268,7 +152,7 @@ index 3ca3762cc..d8e6b4a3d 100644
268 return 1; 152 return 1;
269 break; 153 break;
270 case PERMIT_FORCED_ONLY: 154 case PERMIT_FORCED_ONLY:
271@@ -737,99 +738,6 @@ fakepw(void) 155@@ -723,99 +724,6 @@ fakepw(void)
272 return (&fake); 156 return (&fake);
273 } 157 }
274 158
@@ -369,7 +253,7 @@ index 3ca3762cc..d8e6b4a3d 100644
369 * Return the canonical name of the host in the other side of the current 253 * Return the canonical name of the host in the other side of the current
370 * connection. The host name is cached, so it is efficient to call this 254 * connection. The host name is cached, so it is efficient to call this
371diff --git a/auth2-gss.c b/auth2-gss.c 255diff --git a/auth2-gss.c b/auth2-gss.c
372index 9351e0428..1f12bb113 100644 256index 9351e0428..d6446c0cf 100644
373--- a/auth2-gss.c 257--- a/auth2-gss.c
374+++ b/auth2-gss.c 258+++ b/auth2-gss.c
375@@ -1,7 +1,7 @@ 259@@ -1,7 +1,7 @@
@@ -381,11 +265,11 @@ index 9351e0428..1f12bb113 100644
381 * 265 *
382 * Redistribution and use in source and binary forms, with or without 266 * Redistribution and use in source and binary forms, with or without
383 * modification, are permitted provided that the following conditions 267 * modification, are permitted provided that the following conditions
384@@ -54,6 +54,46 @@ static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh); 268@@ -54,6 +54,48 @@ static int input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh);
385 static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh); 269 static int input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh);
386 static int input_gssapi_errtok(int, u_int32_t, struct ssh *); 270 static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
387 271
388+/* 272+/*
389+ * The 'gssapi_keyex' userauth mechanism. 273+ * The 'gssapi_keyex' userauth mechanism.
390+ */ 274+ */
391+static int 275+static int
@@ -393,7 +277,7 @@ index 9351e0428..1f12bb113 100644
393+{ 277+{
394+ Authctxt *authctxt = ssh->authctxt; 278+ Authctxt *authctxt = ssh->authctxt;
395+ int r, authenticated = 0; 279+ int r, authenticated = 0;
396+ struct sshbuf *b; 280+ struct sshbuf *b = NULL;
397+ gss_buffer_desc mic, gssbuf; 281+ gss_buffer_desc mic, gssbuf;
398+ u_char *p; 282+ u_char *p;
399+ size_t len; 283+ size_t len;
@@ -401,8 +285,10 @@ index 9351e0428..1f12bb113 100644
401+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 || 285+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0 ||
402+ (r = sshpkt_get_end(ssh)) != 0) 286+ (r = sshpkt_get_end(ssh)) != 0)
403+ fatal("%s: %s", __func__, ssh_err(r)); 287+ fatal("%s: %s", __func__, ssh_err(r));
288+
404+ if ((b = sshbuf_new()) == NULL) 289+ if ((b = sshbuf_new()) == NULL)
405+ fatal("%s: sshbuf_new failed", __func__); 290+ fatal("%s: sshbuf_new failed", __func__);
291+
406+ mic.value = p; 292+ mic.value = p;
407+ mic.length = len; 293+ mic.length = len;
408+ 294+
@@ -414,11 +300,11 @@ index 9351e0428..1f12bb113 100644
414+ gssbuf.length = sshbuf_len(b); 300+ gssbuf.length = sshbuf_len(b);
415+ 301+
416+ /* gss_kex_context is NULL with privsep, so we can't check it here */ 302+ /* gss_kex_context is NULL with privsep, so we can't check it here */
417+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context, 303+ if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gss_kex_context,
418+ &gssbuf, &mic)))) 304+ &gssbuf, &mic))))
419+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, 305+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
420+ authctxt->pw)); 306+ authctxt->pw, 1));
421+ 307+
422+ sshbuf_free(b); 308+ sshbuf_free(b);
423+ free(mic.value); 309+ free(mic.value);
424+ 310+
@@ -428,27 +314,27 @@ index 9351e0428..1f12bb113 100644
428 /* 314 /*
429 * We only support those mechanisms that we know about (ie ones that we know 315 * We only support those mechanisms that we know about (ie ones that we know
430 * how to check local user kuserok and the like) 316 * how to check local user kuserok and the like)
431@@ -260,7 +300,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh) 317@@ -260,7 +302,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, struct ssh *ssh)
432 if ((r = sshpkt_get_end(ssh)) != 0) 318 if ((r = sshpkt_get_end(ssh)) != 0)
433 fatal("%s: %s", __func__, ssh_err(r)); 319 fatal("%s: %s", __func__, ssh_err(r));
434 320
435- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 321- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
436+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user, 322+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
437+ authctxt->pw)); 323+ authctxt->pw, 1));
438 324
439 if ((!use_privsep || mm_is_monitor()) && 325 if ((!use_privsep || mm_is_monitor()) &&
440 (displayname = ssh_gssapi_displayname()) != NULL) 326 (displayname = ssh_gssapi_displayname()) != NULL)
441@@ -306,7 +347,8 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) 327@@ -306,7 +349,8 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
442 gssbuf.length = sshbuf_len(b); 328 gssbuf.length = sshbuf_len(b);
443 329
444 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) 330 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
445- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user)); 331- authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user));
446+ authenticated = 332+ authenticated = PRIVSEP(ssh_gssapi_userok(authctxt->user,
447+ PRIVSEP(ssh_gssapi_userok(authctxt->user, authctxt->pw)); 333+ authctxt->pw, 0));
448 else 334 else
449 logit("GSSAPI MIC check failed"); 335 logit("GSSAPI MIC check failed");
450 336
451@@ -326,6 +368,12 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh) 337@@ -326,6 +370,12 @@ input_gssapi_mic(int type, u_int32_t plen, struct ssh *ssh)
452 return 0; 338 return 0;
453 } 339 }
454 340
@@ -462,10 +348,10 @@ index 9351e0428..1f12bb113 100644
462 "gssapi-with-mic", 348 "gssapi-with-mic",
463 userauth_gssapi, 349 userauth_gssapi,
464diff --git a/auth2.c b/auth2.c 350diff --git a/auth2.c b/auth2.c
465index 4d19957a6..a77742819 100644 351index 16ae1a363..7417eafa4 100644
466--- a/auth2.c 352--- a/auth2.c
467+++ b/auth2.c 353+++ b/auth2.c
468@@ -74,6 +74,7 @@ extern Authmethod method_passwd; 354@@ -75,6 +75,7 @@ extern Authmethod method_passwd;
469 extern Authmethod method_kbdint; 355 extern Authmethod method_kbdint;
470 extern Authmethod method_hostbased; 356 extern Authmethod method_hostbased;
471 #ifdef GSSAPI 357 #ifdef GSSAPI
@@ -473,7 +359,7 @@ index 4d19957a6..a77742819 100644
473 extern Authmethod method_gssapi; 359 extern Authmethod method_gssapi;
474 #endif 360 #endif
475 361
476@@ -81,6 +82,7 @@ Authmethod *authmethods[] = { 362@@ -82,6 +83,7 @@ Authmethod *authmethods[] = {
477 &method_none, 363 &method_none,
478 &method_pubkey, 364 &method_pubkey,
479 #ifdef GSSAPI 365 #ifdef GSSAPI
@@ -600,7 +486,7 @@ index 26d62855a..0cadc9f18 100644
600 int get_peer_port(int); 486 int get_peer_port(int);
601 char *get_local_ipaddr(int); 487 char *get_local_ipaddr(int);
602diff --git a/clientloop.c b/clientloop.c 488diff --git a/clientloop.c b/clientloop.c
603index 8d312cdaa..1464634b0 100644 489index 086c0dfe8..9b90c64f3 100644
604--- a/clientloop.c 490--- a/clientloop.c
605+++ b/clientloop.c 491+++ b/clientloop.c
606@@ -112,6 +112,10 @@ 492@@ -112,6 +112,10 @@
@@ -614,7 +500,7 @@ index 8d312cdaa..1464634b0 100644
614 /* import options */ 500 /* import options */
615 extern Options options; 501 extern Options options;
616 502
617@@ -1370,9 +1374,18 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg, 503@@ -1374,9 +1378,18 @@ client_loop(struct ssh *ssh, int have_pty, int escape_char_arg,
618 break; 504 break;
619 505
620 /* Do channel operations unless rekeying in progress. */ 506 /* Do channel operations unless rekeying in progress. */
@@ -632,37 +518,13 @@ index 8d312cdaa..1464634b0 100644
632+ } 518+ }
633+ 519+
634 /* Buffer input from the connection. */ 520 /* Buffer input from the connection. */
635 client_process_net_input(readset); 521 client_process_net_input(ssh, readset);
636
637diff --git a/config.h.in b/config.h.in
638index 91b65db8f..209760c7c 100644
639--- a/config.h.in
640+++ b/config.h.in
641@@ -1845,6 +1845,9 @@
642 /* Use btmp to log bad logins */
643 #undef USE_BTMP
644
645+/* platform uses an in-memory credentials cache */
646+#undef USE_CCAPI
647+
648 /* Use libedit for sftp */
649 #undef USE_LIBEDIT
650
651@@ -1860,6 +1863,9 @@
652 /* Use PIPES instead of a socketpair() */
653 #undef USE_PIPES
654
655+/* platform has the Security Authorization Session API */
656+#undef USE_SECURITY_SESSION_API
657+
658 /* Define if you have Solaris privileges */
659 #undef USE_SOLARIS_PRIVS
660 522
661diff --git a/configure.ac b/configure.ac 523diff --git a/configure.ac b/configure.ac
662index 7379ab358..023e7cc55 100644 524index 30be6c182..2869f7042 100644
663--- a/configure.ac 525--- a/configure.ac
664+++ b/configure.ac 526+++ b/configure.ac
665@@ -664,6 +664,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) 527@@ -665,6 +665,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
666 [Use tunnel device compatibility to OpenBSD]) 528 [Use tunnel device compatibility to OpenBSD])
667 AC_DEFINE([SSH_TUN_PREPEND_AF], [1], 529 AC_DEFINE([SSH_TUN_PREPEND_AF], [1],
668 [Prepend the address family to IP tunnel traffic]) 530 [Prepend the address family to IP tunnel traffic])
@@ -670,7 +532,7 @@ index 7379ab358..023e7cc55 100644
670+ AC_TRY_COMPILE([#include <Security/AuthSession.h>], 532+ AC_TRY_COMPILE([#include <Security/AuthSession.h>],
671+ [SessionCreate(0, 0);], 533+ [SessionCreate(0, 0);],
672+ [ac_cv_use_security_session_api="yes" 534+ [ac_cv_use_security_session_api="yes"
673+ AC_DEFINE([USE_SECURITY_SESSION_API], [1], 535+ AC_DEFINE([USE_SECURITY_SESSION_API], [1],
674+ [platform has the Security Authorization Session API]) 536+ [platform has the Security Authorization Session API])
675+ LIBS="$LIBS -framework Security" 537+ LIBS="$LIBS -framework Security"
676+ AC_MSG_RESULT([yes])], 538+ AC_MSG_RESULT([yes])],
@@ -681,7 +543,7 @@ index 7379ab358..023e7cc55 100644
681+ [#include <Kerberos/Kerberos.h>], 543+ [#include <Kerberos/Kerberos.h>],
682+ [cc_context_t c; 544+ [cc_context_t c;
683+ (void) cc_initialize (&c, 0, NULL, NULL);], 545+ (void) cc_initialize (&c, 0, NULL, NULL);],
684+ [AC_DEFINE([USE_CCAPI], [1], 546+ [AC_DEFINE([USE_CCAPI], [1],
685+ [platform uses an in-memory credentials cache]) 547+ [platform uses an in-memory credentials cache])
686+ LIBS="$LIBS -framework Security" 548+ LIBS="$LIBS -framework Security"
687+ AC_MSG_RESULT([yes]) 549+ AC_MSG_RESULT([yes])
@@ -694,7 +556,7 @@ index 7379ab358..023e7cc55 100644
694 AC_CHECK_DECL([AU_IPv4], [], 556 AC_CHECK_DECL([AU_IPv4], [],
695 AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records]) 557 AC_DEFINE([AU_IPv4], [0], [System only supports IPv4 audit records])
696diff --git a/gss-genr.c b/gss-genr.c 558diff --git a/gss-genr.c b/gss-genr.c
697index d56257b4a..491e62cee 100644 559index d56257b4a..763a63ffa 100644
698--- a/gss-genr.c 560--- a/gss-genr.c
699+++ b/gss-genr.c 561+++ b/gss-genr.c
700@@ -1,7 +1,7 @@ 562@@ -1,7 +1,7 @@
@@ -706,16 +568,15 @@ index d56257b4a..491e62cee 100644
706 * 568 *
707 * Redistribution and use in source and binary forms, with or without 569 * Redistribution and use in source and binary forms, with or without
708 * modification, are permitted provided that the following conditions 570 * modification, are permitted provided that the following conditions
709@@ -39,14 +39,37 @@ 571@@ -41,12 +41,36 @@
710 #include "xmalloc.h"
711 #include "ssherr.h"
712 #include "sshbuf.h" 572 #include "sshbuf.h"
713+#include "sshkey.h"
714 #include "log.h" 573 #include "log.h"
715 #include "ssh2.h" 574 #include "ssh2.h"
716+#include "cipher.h" 575+#include "cipher.h"
576+#include "sshkey.h"
717+#include "kex.h" 577+#include "kex.h"
718+#include "digest.h" 578+#include "digest.h"
579+#include "packet.h"
719 580
720 #include "ssh-gss.h" 581 #include "ssh-gss.h"
721 582
@@ -736,7 +597,7 @@ index d56257b4a..491e62cee 100644
736+ 597+
737+static ssh_gss_kex_mapping *gss_enc2oid = NULL; 598+static ssh_gss_kex_mapping *gss_enc2oid = NULL;
738+ 599+
739+int 600+int
740+ssh_gssapi_oid_table_ok(void) { 601+ssh_gssapi_oid_table_ok(void) {
741+ return (gss_enc2oid != NULL); 602+ return (gss_enc2oid != NULL);
742+} 603+}
@@ -744,10 +605,25 @@ index d56257b4a..491e62cee 100644
744 /* sshbuf_get for gss_buffer_desc */ 605 /* sshbuf_get for gss_buffer_desc */
745 int 606 int
746 ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) 607 ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g)
747@@ -62,6 +85,143 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g) 608@@ -62,6 +86,162 @@ ssh_gssapi_get_buffer_desc(struct sshbuf *b, gss_buffer_desc *g)
748 return 0; 609 return 0;
749 } 610 }
750 611
612+/* sshpkt_get of gss_buffer_desc */
613+int
614+ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *ssh, gss_buffer_desc *g)
615+{
616+ int r;
617+ u_char *p;
618+ size_t len;
619+
620+ if ((r = sshpkt_get_string(ssh, &p, &len)) != 0)
621+ return r;
622+ g->value = p;
623+ g->length = len;
624+ return 0;
625+}
626+
751+/* 627+/*
752+ * Return a list of the gss-group1-sha1 mechanisms supported by this program 628+ * Return a list of the gss-group1-sha1 mechanisms supported by this program
753+ * 629+ *
@@ -756,27 +632,30 @@ index d56257b4a..491e62cee 100644
756+ */ 632+ */
757+ 633+
758+char * 634+char *
759+ssh_gssapi_client_mechanisms(const char *host, const char *client) { 635+ssh_gssapi_client_mechanisms(const char *host, const char *client,
760+ gss_OID_set gss_supported; 636+ const char *kex) {
637+ gss_OID_set gss_supported = NULL;
761+ OM_uint32 min_status; 638+ OM_uint32 min_status;
762+ 639+
763+ if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported))) 640+ if (GSS_ERROR(gss_indicate_mechs(&min_status, &gss_supported)))
764+ return NULL; 641+ return NULL;
765+ 642+
766+ return(ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism, 643+ return ssh_gssapi_kex_mechs(gss_supported, ssh_gssapi_check_mechanism,
767+ host, client)); 644+ host, client, kex);
768+} 645+}
769+ 646+
770+char * 647+char *
771+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check, 648+ssh_gssapi_kex_mechs(gss_OID_set gss_supported, ssh_gssapi_check_fn *check,
772+ const char *host, const char *client) { 649+ const char *host, const char *client, const char *kex) {
773+ struct sshbuf *buf; 650+ struct sshbuf *buf = NULL;
774+ size_t i; 651+ size_t i;
775+ int r, oidpos, enclen; 652+ int r = SSH_ERR_ALLOC_FAIL;
653+ int oidpos, enclen;
776+ char *mechs, *encoded; 654+ char *mechs, *encoded;
777+ u_char digest[SSH_DIGEST_MAX_LENGTH]; 655+ u_char digest[SSH_DIGEST_MAX_LENGTH];
778+ char deroid[2]; 656+ char deroid[2];
779+ struct ssh_digest_ctx *md; 657+ struct ssh_digest_ctx *md = NULL;
658+ char *s, *cp, *p;
780+ 659+
781+ if (gss_enc2oid != NULL) { 660+ if (gss_enc2oid != NULL) {
782+ for (i = 0; gss_enc2oid[i].encoded != NULL; i++) 661+ for (i = 0; gss_enc2oid[i].encoded != NULL; i++)
@@ -791,6 +670,7 @@ index d56257b4a..491e62cee 100644
791+ fatal("%s: sshbuf_new failed", __func__); 670+ fatal("%s: sshbuf_new failed", __func__);
792+ 671+
793+ oidpos = 0; 672+ oidpos = 0;
673+ s = cp = xstrdup(kex);
794+ for (i = 0; i < gss_supported->count; i++) { 674+ for (i = 0; i < gss_supported->count; i++) {
795+ if (gss_supported->elements[i].length < 128 && 675+ if (gss_supported->elements[i].length < 128 &&
796+ (*check)(NULL, &(gss_supported->elements[i]), host, client)) { 676+ (*check)(NULL, &(gss_supported->elements[i]), host, client)) {
@@ -799,12 +679,15 @@ index d56257b4a..491e62cee 100644
799+ deroid[1] = gss_supported->elements[i].length; 679+ deroid[1] = gss_supported->elements[i].length;
800+ 680+
801+ if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || 681+ if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL ||
802+ ssh_digest_update(md, deroid, 2) != 0 || 682+ (r = ssh_digest_update(md, deroid, 2)) != 0 ||
803+ ssh_digest_update(md, 683+ (r = ssh_digest_update(md,
804+ gss_supported->elements[i].elements, 684+ gss_supported->elements[i].elements,
805+ gss_supported->elements[i].length) != 0 || 685+ gss_supported->elements[i].length)) != 0 ||
806+ ssh_digest_final(md, digest, sizeof(digest)) != 0) 686+ (r = ssh_digest_final(md, digest, sizeof(digest))) != 0)
807+ fatal("%s: digest failed", __func__); 687+ fatal("%s: digest failed: %s", __func__,
688+ ssh_err(r));
689+ ssh_digest_free(md);
690+ md = NULL;
808+ 691+
809+ encoded = xmalloc(ssh_digest_bytes(SSH_DIGEST_MD5) 692+ encoded = xmalloc(ssh_digest_bytes(SSH_DIGEST_MD5)
810+ * 2); 693+ * 2);
@@ -812,69 +695,66 @@ index d56257b4a..491e62cee 100644
812+ ssh_digest_bytes(SSH_DIGEST_MD5), encoded, 695+ ssh_digest_bytes(SSH_DIGEST_MD5), encoded,
813+ ssh_digest_bytes(SSH_DIGEST_MD5) * 2); 696+ ssh_digest_bytes(SSH_DIGEST_MD5) * 2);
814+ 697+
815+ if (oidpos != 0) { 698+ cp = strncpy(s, kex, strlen(kex));
816+ if ((r = sshbuf_put_u8(buf, ',')) != 0) 699+ for ((p = strsep(&cp, ",")); p && *p != '\0';
817+ fatal("%s: buffer error: %s", 700+ (p = strsep(&cp, ","))) {
701+ if (sshbuf_len(buf) != 0 &&
702+ (r = sshbuf_put_u8(buf, ',')) != 0)
703+ fatal("%s: sshbuf_put_u8 error: %s",
704+ __func__, ssh_err(r));
705+ if ((r = sshbuf_put(buf, p, strlen(p))) != 0 ||
706+ (r = sshbuf_put(buf, encoded, enclen)) != 0)
707+ fatal("%s: sshbuf_put error: %s",
818+ __func__, ssh_err(r)); 708+ __func__, ssh_err(r));
819+ } 709+ }
820+ 710+
821+ if ((r = sshbuf_put(buf, KEX_GSS_GEX_SHA1_ID,
822+ sizeof(KEX_GSS_GEX_SHA1_ID) - 1)) != 0 ||
823+ (r = sshbuf_put(buf, encoded, enclen)) != 0 ||
824+ (r = sshbuf_put_u8(buf, ',')) != 0 ||
825+ (r = sshbuf_put(buf, KEX_GSS_GRP1_SHA1_ID,
826+ sizeof(KEX_GSS_GRP1_SHA1_ID) - 1)) != 0 ||
827+ (r = sshbuf_put(buf, encoded, enclen)) != 0 ||
828+ (r = sshbuf_put_u8(buf, ',')) != 0 ||
829+ (r = sshbuf_put(buf, KEX_GSS_GRP14_SHA1_ID,
830+ sizeof(KEX_GSS_GRP14_SHA1_ID) - 1)) != 0 ||
831+ (r = sshbuf_put(buf, encoded, enclen)) != 0)
832+ fatal("%s: buffer error: %s",
833+ __func__, ssh_err(r));
834+
835+ gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]); 711+ gss_enc2oid[oidpos].oid = &(gss_supported->elements[i]);
836+ gss_enc2oid[oidpos].encoded = encoded; 712+ gss_enc2oid[oidpos].encoded = encoded;
837+ oidpos++; 713+ oidpos++;
838+ } 714+ }
839+ } 715+ }
716+ free(s);
840+ gss_enc2oid[oidpos].oid = NULL; 717+ gss_enc2oid[oidpos].oid = NULL;
841+ gss_enc2oid[oidpos].encoded = NULL; 718+ gss_enc2oid[oidpos].encoded = NULL;
842+ 719+
843+ if ((mechs = sshbuf_dup_string(buf)) == NULL) 720+ if ((mechs = sshbuf_dup_string(buf)) == NULL)
844+ fatal("%s: sshbuf_dup_string failed", __func__); 721+ fatal("%s: sshbuf_dup_string failed", __func__);
845+ 722+
723+ sshbuf_free(buf);
724+
846+ if (strlen(mechs) == 0) { 725+ if (strlen(mechs) == 0) {
847+ free(mechs); 726+ free(mechs);
848+ mechs = NULL; 727+ mechs = NULL;
849+ } 728+ }
850+ 729+
851+ return (mechs); 730+ return (mechs);
852+} 731+}
853+ 732+
854+gss_OID 733+gss_OID
855+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) { 734+ssh_gssapi_id_kex(Gssctxt *ctx, char *name, int kex_type) {
856+ int i = 0; 735+ int i = 0;
857+ 736+
858+ switch (kex_type) { 737+#define SKIP_KEX_NAME(type) \
859+ case KEX_GSS_GRP1_SHA1: 738+ case type: \
860+ if (strlen(name) < sizeof(KEX_GSS_GRP1_SHA1_ID)) 739+ if (strlen(name) < sizeof(type##_ID)) \
861+ return GSS_C_NO_OID; 740+ return GSS_C_NO_OID; \
862+ name += sizeof(KEX_GSS_GRP1_SHA1_ID) - 1; 741+ name += sizeof(type##_ID) - 1; \
863+ break;
864+ case KEX_GSS_GRP14_SHA1:
865+ if (strlen(name) < sizeof(KEX_GSS_GRP14_SHA1_ID))
866+ return GSS_C_NO_OID;
867+ name += sizeof(KEX_GSS_GRP14_SHA1_ID) - 1;
868+ break;
869+ case KEX_GSS_GEX_SHA1:
870+ if (strlen(name) < sizeof(KEX_GSS_GEX_SHA1_ID))
871+ return GSS_C_NO_OID;
872+ name += sizeof(KEX_GSS_GEX_SHA1_ID) - 1;
873+ break; 742+ break;
743+
744+ switch (kex_type) {
745+ SKIP_KEX_NAME(KEX_GSS_GRP1_SHA1)
746+ SKIP_KEX_NAME(KEX_GSS_GRP14_SHA1)
747+ SKIP_KEX_NAME(KEX_GSS_GRP14_SHA256)
748+ SKIP_KEX_NAME(KEX_GSS_GRP16_SHA512)
749+ SKIP_KEX_NAME(KEX_GSS_GEX_SHA1)
750+ SKIP_KEX_NAME(KEX_GSS_NISTP256_SHA256)
751+ SKIP_KEX_NAME(KEX_GSS_C25519_SHA256)
874+ default: 752+ default:
875+ return GSS_C_NO_OID; 753+ return GSS_C_NO_OID;
876+ } 754+ }
877+ 755+
756+#undef SKIP_KEX_NAME
757+
878+ while (gss_enc2oid[i].encoded != NULL && 758+ while (gss_enc2oid[i].encoded != NULL &&
879+ strcmp(name, gss_enc2oid[i].encoded) != 0) 759+ strcmp(name, gss_enc2oid[i].encoded) != 0)
880+ i++; 760+ i++;
@@ -888,7 +768,7 @@ index d56257b4a..491e62cee 100644
888 /* Check that the OID in a data stream matches that in the context */ 768 /* Check that the OID in a data stream matches that in the context */
889 int 769 int
890 ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len) 770 ssh_gssapi_check_oid(Gssctxt *ctx, void *data, size_t len)
891@@ -218,7 +378,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok, 771@@ -218,7 +398,7 @@ ssh_gssapi_init_ctx(Gssctxt *ctx, int deleg_creds, gss_buffer_desc *recv_tok,
892 } 772 }
893 773
894 ctx->major = gss_init_sec_context(&ctx->minor, 774 ctx->major = gss_init_sec_context(&ctx->minor,
@@ -897,7 +777,7 @@ index d56257b4a..491e62cee 100644
897 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag, 777 GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG | deleg_flag,
898 0, NULL, recv_tok, NULL, send_tok, flags, NULL); 778 0, NULL, recv_tok, NULL, send_tok, flags, NULL);
899 779
900@@ -247,9 +407,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host) 780@@ -247,9 +427,43 @@ ssh_gssapi_import_name(Gssctxt *ctx, const char *host)
901 return (ctx->major); 781 return (ctx->major);
902 } 782 }
903 783
@@ -919,8 +799,8 @@ index d56257b4a..491e62cee 100644
919+ GSS_C_NT_USER_NAME, &gssname); 799+ GSS_C_NT_USER_NAME, &gssname);
920+ 800+
921+ if (!ctx->major) 801+ if (!ctx->major)
922+ ctx->major = gss_acquire_cred(&ctx->minor, 802+ ctx->major = gss_acquire_cred(&ctx->minor,
923+ gssname, 0, oidset, GSS_C_INITIATE, 803+ gssname, 0, oidset, GSS_C_INITIATE,
924+ &ctx->client_creds, NULL, NULL); 804+ &ctx->client_creds, NULL, NULL);
925+ 805+
926+ gss_release_name(&status, &gssname); 806+ gss_release_name(&status, &gssname);
@@ -935,13 +815,13 @@ index d56257b4a..491e62cee 100644
935 OM_uint32 815 OM_uint32
936 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) 816 ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
937 { 817 {
938+ if (ctx == NULL) 818+ if (ctx == NULL)
939+ return -1; 819+ return -1;
940+ 820+
941 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context, 821 if ((ctx->major = gss_get_mic(&ctx->minor, ctx->context,
942 GSS_C_QOP_DEFAULT, buffer, hash))) 822 GSS_C_QOP_DEFAULT, buffer, hash)))
943 ssh_gssapi_error(ctx); 823 ssh_gssapi_error(ctx);
944@@ -257,6 +451,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash) 824@@ -257,6 +471,19 @@ ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_t buffer, gss_buffer_t hash)
945 return (ctx->major); 825 return (ctx->major);
946 } 826 }
947 827
@@ -961,12 +841,12 @@ index d56257b4a..491e62cee 100644
961 void 841 void
962 ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, 842 ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service,
963 const char *context) 843 const char *context)
964@@ -273,11 +480,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service, 844@@ -273,11 +500,16 @@ ssh_gssapi_buildmic(struct sshbuf *b, const char *user, const char *service,
965 } 845 }
966 846
967 int 847 int
968-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 848-ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
969+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host, 849+ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host,
970+ const char *client) 850+ const char *client)
971 { 851 {
972 gss_buffer_desc token = GSS_C_EMPTY_BUFFER; 852 gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
@@ -979,7 +859,7 @@ index d56257b4a..491e62cee 100644
979 859
980 /* RFC 4462 says we MUST NOT do SPNEGO */ 860 /* RFC 4462 says we MUST NOT do SPNEGO */
981 if (oid->length == spnego_oid.length && 861 if (oid->length == spnego_oid.length &&
982@@ -287,6 +499,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 862@@ -287,6 +519,10 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
983 ssh_gssapi_build_ctx(ctx); 863 ssh_gssapi_build_ctx(ctx);
984 ssh_gssapi_set_oid(*ctx, oid); 864 ssh_gssapi_set_oid(*ctx, oid);
985 major = ssh_gssapi_import_name(*ctx, host); 865 major = ssh_gssapi_import_name(*ctx, host);
@@ -990,12 +870,12 @@ index d56257b4a..491e62cee 100644
990 if (!GSS_ERROR(major)) { 870 if (!GSS_ERROR(major)) {
991 major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token, 871 major = ssh_gssapi_init_ctx(*ctx, 0, GSS_C_NO_BUFFER, &token,
992 NULL); 872 NULL);
993@@ -296,10 +512,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host) 873@@ -296,10 +532,66 @@ ssh_gssapi_check_mechanism(Gssctxt **ctx, gss_OID oid, const char *host)
994 GSS_C_NO_BUFFER); 874 GSS_C_NO_BUFFER);
995 } 875 }
996 876
997- if (GSS_ERROR(major)) 877- if (GSS_ERROR(major))
998+ if (GSS_ERROR(major) || intctx != NULL) 878+ if (GSS_ERROR(major) || intctx != NULL)
999 ssh_gssapi_delete_ctx(ctx); 879 ssh_gssapi_delete_ctx(ctx);
1000 880
1001 return (!GSS_ERROR(major)); 881 return (!GSS_ERROR(major));
@@ -1010,7 +890,7 @@ index d56257b4a..491e62cee 100644
1010+ static OM_uint32 last_call = 0; 890+ static OM_uint32 last_call = 0;
1011+ OM_uint32 lifetime, now, major, minor; 891+ OM_uint32 lifetime, now, major, minor;
1012+ int equal; 892+ int equal;
1013+ 893+
1014+ now = time(NULL); 894+ now = time(NULL);
1015+ 895+
1016+ if (ctxt) { 896+ if (ctxt) {
@@ -1038,8 +918,8 @@ index d56257b4a..491e62cee 100644
1038+ 918+
1039+ if (saved_mech == GSS_C_NO_OID) 919+ if (saved_mech == GSS_C_NO_OID)
1040+ return 0; 920+ return 0;
1041+ 921+
1042+ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL, 922+ major = gss_inquire_cred(&minor, GSS_C_NO_CREDENTIAL,
1043+ &name, &lifetime, NULL, NULL); 923+ &name, &lifetime, NULL, NULL);
1044+ if (major == GSS_S_CREDENTIALS_EXPIRED) 924+ if (major == GSS_S_CREDENTIALS_EXPIRED)
1045+ return 0; 925+ return 0;
@@ -1059,7 +939,7 @@ index d56257b4a..491e62cee 100644
1059+ 939+
1060 #endif /* GSSAPI */ 940 #endif /* GSSAPI */
1061diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c 941diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
1062index a151bc1e4..90f8692f5 100644 942index a151bc1e4..ef9beb67c 100644
1063--- a/gss-serv-krb5.c 943--- a/gss-serv-krb5.c
1064+++ b/gss-serv-krb5.c 944+++ b/gss-serv-krb5.c
1065@@ -1,7 +1,7 @@ 945@@ -1,7 +1,7 @@
@@ -1107,7 +987,7 @@ index a151bc1e4..90f8692f5 100644
1107 } 987 }
1108 988
1109+int 989+int
1110+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store, 990+ssh_gssapi_krb5_updatecreds(ssh_gssapi_ccache *store,
1111+ ssh_gssapi_client *client) 991+ ssh_gssapi_client *client)
1112+{ 992+{
1113+ krb5_ccache ccache = NULL; 993+ krb5_ccache ccache = NULL;
@@ -1116,14 +996,14 @@ index a151bc1e4..90f8692f5 100644
1116+ krb5_error_code problem; 996+ krb5_error_code problem;
1117+ OM_uint32 maj_status, min_status; 997+ OM_uint32 maj_status, min_status;
1118+ 998+
1119+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) { 999+ if ((problem = krb5_cc_resolve(krb_context, store->envval, &ccache))) {
1120+ logit("krb5_cc_resolve(): %.100s", 1000+ logit("krb5_cc_resolve(): %.100s",
1121+ krb5_get_err_text(krb_context, problem)); 1001+ krb5_get_err_text(krb_context, problem));
1122+ return 0; 1002+ return 0;
1123+ } 1003+ }
1124+ 1004+
1125+ /* Find out who the principal in this cache is */ 1005+ /* Find out who the principal in this cache is */
1126+ if ((problem = krb5_cc_get_principal(krb_context, ccache, 1006+ if ((problem = krb5_cc_get_principal(krb_context, ccache,
1127+ &principal))) { 1007+ &principal))) {
1128+ logit("krb5_cc_get_principal(): %.100s", 1008+ logit("krb5_cc_get_principal(): %.100s",
1129+ krb5_get_err_text(krb_context, problem)); 1009+ krb5_get_err_text(krb_context, problem));
@@ -1185,7 +1065,7 @@ index a151bc1e4..90f8692f5 100644
1185 1065
1186 #endif /* KRB5 */ 1066 #endif /* KRB5 */
1187diff --git a/gss-serv.c b/gss-serv.c 1067diff --git a/gss-serv.c b/gss-serv.c
1188index ab3a15f0f..6c087a1b1 100644 1068index ab3a15f0f..1d47870e7 100644
1189--- a/gss-serv.c 1069--- a/gss-serv.c
1190+++ b/gss-serv.c 1070+++ b/gss-serv.c
1191@@ -1,7 +1,7 @@ 1071@@ -1,7 +1,7 @@
@@ -1197,7 +1077,7 @@ index ab3a15f0f..6c087a1b1 100644
1197 * 1077 *
1198 * Redistribution and use in source and binary forms, with or without 1078 * Redistribution and use in source and binary forms, with or without
1199 * modification, are permitted provided that the following conditions 1079 * modification, are permitted provided that the following conditions
1200@@ -44,17 +44,22 @@ 1080@@ -44,17 +44,19 @@
1201 #include "session.h" 1081 #include "session.h"
1202 #include "misc.h" 1082 #include "misc.h"
1203 #include "servconf.h" 1083 #include "servconf.h"
@@ -1205,16 +1085,14 @@ index ab3a15f0f..6c087a1b1 100644
1205 1085
1206 #include "ssh-gss.h" 1086 #include "ssh-gss.h"
1207+#include "monitor_wrap.h" 1087+#include "monitor_wrap.h"
1208+
1209+extern ServerOptions options;
1210 1088
1211 extern ServerOptions options; 1089 extern ServerOptions options;
1212 1090
1213 static ssh_gssapi_client gssapi_client = 1091 static ssh_gssapi_client gssapi_client =
1214 { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, 1092- { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER,
1215- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}}; 1093- GSS_C_NO_CREDENTIAL, NULL, {NULL, NULL, NULL, NULL}};
1216+ GSS_C_NO_CREDENTIAL, GSS_C_NO_NAME, NULL, 1094+ { GSS_C_EMPTY_BUFFER, GSS_C_EMPTY_BUFFER, GSS_C_NO_CREDENTIAL,
1217+ {NULL, NULL, NULL, NULL, NULL}, 0, 0}; 1095+ GSS_C_NO_NAME, NULL, {NULL, NULL, NULL, NULL, NULL}, 0, 0};
1218 1096
1219 ssh_gssapi_mech gssapi_null_mech = 1097 ssh_gssapi_mech gssapi_null_mech =
1220- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL}; 1098- { NULL, NULL, {0, NULL}, NULL, NULL, NULL, NULL};
@@ -1222,7 +1100,7 @@ index ab3a15f0f..6c087a1b1 100644
1222 1100
1223 #ifdef KRB5 1101 #ifdef KRB5
1224 extern ssh_gssapi_mech gssapi_kerberos_mech; 1102 extern ssh_gssapi_mech gssapi_kerberos_mech;
1225@@ -140,6 +145,28 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) 1103@@ -140,6 +142,29 @@ ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid)
1226 return (ssh_gssapi_acquire_cred(*ctx)); 1104 return (ssh_gssapi_acquire_cred(*ctx));
1227 } 1105 }
1228 1106
@@ -1232,7 +1110,8 @@ index ab3a15f0f..6c087a1b1 100644
1232+ if (supported_oids == NULL) 1110+ if (supported_oids == NULL)
1233+ ssh_gssapi_prepare_supported_oids(); 1111+ ssh_gssapi_prepare_supported_oids();
1234+ return (ssh_gssapi_kex_mechs(supported_oids, 1112+ return (ssh_gssapi_kex_mechs(supported_oids,
1235+ &ssh_gssapi_server_check_mech, NULL, NULL)); 1113+ &ssh_gssapi_server_check_mech, NULL, NULL,
1114+ options.gss_kex_algorithms));
1236+} 1115+}
1237+ 1116+
1238+/* Unprivileged */ 1117+/* Unprivileged */
@@ -1241,7 +1120,7 @@ index ab3a15f0f..6c087a1b1 100644
1241+ const char *dummy) { 1120+ const char *dummy) {
1242+ Gssctxt *ctx = NULL; 1121+ Gssctxt *ctx = NULL;
1243+ int res; 1122+ int res;
1244+ 1123+
1245+ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid))); 1124+ res = !GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctx, oid)));
1246+ ssh_gssapi_delete_ctx(&ctx); 1125+ ssh_gssapi_delete_ctx(&ctx);
1247+ 1126+
@@ -1251,7 +1130,7 @@ index ab3a15f0f..6c087a1b1 100644
1251 /* Unprivileged */ 1130 /* Unprivileged */
1252 void 1131 void
1253 ssh_gssapi_supported_oids(gss_OID_set *oidset) 1132 ssh_gssapi_supported_oids(gss_OID_set *oidset)
1254@@ -150,7 +177,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset) 1133@@ -150,7 +175,9 @@ ssh_gssapi_supported_oids(gss_OID_set *oidset)
1255 gss_OID_set supported; 1134 gss_OID_set supported;
1256 1135
1257 gss_create_empty_oid_set(&min_status, oidset); 1136 gss_create_empty_oid_set(&min_status, oidset);
@@ -1262,7 +1141,7 @@ index ab3a15f0f..6c087a1b1 100644
1262 1141
1263 while (supported_mechs[i]->name != NULL) { 1142 while (supported_mechs[i]->name != NULL) {
1264 if (GSS_ERROR(gss_test_oid_set_member(&min_status, 1143 if (GSS_ERROR(gss_test_oid_set_member(&min_status,
1265@@ -276,8 +305,48 @@ OM_uint32 1144@@ -276,8 +303,48 @@ OM_uint32
1266 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) 1145 ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
1267 { 1146 {
1268 int i = 0; 1147 int i = 0;
@@ -1278,21 +1157,21 @@ index ab3a15f0f..6c087a1b1 100644
1278+ return GSS_S_COMPLETE; 1157+ return GSS_S_COMPLETE;
1279+ } 1158+ }
1280+ 1159+
1281+ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor, 1160+ if ((ctx->major = gss_inquire_cred_by_mech(&ctx->minor,
1282+ ctx->client_creds, ctx->oid, &new_name, 1161+ ctx->client_creds, ctx->oid, &new_name,
1283+ NULL, NULL, NULL))) { 1162+ NULL, NULL, NULL))) {
1284+ ssh_gssapi_error(ctx); 1163+ ssh_gssapi_error(ctx);
1285+ return (ctx->major); 1164+ return (ctx->major);
1286+ } 1165+ }
1287+ 1166+
1288+ ctx->major = gss_compare_name(&ctx->minor, client->name, 1167+ ctx->major = gss_compare_name(&ctx->minor, client->name,
1289+ new_name, &equal); 1168+ new_name, &equal);
1290+ 1169+
1291+ if (GSS_ERROR(ctx->major)) { 1170+ if (GSS_ERROR(ctx->major)) {
1292+ ssh_gssapi_error(ctx); 1171+ ssh_gssapi_error(ctx);
1293+ return (ctx->major); 1172+ return (ctx->major);
1294+ } 1173+ }
1295+ 1174+
1296+ if (!equal) { 1175+ if (!equal) {
1297+ debug("Rekeyed credentials have different name"); 1176+ debug("Rekeyed credentials have different name");
1298+ return GSS_S_COMPLETE; 1177+ return GSS_S_COMPLETE;
@@ -1305,14 +1184,14 @@ index ab3a15f0f..6c087a1b1 100644
1305+ gss_release_cred(&ctx->minor, &client->creds); 1184+ gss_release_cred(&ctx->minor, &client->creds);
1306+ client->name = new_name; 1185+ client->name = new_name;
1307+ client->creds = ctx->client_creds; 1186+ client->creds = ctx->client_creds;
1308+ ctx->client_creds = GSS_C_NO_CREDENTIAL; 1187+ ctx->client_creds = GSS_C_NO_CREDENTIAL;
1309+ client->updated = 1; 1188+ client->updated = 1;
1310+ return GSS_S_COMPLETE; 1189+ return GSS_S_COMPLETE;
1311+ } 1190+ }
1312 1191
1313 client->mech = NULL; 1192 client->mech = NULL;
1314 1193
1315@@ -292,6 +361,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) 1194@@ -292,6 +359,13 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
1316 if (client->mech == NULL) 1195 if (client->mech == NULL)
1317 return GSS_S_FAILURE; 1196 return GSS_S_FAILURE;
1318 1197
@@ -1326,7 +1205,7 @@ index ab3a15f0f..6c087a1b1 100644
1326 if ((ctx->major = gss_display_name(&ctx->minor, ctx->client, 1205 if ((ctx->major = gss_display_name(&ctx->minor, ctx->client,
1327 &client->displayname, NULL))) { 1206 &client->displayname, NULL))) {
1328 ssh_gssapi_error(ctx); 1207 ssh_gssapi_error(ctx);
1329@@ -309,6 +385,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client) 1208@@ -309,6 +383,8 @@ ssh_gssapi_getclient(Gssctxt *ctx, ssh_gssapi_client *client)
1330 return (ctx->major); 1209 return (ctx->major);
1331 } 1210 }
1332 1211
@@ -1335,16 +1214,20 @@ index ab3a15f0f..6c087a1b1 100644
1335 /* We can't copy this structure, so we just move the pointer to it */ 1214 /* We can't copy this structure, so we just move the pointer to it */
1336 client->creds = ctx->client_creds; 1215 client->creds = ctx->client_creds;
1337 ctx->client_creds = GSS_C_NO_CREDENTIAL; 1216 ctx->client_creds = GSS_C_NO_CREDENTIAL;
1338@@ -356,7 +434,7 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep) 1217@@ -356,19 +432,23 @@ ssh_gssapi_do_child(char ***envp, u_int *envsizep)
1339 1218
1340 /* Privileged */ 1219 /* Privileged */
1341 int 1220 int
1342-ssh_gssapi_userok(char *user) 1221-ssh_gssapi_userok(char *user)
1343+ssh_gssapi_userok(char *user, struct passwd *pw) 1222+ssh_gssapi_userok(char *user, struct passwd *pw, int kex)
1344 { 1223 {
1345 OM_uint32 lmin; 1224 OM_uint32 lmin;
1346 1225
1347@@ -366,9 +444,11 @@ ssh_gssapi_userok(char *user) 1226+ (void) kex; /* used in privilege separation */
1227+
1228 if (gssapi_client.exportedname.length == 0 ||
1229 gssapi_client.exportedname.value == NULL) {
1230 debug("No suitable client data");
1348 return 0; 1231 return 0;
1349 } 1232 }
1350 if (gssapi_client.mech && gssapi_client.mech->userok) 1233 if (gssapi_client.mech && gssapi_client.mech->userok)
@@ -1365,7 +1248,7 @@ index ab3a15f0f..6c087a1b1 100644
1365-/* Privileged */ 1248-/* Privileged */
1366-OM_uint32 1249-OM_uint32
1367-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 1250-ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
1368+/* These bits are only used for rekeying. The unpriviledged child is running 1251+/* These bits are only used for rekeying. The unpriviledged child is running
1369+ * as the user, the monitor is root. 1252+ * as the user, the monitor is root.
1370+ * 1253+ *
1371+ * In the child, we want to : 1254+ * In the child, we want to :
@@ -1376,7 +1259,7 @@ index ab3a15f0f..6c087a1b1 100644
1376+/* Stuff for PAM */ 1259+/* Stuff for PAM */
1377+ 1260+
1378+#ifdef USE_PAM 1261+#ifdef USE_PAM
1379+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg, 1262+static int ssh_gssapi_simple_conv(int n, const struct pam_message **msg,
1380+ struct pam_response **resp, void *data) 1263+ struct pam_response **resp, void *data)
1381 { 1264 {
1382- ctx->major = gss_verify_mic(&ctx->minor, ctx->context, 1265- ctx->major = gss_verify_mic(&ctx->minor, ctx->context,
@@ -1389,18 +1272,18 @@ index ab3a15f0f..6c087a1b1 100644
1389+void 1272+void
1390+ssh_gssapi_rekey_creds(void) { 1273+ssh_gssapi_rekey_creds(void) {
1391+ int ok; 1274+ int ok;
1392+ int ret;
1393+#ifdef USE_PAM 1275+#ifdef USE_PAM
1276+ int ret;
1394+ pam_handle_t *pamh = NULL; 1277+ pam_handle_t *pamh = NULL;
1395+ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL}; 1278+ struct pam_conv pamconv = {ssh_gssapi_simple_conv, NULL};
1396+ char *envstr; 1279+ char *envstr;
1397+#endif 1280+#endif
1398+ 1281+
1399+ if (gssapi_client.store.filename == NULL && 1282+ if (gssapi_client.store.filename == NULL &&
1400+ gssapi_client.store.envval == NULL && 1283+ gssapi_client.store.envval == NULL &&
1401+ gssapi_client.store.envvar == NULL) 1284+ gssapi_client.store.envvar == NULL)
1402+ return; 1285+ return;
1403+ 1286+
1404+ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store)); 1287+ ok = PRIVSEP(ssh_gssapi_update_creds(&gssapi_client.store));
1405+ 1288+
1406+ if (!ok) 1289+ if (!ok)
@@ -1423,7 +1306,7 @@ index ab3a15f0f..6c087a1b1 100644
1423+ if (ret) 1306+ if (ret)
1424+ return; 1307+ return;
1425+ 1308+
1426+ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar, 1309+ xasprintf(&envstr, "%s=%s", gssapi_client.store.envvar,
1427+ gssapi_client.store.envval); 1310+ gssapi_client.store.envval);
1428+ 1311+
1429+ ret = pam_putenv(pamh, envstr); 1312+ ret = pam_putenv(pamh, envstr);
@@ -1433,7 +1316,7 @@ index ab3a15f0f..6c087a1b1 100644
1433+#endif 1316+#endif
1434+} 1317+}
1435+ 1318+
1436+int 1319+int
1437+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) { 1320+ssh_gssapi_update_creds(ssh_gssapi_ccache *store) {
1438+ int ok = 0; 1321+ int ok = 0;
1439+ 1322+
@@ -1455,11 +1338,29 @@ index ab3a15f0f..6c087a1b1 100644
1455 } 1338 }
1456 1339
1457 /* Privileged */ 1340 /* Privileged */
1341diff --git a/hmac.c b/hmac.c
1342index 1c879640c..a29f32c5c 100644
1343--- a/hmac.c
1344+++ b/hmac.c
1345@@ -19,6 +19,7 @@
1346
1347 #include <sys/types.h>
1348 #include <string.h>
1349+#include <stdlib.h>
1350
1351 #include "sshbuf.h"
1352 #include "digest.h"
1458diff --git a/kex.c b/kex.c 1353diff --git a/kex.c b/kex.c
1459index 25f9f66f6..fb5bfaea5 100644 1354index 34808b5c3..a2a4794e8 100644
1460--- a/kex.c 1355--- a/kex.c
1461+++ b/kex.c 1356+++ b/kex.c
1462@@ -54,6 +54,10 @@ 1357@@ -55,11 +55,16 @@
1358 #include "misc.h"
1359 #include "dispatch.h"
1360 #include "monitor.h"
1361+#include "xmalloc.h"
1362
1363 #include "ssherr.h"
1463 #include "sshbuf.h" 1364 #include "sshbuf.h"
1464 #include "digest.h" 1365 #include "digest.h"
1465 1366
@@ -1470,57 +1371,129 @@ index 25f9f66f6..fb5bfaea5 100644
1470 /* prototype */ 1371 /* prototype */
1471 static int kex_choose_conf(struct ssh *); 1372 static int kex_choose_conf(struct ssh *);
1472 static int kex_input_newkeys(int, u_int32_t, struct ssh *); 1373 static int kex_input_newkeys(int, u_int32_t, struct ssh *);
1473@@ -105,6 +109,14 @@ static const struct kexalg kexalgs[] = { 1374@@ -113,15 +118,28 @@ static const struct kexalg kexalgs[] = {
1474 #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */ 1375 #endif /* HAVE_EVP_SHA256 || !WITH_OPENSSL */
1475 { NULL, -1, -1, -1}, 1376 { NULL, -1, -1, -1},
1476 }; 1377 };
1477+static const struct kexalg kexalg_prefixes[] = { 1378+static const struct kexalg gss_kexalgs[] = {
1478+#ifdef GSSAPI 1379+#ifdef GSSAPI
1479+ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, 1380+ { KEX_GSS_GEX_SHA1_ID, KEX_GSS_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
1480+ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, 1381+ { KEX_GSS_GRP1_SHA1_ID, KEX_GSS_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
1481+ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, 1382+ { KEX_GSS_GRP14_SHA1_ID, KEX_GSS_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
1383+ { KEX_GSS_GRP14_SHA256_ID, KEX_GSS_GRP14_SHA256, 0, SSH_DIGEST_SHA256 },
1384+ { KEX_GSS_GRP16_SHA512_ID, KEX_GSS_GRP16_SHA512, 0, SSH_DIGEST_SHA512 },
1385+ { KEX_GSS_NISTP256_SHA256_ID, KEX_GSS_NISTP256_SHA256,
1386+ NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
1387+ { KEX_GSS_C25519_SHA256_ID, KEX_GSS_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
1482+#endif 1388+#endif
1483+ { NULL, -1, -1, -1 }, 1389+ { NULL, -1, -1, -1 },
1484+}; 1390+};
1485 1391
1486 char * 1392-char *
1487 kex_alg_list(char sep) 1393-kex_alg_list(char sep)
1488@@ -137,6 +149,10 @@ kex_alg_by_name(const char *name) 1394+static char *
1395+kex_alg_list_internal(char sep, const struct kexalg *algs)
1396 {
1397 char *ret = NULL, *tmp;
1398 size_t nlen, rlen = 0;
1399 const struct kexalg *k;
1400
1401- for (k = kexalgs; k->name != NULL; k++) {
1402+ for (k = algs; k->name != NULL; k++) {
1403 if (ret != NULL)
1404 ret[rlen++] = sep;
1405 nlen = strlen(k->name);
1406@@ -136,6 +154,18 @@ kex_alg_list(char sep)
1407 return ret;
1408 }
1409
1410+char *
1411+kex_alg_list(char sep)
1412+{
1413+ return kex_alg_list_internal(sep, kexalgs);
1414+}
1415+
1416+char *
1417+kex_gss_alg_list(char sep)
1418+{
1419+ return kex_alg_list_internal(sep, gss_kexalgs);
1420+}
1421+
1422 static const struct kexalg *
1423 kex_alg_by_name(const char *name)
1424 {
1425@@ -145,6 +175,10 @@ kex_alg_by_name(const char *name)
1489 if (strcmp(k->name, name) == 0) 1426 if (strcmp(k->name, name) == 0)
1490 return k; 1427 return k;
1491 } 1428 }
1492+ for (k = kexalg_prefixes; k->name != NULL; k++) { 1429+ for (k = gss_kexalgs; k->name != NULL; k++) {
1493+ if (strncmp(k->name, name, strlen(k->name)) == 0) 1430+ if (strncmp(k->name, name, strlen(k->name)) == 0)
1494+ return k; 1431+ return k;
1495+ } 1432+ }
1496 return NULL; 1433 return NULL;
1497 } 1434 }
1498 1435
1499@@ -653,6 +669,9 @@ kex_free(struct kex *kex) 1436@@ -301,6 +335,29 @@ kex_assemble_names(char **listp, const char *def, const char *all)
1500 sshbuf_free(kex->peer); 1437 return r;
1501 sshbuf_free(kex->my); 1438 }
1439
1440+/* Validate GSS KEX method name list */
1441+int
1442+kex_gss_names_valid(const char *names)
1443+{
1444+ char *s, *cp, *p;
1445+
1446+ if (names == NULL || *names == '\0')
1447+ return 0;
1448+ s = cp = xstrdup(names);
1449+ for ((p = strsep(&cp, ",")); p && *p != '\0';
1450+ (p = strsep(&cp, ","))) {
1451+ if (strncmp(p, "gss-", 4) != 0
1452+ || kex_alg_by_name(p) == NULL) {
1453+ error("Unsupported KEX algorithm \"%.100s\"", p);
1454+ free(s);
1455+ return 0;
1456+ }
1457+ }
1458+ debug3("gss kex names ok: [%s]", names);
1459+ free(s);
1460+ return 1;
1461+}
1462+
1463 /* put algorithm proposal into buffer */
1464 int
1465 kex_prop2buf(struct sshbuf *b, char *proposal[PROPOSAL_MAX])
1466@@ -657,6 +714,9 @@ kex_free(struct kex *kex)
1467 sshbuf_free(kex->server_version);
1468 sshbuf_free(kex->client_pub);
1502 free(kex->session_id); 1469 free(kex->session_id);
1503+#ifdef GSSAPI 1470+#ifdef GSSAPI
1504+ free(kex->gss_host); 1471+ free(kex->gss_host);
1505+#endif /* GSSAPI */ 1472+#endif /* GSSAPI */
1506 free(kex->client_version_string);
1507 free(kex->server_version_string);
1508 free(kex->failed_choice); 1473 free(kex->failed_choice);
1474 free(kex->hostkey_alg);
1475 free(kex->name);
1509diff --git a/kex.h b/kex.h 1476diff --git a/kex.h b/kex.h
1510index 593de1208..4e5ead839 100644 1477index 6d446d1cc..2d5f1d4ed 100644
1511--- a/kex.h 1478--- a/kex.h
1512+++ b/kex.h 1479+++ b/kex.h
1513@@ -100,6 +100,9 @@ enum kex_exchange { 1480@@ -103,6 +103,15 @@ enum kex_exchange {
1514 KEX_DH_GEX_SHA256,
1515 KEX_ECDH_SHA2, 1481 KEX_ECDH_SHA2,
1516 KEX_C25519_SHA256, 1482 KEX_C25519_SHA256,
1483 KEX_KEM_SNTRUP4591761X25519_SHA512,
1484+#ifdef GSSAPI
1517+ KEX_GSS_GRP1_SHA1, 1485+ KEX_GSS_GRP1_SHA1,
1518+ KEX_GSS_GRP14_SHA1, 1486+ KEX_GSS_GRP14_SHA1,
1487+ KEX_GSS_GRP14_SHA256,
1488+ KEX_GSS_GRP16_SHA512,
1519+ KEX_GSS_GEX_SHA1, 1489+ KEX_GSS_GEX_SHA1,
1490+ KEX_GSS_NISTP256_SHA256,
1491+ KEX_GSS_C25519_SHA256,
1492+#endif
1520 KEX_MAX 1493 KEX_MAX
1521 }; 1494 };
1522 1495
1523@@ -148,6 +151,12 @@ struct kex { 1496@@ -154,6 +163,12 @@ struct kex {
1524 u_int flags; 1497 u_int flags;
1525 int hash_alg; 1498 int hash_alg;
1526 int ec_nid; 1499 int ec_nid;
@@ -1530,27 +1503,93 @@ index 593de1208..4e5ead839 100644
1530+ char *gss_host; 1503+ char *gss_host;
1531+ char *gss_client; 1504+ char *gss_client;
1532+#endif 1505+#endif
1533 char *client_version_string;
1534 char *server_version_string;
1535 char *failed_choice; 1506 char *failed_choice;
1536@@ -198,6 +207,11 @@ int kexecdh_server(struct ssh *); 1507 int (*verify_host_key)(struct sshkey *, struct ssh *);
1537 int kexc25519_client(struct ssh *); 1508 struct sshkey *(*load_host_public_key)(int, int, struct ssh *);
1538 int kexc25519_server(struct ssh *); 1509@@ -175,8 +190,10 @@ struct kex {
1539 1510
1540+#ifdef GSSAPI 1511 int kex_names_valid(const char *);
1512 char *kex_alg_list(char);
1513+char *kex_gss_alg_list(char);
1514 char *kex_names_cat(const char *, const char *);
1515 int kex_assemble_names(char **, const char *, const char *);
1516+int kex_gss_names_valid(const char *);
1517
1518 int kex_exchange_identification(struct ssh *, int, const char *);
1519
1520@@ -203,6 +220,12 @@ int kexgex_client(struct ssh *);
1521 int kexgex_server(struct ssh *);
1522 int kex_gen_client(struct ssh *);
1523 int kex_gen_server(struct ssh *);
1524+#if defined(GSSAPI) && defined(WITH_OPENSSL)
1525+int kexgssgex_client(struct ssh *);
1526+int kexgssgex_server(struct ssh *);
1541+int kexgss_client(struct ssh *); 1527+int kexgss_client(struct ssh *);
1542+int kexgss_server(struct ssh *); 1528+int kexgss_server(struct ssh *);
1543+#endif 1529+#endif
1544+ 1530
1545 int kex_dh_hash(int, const char *, const char *, 1531 int kex_dh_keypair(struct kex *);
1546 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, 1532 int kex_dh_enc(struct kex *, const struct sshbuf *, struct sshbuf **,
1547 const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); 1533@@ -235,6 +258,12 @@ int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *,
1534 const BIGNUM *, const u_char *, size_t,
1535 u_char *, size_t *);
1536
1537+int kex_gen_hash(int hash_alg, const struct sshbuf *client_version,
1538+ const struct sshbuf *server_version, const struct sshbuf *client_kexinit,
1539+ const struct sshbuf *server_kexinit, const struct sshbuf *server_host_key_blob,
1540+ const struct sshbuf *client_pub, const struct sshbuf *server_pub,
1541+ const struct sshbuf *shared_secret, u_char *hash, size_t *hashlen);
1542+
1543 void kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
1544 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE)))
1545 __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE)));
1546diff --git a/kexdh.c b/kexdh.c
1547index 67133e339..edaa46762 100644
1548--- a/kexdh.c
1549+++ b/kexdh.c
1550@@ -48,13 +48,23 @@ kex_dh_keygen(struct kex *kex)
1551 {
1552 switch (kex->kex_type) {
1553 case KEX_DH_GRP1_SHA1:
1554+#ifdef GSSAPI
1555+ case KEX_GSS_GRP1_SHA1:
1556+#endif
1557 kex->dh = dh_new_group1();
1558 break;
1559 case KEX_DH_GRP14_SHA1:
1560 case KEX_DH_GRP14_SHA256:
1561+#ifdef GSSAPI
1562+ case KEX_GSS_GRP14_SHA1:
1563+ case KEX_GSS_GRP14_SHA256:
1564+#endif
1565 kex->dh = dh_new_group14();
1566 break;
1567 case KEX_DH_GRP16_SHA512:
1568+#ifdef GSSAPI
1569+ case KEX_GSS_GRP16_SHA512:
1570+#endif
1571 kex->dh = dh_new_group16();
1572 break;
1573 case KEX_DH_GRP18_SHA512:
1574diff --git a/kexgen.c b/kexgen.c
1575index 2abbb9ef6..569dc83f3 100644
1576--- a/kexgen.c
1577+++ b/kexgen.c
1578@@ -43,7 +43,7 @@
1579 static int input_kex_gen_init(int, u_int32_t, struct ssh *);
1580 static int input_kex_gen_reply(int type, u_int32_t seq, struct ssh *ssh);
1581
1582-static int
1583+int
1584 kex_gen_hash(
1585 int hash_alg,
1586 const struct sshbuf *client_version,
1548diff --git a/kexgssc.c b/kexgssc.c 1587diff --git a/kexgssc.c b/kexgssc.c
1549new file mode 100644 1588new file mode 100644
1550index 000000000..3c8ae08dd 1589index 000000000..f6e1405eb
1551--- /dev/null 1590--- /dev/null
1552+++ b/kexgssc.c 1591+++ b/kexgssc.c
1553@@ -0,0 +1,341 @@ 1592@@ -0,0 +1,606 @@
1554+/* 1593+/*
1555+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. 1594+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
1556+ * 1595+ *
@@ -1577,7 +1616,7 @@ index 000000000..3c8ae08dd
1577+ 1616+
1578+#include "includes.h" 1617+#include "includes.h"
1579+ 1618+
1580+#ifdef GSSAPI 1619+#if defined(GSSAPI) && defined(WITH_OPENSSL)
1581+ 1620+
1582+#include "includes.h" 1621+#include "includes.h"
1583+ 1622+
@@ -1596,113 +1635,88 @@ index 000000000..3c8ae08dd
1596+#include "packet.h" 1635+#include "packet.h"
1597+#include "dh.h" 1636+#include "dh.h"
1598+#include "digest.h" 1637+#include "digest.h"
1638+#include "ssherr.h"
1599+ 1639+
1600+#include "ssh-gss.h" 1640+#include "ssh-gss.h"
1601+ 1641+
1602+int 1642+int
1603+kexgss_client(struct ssh *ssh) { 1643+kexgss_client(struct ssh *ssh)
1604+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 1644+{
1605+ gss_buffer_desc recv_tok, gssbuf, msg_tok, *token_ptr; 1645+ struct kex *kex = ssh->kex;
1646+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER,
1647+ recv_tok = GSS_C_EMPTY_BUFFER,
1648+ gssbuf, msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr;
1606+ Gssctxt *ctxt; 1649+ Gssctxt *ctxt;
1607+ OM_uint32 maj_status, min_status, ret_flags; 1650+ OM_uint32 maj_status, min_status, ret_flags;
1608+ u_int klen, kout, slen = 0, strlen; 1651+ struct sshbuf *server_blob = NULL;
1609+ DH *dh; 1652+ struct sshbuf *shared_secret = NULL;
1610+ BIGNUM *dh_server_pub = NULL; 1653+ struct sshbuf *server_host_key_blob = NULL;
1611+ BIGNUM *shared_secret = NULL; 1654+ struct sshbuf *empty = NULL;
1612+ const BIGNUM *pub_key, *dh_p, *dh_g; 1655+ u_char *msg;
1613+ BIGNUM *p = NULL;
1614+ BIGNUM *g = NULL;
1615+ u_char *kbuf;
1616+ u_char *serverhostkey = NULL;
1617+ u_char *empty = "";
1618+ char *msg;
1619+ int type = 0; 1656+ int type = 0;
1620+ int first = 1; 1657+ int first = 1;
1621+ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
1622+ u_char hash[SSH_DIGEST_MAX_LENGTH]; 1658+ u_char hash[SSH_DIGEST_MAX_LENGTH];
1623+ size_t hashlen; 1659+ size_t hashlen;
1660+ u_char c;
1661+ int r;
1624+ 1662+
1625+ /* Initialise our GSSAPI world */ 1663+ /* Initialise our GSSAPI world */
1626+ ssh_gssapi_build_ctx(&ctxt); 1664+ ssh_gssapi_build_ctx(&ctxt);
1627+ if (ssh_gssapi_id_kex(ctxt, ssh->kex->name, ssh->kex->kex_type) 1665+ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)
1628+ == GSS_C_NO_OID) 1666+ == GSS_C_NO_OID)
1629+ fatal("Couldn't identify host exchange"); 1667+ fatal("Couldn't identify host exchange");
1630+ 1668+
1631+ if (ssh_gssapi_import_name(ctxt, ssh->kex->gss_host)) 1669+ if (ssh_gssapi_import_name(ctxt, kex->gss_host))
1632+ fatal("Couldn't import hostname"); 1670+ fatal("Couldn't import hostname");
1633+ 1671+
1634+ if (ssh->kex->gss_client && 1672+ if (kex->gss_client &&
1635+ ssh_gssapi_client_identity(ctxt, ssh->kex->gss_client)) 1673+ ssh_gssapi_client_identity(ctxt, kex->gss_client))
1636+ fatal("Couldn't acquire client credentials"); 1674+ fatal("Couldn't acquire client credentials");
1637+ 1675+
1638+ switch (ssh->kex->kex_type) { 1676+ /* Step 1 */
1677+ switch (kex->kex_type) {
1639+ case KEX_GSS_GRP1_SHA1: 1678+ case KEX_GSS_GRP1_SHA1:
1640+ dh = dh_new_group1();
1641+ break;
1642+ case KEX_GSS_GRP14_SHA1: 1679+ case KEX_GSS_GRP14_SHA1:
1643+ dh = dh_new_group14(); 1680+ case KEX_GSS_GRP14_SHA256:
1681+ case KEX_GSS_GRP16_SHA512:
1682+ r = kex_dh_keypair(kex);
1683+ break;
1684+ case KEX_GSS_NISTP256_SHA256:
1685+ r = kex_ecdh_keypair(kex);
1644+ break; 1686+ break;
1645+ case KEX_GSS_GEX_SHA1: 1687+ case KEX_GSS_C25519_SHA256:
1646+ debug("Doing group exchange\n"); 1688+ r = kex_c25519_keypair(kex);
1647+ nbits = dh_estimate(ssh->kex->we_need * 8);
1648+ packet_start(SSH2_MSG_KEXGSS_GROUPREQ);
1649+ packet_put_int(min);
1650+ packet_put_int(nbits);
1651+ packet_put_int(max);
1652+
1653+ packet_send();
1654+
1655+ packet_read_expect(SSH2_MSG_KEXGSS_GROUP);
1656+
1657+ if ((p = BN_new()) == NULL)
1658+ fatal("BN_new() failed");
1659+ packet_get_bignum2(p);
1660+ if ((g = BN_new()) == NULL)
1661+ fatal("BN_new() failed");
1662+ packet_get_bignum2(g);
1663+ packet_check_eom();
1664+
1665+ if (BN_num_bits(p) < min || BN_num_bits(p) > max)
1666+ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
1667+ min, BN_num_bits(p), max);
1668+
1669+ dh = dh_new_group(g, p);
1670+ break; 1689+ break;
1671+ default: 1690+ default:
1672+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); 1691+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
1673+ } 1692+ }
1674+ 1693+ if (r != 0)
1675+ /* Step 1 - e is dh->pub_key */ 1694+ return r;
1676+ dh_gen_key(dh, ssh->kex->we_need * 8);
1677+ DH_get0_key(dh, &pub_key, NULL);
1678+ DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
1679+
1680+ /* This is f, we initialise it now to make life easier */
1681+ dh_server_pub = BN_new();
1682+ if (dh_server_pub == NULL)
1683+ fatal("dh_server_pub == NULL");
1684+ 1695+
1685+ token_ptr = GSS_C_NO_BUFFER; 1696+ token_ptr = GSS_C_NO_BUFFER;
1686+ 1697+
1687+ do { 1698+ do {
1688+ debug("Calling gss_init_sec_context"); 1699+ debug("Calling gss_init_sec_context");
1689+ 1700+
1690+ maj_status = ssh_gssapi_init_ctx(ctxt, 1701+ maj_status = ssh_gssapi_init_ctx(ctxt,
1691+ ssh->kex->gss_deleg_creds, token_ptr, &send_tok, 1702+ kex->gss_deleg_creds, token_ptr, &send_tok,
1692+ &ret_flags); 1703+ &ret_flags);
1693+ 1704+
1694+ if (GSS_ERROR(maj_status)) { 1705+ if (GSS_ERROR(maj_status)) {
1706+ /* XXX Useles code: Missing send? */
1695+ if (send_tok.length != 0) { 1707+ if (send_tok.length != 0) {
1696+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); 1708+ if ((r = sshpkt_start(ssh,
1697+ packet_put_string(send_tok.value, 1709+ SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
1698+ send_tok.length); 1710+ (r = sshpkt_put_string(ssh, send_tok.value,
1711+ send_tok.length)) != 0)
1712+ fatal("sshpkt failed: %s", ssh_err(r));
1699+ } 1713+ }
1700+ fatal("gss_init_context failed"); 1714+ fatal("gss_init_context failed");
1701+ } 1715+ }
1702+ 1716+
1703+ /* If we've got an old receive buffer get rid of it */ 1717+ /* If we've got an old receive buffer get rid of it */
1704+ if (token_ptr != GSS_C_NO_BUFFER) 1718+ if (token_ptr != GSS_C_NO_BUFFER)
1705+ free(recv_tok.value); 1719+ gss_release_buffer(&min_status, &recv_tok);
1706+ 1720+
1707+ if (maj_status == GSS_S_COMPLETE) { 1721+ if (maj_status == GSS_S_COMPLETE) {
1708+ /* If mutual state flag is not true, kex fails */ 1722+ /* If mutual state flag is not true, kex fails */
@@ -1714,75 +1728,90 @@ index 000000000..3c8ae08dd
1714+ fatal("Integrity check failed"); 1728+ fatal("Integrity check failed");
1715+ } 1729+ }
1716+ 1730+
1717+ /* 1731+ /*
1718+ * If we have data to send, then the last message that we 1732+ * If we have data to send, then the last message that we
1719+ * received cannot have been a 'complete'. 1733+ * received cannot have been a 'complete'.
1720+ */ 1734+ */
1721+ if (send_tok.length != 0) { 1735+ if (send_tok.length != 0) {
1722+ if (first) { 1736+ if (first) {
1723+ packet_start(SSH2_MSG_KEXGSS_INIT); 1737+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 ||
1724+ packet_put_string(send_tok.value, 1738+ (r = sshpkt_put_string(ssh, send_tok.value,
1725+ send_tok.length); 1739+ send_tok.length)) != 0 ||
1726+ packet_put_bignum2(pub_key); 1740+ (r = sshpkt_put_stringb(ssh, kex->client_pub)) != 0)
1741+ fatal("failed to construct packet: %s", ssh_err(r));
1727+ first = 0; 1742+ first = 0;
1728+ } else { 1743+ } else {
1729+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); 1744+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
1730+ packet_put_string(send_tok.value, 1745+ (r = sshpkt_put_string(ssh, send_tok.value,
1731+ send_tok.length); 1746+ send_tok.length)) != 0)
1747+ fatal("failed to construct packet: %s", ssh_err(r));
1732+ } 1748+ }
1733+ packet_send(); 1749+ if ((r = sshpkt_send(ssh)) != 0)
1750+ fatal("failed to send packet: %s", ssh_err(r));
1734+ gss_release_buffer(&min_status, &send_tok); 1751+ gss_release_buffer(&min_status, &send_tok);
1735+ 1752+
1736+ /* If we've sent them data, they should reply */ 1753+ /* If we've sent them data, they should reply */
1737+ do { 1754+ do {
1738+ type = packet_read(); 1755+ type = ssh_packet_read(ssh);
1739+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) { 1756+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
1740+ debug("Received KEXGSS_HOSTKEY"); 1757+ debug("Received KEXGSS_HOSTKEY");
1741+ if (serverhostkey) 1758+ if (server_host_key_blob)
1742+ fatal("Server host key received more than once"); 1759+ fatal("Server host key received more than once");
1743+ serverhostkey = 1760+ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
1744+ packet_get_string(&slen); 1761+ fatal("Failed to read server host key: %s", ssh_err(r));
1745+ } 1762+ }
1746+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY); 1763+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
1747+ 1764+
1748+ switch (type) { 1765+ switch (type) {
1749+ case SSH2_MSG_KEXGSS_CONTINUE: 1766+ case SSH2_MSG_KEXGSS_CONTINUE:
1750+ debug("Received GSSAPI_CONTINUE"); 1767+ debug("Received GSSAPI_CONTINUE");
1751+ if (maj_status == GSS_S_COMPLETE) 1768+ if (maj_status == GSS_S_COMPLETE)
1752+ fatal("GSSAPI Continue received from server when complete"); 1769+ fatal("GSSAPI Continue received from server when complete");
1753+ recv_tok.value = packet_get_string(&strlen); 1770+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
1754+ recv_tok.length = strlen; 1771+ &recv_tok)) != 0 ||
1772+ (r = sshpkt_get_end(ssh)) != 0)
1773+ fatal("Failed to read token: %s", ssh_err(r));
1755+ break; 1774+ break;
1756+ case SSH2_MSG_KEXGSS_COMPLETE: 1775+ case SSH2_MSG_KEXGSS_COMPLETE:
1757+ debug("Received GSSAPI_COMPLETE"); 1776+ debug("Received GSSAPI_COMPLETE");
1758+ packet_get_bignum2(dh_server_pub); 1777+ if (msg_tok.value != NULL)
1759+ msg_tok.value = packet_get_string(&strlen); 1778+ fatal("Received GSSAPI_COMPLETE twice?");
1760+ msg_tok.length = strlen; 1779+ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
1780+ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
1781+ &msg_tok)) != 0)
1782+ fatal("Failed to read message: %s", ssh_err(r));
1761+ 1783+
1762+ /* Is there a token included? */ 1784+ /* Is there a token included? */
1763+ if (packet_get_char()) { 1785+ if ((r = sshpkt_get_u8(ssh, &c)) != 0)
1764+ recv_tok.value= 1786+ fatal("sshpkt failed: %s", ssh_err(r));
1765+ packet_get_string(&strlen); 1787+ if (c) {
1766+ recv_tok.length = strlen; 1788+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(
1789+ ssh, &recv_tok)) != 0)
1790+ fatal("Failed to read token: %s", ssh_err(r));
1767+ /* If we're already complete - protocol error */ 1791+ /* If we're already complete - protocol error */
1768+ if (maj_status == GSS_S_COMPLETE) 1792+ if (maj_status == GSS_S_COMPLETE)
1769+ packet_disconnect("Protocol error: received token when complete"); 1793+ sshpkt_disconnect(ssh, "Protocol error: received token when complete");
1770+ } else { 1794+ } else {
1771+ /* No token included */ 1795+ /* No token included */
1772+ if (maj_status != GSS_S_COMPLETE) 1796+ if (maj_status != GSS_S_COMPLETE)
1773+ packet_disconnect("Protocol error: did not receive final token"); 1797+ sshpkt_disconnect(ssh, "Protocol error: did not receive final token");
1798+ }
1799+ if ((r = sshpkt_get_end(ssh)) != 0) {
1800+ fatal("Expecting end of packet.");
1774+ } 1801+ }
1775+ break; 1802+ break;
1776+ case SSH2_MSG_KEXGSS_ERROR: 1803+ case SSH2_MSG_KEXGSS_ERROR:
1777+ debug("Received Error"); 1804+ debug("Received Error");
1778+ maj_status = packet_get_int(); 1805+ if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 ||
1779+ min_status = packet_get_int(); 1806+ (r = sshpkt_get_u32(ssh, &min_status)) != 0 ||
1780+ msg = packet_get_string(NULL); 1807+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
1781+ (void) packet_get_string_ptr(NULL); 1808+ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */
1782+ fatal("GSSAPI Error: \n%.400s",msg); 1809+ (r = sshpkt_get_end(ssh)) != 0)
1810+ fatal("sshpkt_get failed: %s", ssh_err(r));
1811+ fatal("GSSAPI Error: \n%.400s", msg);
1783+ default: 1812+ default:
1784+ packet_disconnect("Protocol error: didn't expect packet type %d", 1813+ sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d",
1785+ type); 1814+ type);
1786+ } 1815+ }
1787+ token_ptr = &recv_tok; 1816+ token_ptr = &recv_tok;
1788+ } else { 1817+ } else {
@@ -1792,93 +1821,358 @@ index 000000000..3c8ae08dd
1792+ } 1821+ }
1793+ } while (maj_status & GSS_S_CONTINUE_NEEDED); 1822+ } while (maj_status & GSS_S_CONTINUE_NEEDED);
1794+ 1823+
1795+ /* 1824+ /*
1796+ * We _must_ have received a COMPLETE message in reply from the 1825+ * We _must_ have received a COMPLETE message in reply from the
1797+ * server, which will have set dh_server_pub and msg_tok 1826+ * server, which will have set server_blob and msg_tok
1798+ */ 1827+ */
1799+ 1828+
1800+ if (type != SSH2_MSG_KEXGSS_COMPLETE) 1829+ if (type != SSH2_MSG_KEXGSS_COMPLETE)
1801+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it"); 1830+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
1802+ 1831+
1803+ /* Check f in range [1, p-1] */ 1832+ /* compute shared secret */
1804+ if (!dh_pub_is_valid(dh, dh_server_pub)) 1833+ switch (kex->kex_type) {
1805+ packet_disconnect("bad server public DH value");
1806+
1807+ /* compute K=f^x mod p */
1808+ klen = DH_size(dh);
1809+ kbuf = xmalloc(klen);
1810+ kout = DH_compute_key(kbuf, dh_server_pub, dh);
1811+ if (kout < 0)
1812+ fatal("DH_compute_key: failed");
1813+
1814+ shared_secret = BN_new();
1815+ if (shared_secret == NULL)
1816+ fatal("kexgss_client: BN_new failed");
1817+
1818+ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL)
1819+ fatal("kexdh_client: BN_bin2bn failed");
1820+
1821+ memset(kbuf, 0, klen);
1822+ free(kbuf);
1823+
1824+ hashlen = sizeof(hash);
1825+ switch (ssh->kex->kex_type) {
1826+ case KEX_GSS_GRP1_SHA1: 1834+ case KEX_GSS_GRP1_SHA1:
1827+ case KEX_GSS_GRP14_SHA1: 1835+ case KEX_GSS_GRP14_SHA1:
1828+ kex_dh_hash( 1836+ case KEX_GSS_GRP14_SHA256:
1829+ ssh->kex->hash_alg, 1837+ case KEX_GSS_GRP16_SHA512:
1830+ ssh->kex->client_version_string, 1838+ r = kex_dh_dec(kex, server_blob, &shared_secret);
1831+ ssh->kex->server_version_string, 1839+ break;
1832+ sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), 1840+ case KEX_GSS_C25519_SHA256:
1833+ sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), 1841+ if (sshbuf_ptr(server_blob)[sshbuf_len(server_blob)] & 0x80)
1834+ (serverhostkey ? serverhostkey : empty), slen, 1842+ fatal("The received key has MSB of last octet set!");
1835+ pub_key, /* e */ 1843+ r = kex_c25519_dec(kex, server_blob, &shared_secret);
1836+ dh_server_pub, /* f */
1837+ shared_secret, /* K */
1838+ hash, &hashlen
1839+ );
1840+ break; 1844+ break;
1841+ case KEX_GSS_GEX_SHA1: 1845+ case KEX_GSS_NISTP256_SHA256:
1842+ kexgex_hash( 1846+ if (sshbuf_len(server_blob) != 65)
1843+ ssh->kex->hash_alg, 1847+ fatal("The received NIST-P256 key did not match"
1844+ ssh->kex->client_version_string, 1848+ "expected length (expected 65, got %zu)", sshbuf_len(server_blob));
1845+ ssh->kex->server_version_string, 1849+
1846+ sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), 1850+ if (sshbuf_ptr(server_blob)[0] != POINT_CONVERSION_UNCOMPRESSED)
1847+ sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), 1851+ fatal("The received NIST-P256 key does not have first octet 0x04");
1848+ (serverhostkey ? serverhostkey : empty), slen, 1852+
1849+ min, nbits, max, 1853+ r = kex_ecdh_dec(kex, server_blob, &shared_secret);
1850+ dh_p, dh_g,
1851+ pub_key,
1852+ dh_server_pub,
1853+ shared_secret,
1854+ hash, &hashlen
1855+ );
1856+ break; 1854+ break;
1857+ default: 1855+ default:
1858+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); 1856+ r = SSH_ERR_INVALID_ARGUMENT;
1857+ break;
1858+ }
1859+ if (r != 0)
1860+ goto out;
1861+
1862+ if ((empty = sshbuf_new()) == NULL) {
1863+ r = SSH_ERR_ALLOC_FAIL;
1864+ goto out;
1859+ } 1865+ }
1860+ 1866+
1867+ hashlen = sizeof(hash);
1868+ if ((r = kex_gen_hash(
1869+ kex->hash_alg,
1870+ kex->client_version,
1871+ kex->server_version,
1872+ kex->my,
1873+ kex->peer,
1874+ (server_host_key_blob ? server_host_key_blob : empty),
1875+ kex->client_pub,
1876+ server_blob,
1877+ shared_secret,
1878+ hash, &hashlen)) != 0)
1879+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
1880+
1861+ gssbuf.value = hash; 1881+ gssbuf.value = hash;
1862+ gssbuf.length = hashlen; 1882+ gssbuf.length = hashlen;
1863+ 1883+
1864+ /* Verify that the hash matches the MIC we just got. */ 1884+ /* Verify that the hash matches the MIC we just got. */
1865+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok))) 1885+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
1866+ packet_disconnect("Hash's MIC didn't verify"); 1886+ sshpkt_disconnect(ssh, "Hash's MIC didn't verify");
1867+ 1887+
1868+ free(msg_tok.value); 1888+ gss_release_buffer(&min_status, &msg_tok);
1869+ 1889+
1870+ DH_free(dh); 1890+ if (kex->gss_deleg_creds)
1871+ free(serverhostkey); 1891+ ssh_gssapi_credentials_updated(ctxt);
1872+ BN_clear_free(dh_server_pub); 1892+
1893+ if (gss_kex_context == NULL)
1894+ gss_kex_context = ctxt;
1895+ else
1896+ ssh_gssapi_delete_ctx(&ctxt);
1897+
1898+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
1899+ r = kex_send_newkeys(ssh);
1900+
1901+out:
1902+ explicit_bzero(hash, sizeof(hash));
1903+ explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
1904+ sshbuf_free(empty);
1905+ sshbuf_free(server_host_key_blob);
1906+ sshbuf_free(server_blob);
1907+ sshbuf_free(shared_secret);
1908+ sshbuf_free(kex->client_pub);
1909+ kex->client_pub = NULL;
1910+ return r;
1911+}
1912+
1913+int
1914+kexgssgex_client(struct ssh *ssh)
1915+{
1916+ struct kex *kex = ssh->kex;
1917+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER,
1918+ recv_tok = GSS_C_EMPTY_BUFFER, gssbuf,
1919+ msg_tok = GSS_C_EMPTY_BUFFER, *token_ptr;
1920+ Gssctxt *ctxt;
1921+ OM_uint32 maj_status, min_status, ret_flags;
1922+ struct sshbuf *shared_secret = NULL;
1923+ BIGNUM *p = NULL;
1924+ BIGNUM *g = NULL;
1925+ struct sshbuf *buf = NULL;
1926+ struct sshbuf *server_host_key_blob = NULL;
1927+ struct sshbuf *server_blob = NULL;
1928+ BIGNUM *dh_server_pub = NULL;
1929+ u_char *msg;
1930+ int type = 0;
1931+ int first = 1;
1932+ u_char hash[SSH_DIGEST_MAX_LENGTH];
1933+ size_t hashlen;
1934+ const BIGNUM *pub_key, *dh_p, *dh_g;
1935+ int nbits = 0, min = DH_GRP_MIN, max = DH_GRP_MAX;
1936+ struct sshbuf *empty = NULL;
1937+ u_char c;
1938+ int r;
1939+
1940+ /* Initialise our GSSAPI world */
1941+ ssh_gssapi_build_ctx(&ctxt);
1942+ if (ssh_gssapi_id_kex(ctxt, kex->name, kex->kex_type)
1943+ == GSS_C_NO_OID)
1944+ fatal("Couldn't identify host exchange");
1945+
1946+ if (ssh_gssapi_import_name(ctxt, kex->gss_host))
1947+ fatal("Couldn't import hostname");
1948+
1949+ if (kex->gss_client &&
1950+ ssh_gssapi_client_identity(ctxt, kex->gss_client))
1951+ fatal("Couldn't acquire client credentials");
1952+
1953+ debug("Doing group exchange");
1954+ nbits = dh_estimate(kex->dh_need * 8);
1955+
1956+ kex->min = DH_GRP_MIN;
1957+ kex->max = DH_GRP_MAX;
1958+ kex->nbits = nbits;
1959+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUPREQ)) != 0 ||
1960+ (r = sshpkt_put_u32(ssh, min)) != 0 ||
1961+ (r = sshpkt_put_u32(ssh, nbits)) != 0 ||
1962+ (r = sshpkt_put_u32(ssh, max)) != 0 ||
1963+ (r = sshpkt_send(ssh)) != 0)
1964+ fatal("Failed to construct a packet: %s", ssh_err(r));
1965+
1966+ if ((r = ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0)
1967+ fatal("Error: %s", ssh_err(r));
1968+
1969+ if ((r = sshpkt_get_bignum2(ssh, &p)) != 0 ||
1970+ (r = sshpkt_get_bignum2(ssh, &g)) != 0 ||
1971+ (r = sshpkt_get_end(ssh)) != 0)
1972+ fatal("shpkt_get_bignum2 failed: %s", ssh_err(r));
1973+
1974+ if (BN_num_bits(p) < min || BN_num_bits(p) > max)
1975+ fatal("GSSGRP_GEX group out of range: %d !< %d !< %d",
1976+ min, BN_num_bits(p), max);
1977+
1978+ if ((kex->dh = dh_new_group(g, p)) == NULL)
1979+ fatal("dn_new_group() failed");
1980+ p = g = NULL; /* belong to kex->dh now */
1981+
1982+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
1983+ goto out;
1984+ DH_get0_key(kex->dh, &pub_key, NULL);
1985+
1986+ token_ptr = GSS_C_NO_BUFFER;
1987+
1988+ do {
1989+ /* Step 2 - call GSS_Init_sec_context() */
1990+ debug("Calling gss_init_sec_context");
1991+
1992+ maj_status = ssh_gssapi_init_ctx(ctxt,
1993+ kex->gss_deleg_creds, token_ptr, &send_tok,
1994+ &ret_flags);
1995+
1996+ if (GSS_ERROR(maj_status)) {
1997+ /* XXX Useles code: Missing send? */
1998+ if (send_tok.length != 0) {
1999+ if ((r = sshpkt_start(ssh,
2000+ SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
2001+ (r = sshpkt_put_string(ssh, send_tok.value,
2002+ send_tok.length)) != 0)
2003+ fatal("sshpkt failed: %s", ssh_err(r));
2004+ }
2005+ fatal("gss_init_context failed");
2006+ }
2007+
2008+ /* If we've got an old receive buffer get rid of it */
2009+ if (token_ptr != GSS_C_NO_BUFFER)
2010+ gss_release_buffer(&min_status, &recv_tok);
2011+
2012+ if (maj_status == GSS_S_COMPLETE) {
2013+ /* If mutual state flag is not true, kex fails */
2014+ if (!(ret_flags & GSS_C_MUTUAL_FLAG))
2015+ fatal("Mutual authentication failed");
2016+
2017+ /* If integ avail flag is not true kex fails */
2018+ if (!(ret_flags & GSS_C_INTEG_FLAG))
2019+ fatal("Integrity check failed");
2020+ }
2021+
2022+ /*
2023+ * If we have data to send, then the last message that we
2024+ * received cannot have been a 'complete'.
2025+ */
2026+ if (send_tok.length != 0) {
2027+ if (first) {
2028+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_INIT)) != 0 ||
2029+ (r = sshpkt_put_string(ssh, send_tok.value,
2030+ send_tok.length)) != 0 ||
2031+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0)
2032+ fatal("sshpkt failed: %s", ssh_err(r));
2033+ first = 0;
2034+ } else {
2035+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
2036+ (r = sshpkt_put_string(ssh,send_tok.value,
2037+ send_tok.length)) != 0)
2038+ fatal("sshpkt failed: %s", ssh_err(r));
2039+ }
2040+ if ((r = sshpkt_send(ssh)) != 0)
2041+ fatal("sshpkt_send failed: %s", ssh_err(r));
2042+ gss_release_buffer(&min_status, &send_tok);
2043+
2044+ /* If we've sent them data, they should reply */
2045+ do {
2046+ type = ssh_packet_read(ssh);
2047+ if (type == SSH2_MSG_KEXGSS_HOSTKEY) {
2048+ debug("Received KEXGSS_HOSTKEY");
2049+ if (server_host_key_blob)
2050+ fatal("Server host key received more than once");
2051+ if ((r = sshpkt_getb_froms(ssh, &server_host_key_blob)) != 0)
2052+ fatal("sshpkt failed: %s", ssh_err(r));
2053+ }
2054+ } while (type == SSH2_MSG_KEXGSS_HOSTKEY);
2055+
2056+ switch (type) {
2057+ case SSH2_MSG_KEXGSS_CONTINUE:
2058+ debug("Received GSSAPI_CONTINUE");
2059+ if (maj_status == GSS_S_COMPLETE)
2060+ fatal("GSSAPI Continue received from server when complete");
2061+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
2062+ &recv_tok)) != 0 ||
2063+ (r = sshpkt_get_end(ssh)) != 0)
2064+ fatal("sshpkt failed: %s", ssh_err(r));
2065+ break;
2066+ case SSH2_MSG_KEXGSS_COMPLETE:
2067+ debug("Received GSSAPI_COMPLETE");
2068+ if (msg_tok.value != NULL)
2069+ fatal("Received GSSAPI_COMPLETE twice?");
2070+ if ((r = sshpkt_getb_froms(ssh, &server_blob)) != 0 ||
2071+ (r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
2072+ &msg_tok)) != 0)
2073+ fatal("sshpkt failed: %s", ssh_err(r));
2074+
2075+ /* Is there a token included? */
2076+ if ((r = sshpkt_get_u8(ssh, &c)) != 0)
2077+ fatal("sshpkt failed: %s", ssh_err(r));
2078+ if (c) {
2079+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(
2080+ ssh, &recv_tok)) != 0 ||
2081+ (r = sshpkt_get_end(ssh)) != 0)
2082+ fatal("sshpkt failed: %s", ssh_err(r));
2083+ /* If we're already complete - protocol error */
2084+ if (maj_status == GSS_S_COMPLETE)
2085+ sshpkt_disconnect(ssh, "Protocol error: received token when complete");
2086+ } else {
2087+ /* No token included */
2088+ if (maj_status != GSS_S_COMPLETE)
2089+ sshpkt_disconnect(ssh, "Protocol error: did not receive final token");
2090+ }
2091+ break;
2092+ case SSH2_MSG_KEXGSS_ERROR:
2093+ debug("Received Error");
2094+ if ((r = sshpkt_get_u32(ssh, &maj_status)) != 0 ||
2095+ (r = sshpkt_get_u32(ssh, &min_status)) != 0 ||
2096+ (r = sshpkt_get_string(ssh, &msg, NULL)) != 0 ||
2097+ (r = sshpkt_get_string(ssh, NULL, NULL)) != 0 || /* lang tag */
2098+ (r = sshpkt_get_end(ssh)) != 0)
2099+ fatal("sshpkt failed: %s", ssh_err(r));
2100+ fatal("GSSAPI Error: \n%.400s", msg);
2101+ default:
2102+ sshpkt_disconnect(ssh, "Protocol error: didn't expect packet type %d",
2103+ type);
2104+ }
2105+ token_ptr = &recv_tok;
2106+ } else {
2107+ /* No data, and not complete */
2108+ if (maj_status != GSS_S_COMPLETE)
2109+ fatal("Not complete, and no token output");
2110+ }
2111+ } while (maj_status & GSS_S_CONTINUE_NEEDED);
2112+
2113+ /*
2114+ * We _must_ have received a COMPLETE message in reply from the
2115+ * server, which will have set dh_server_pub and msg_tok
2116+ */
2117+
2118+ if (type != SSH2_MSG_KEXGSS_COMPLETE)
2119+ fatal("Didn't receive a SSH2_MSG_KEXGSS_COMPLETE when I expected it");
2120+
2121+ /* 7. C verifies that the key Q_S is valid */
2122+ /* 8. C computes shared secret */
2123+ if ((buf = sshbuf_new()) == NULL ||
2124+ (r = sshbuf_put_stringb(buf, server_blob)) != 0 ||
2125+ (r = sshbuf_get_bignum2(buf, &dh_server_pub)) != 0)
2126+ goto out;
2127+ sshbuf_free(buf);
2128+ buf = NULL;
2129+
2130+ if ((shared_secret = sshbuf_new()) == NULL) {
2131+ r = SSH_ERR_ALLOC_FAIL;
2132+ goto out;
2133+ }
2134+
2135+ if ((r = kex_dh_compute_key(kex, dh_server_pub, shared_secret)) != 0)
2136+ goto out;
2137+ if ((empty = sshbuf_new()) == NULL) {
2138+ r = SSH_ERR_ALLOC_FAIL;
2139+ goto out;
2140+ }
2141+
2142+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
2143+ hashlen = sizeof(hash);
2144+ if ((r = kexgex_hash(
2145+ kex->hash_alg,
2146+ kex->client_version,
2147+ kex->server_version,
2148+ kex->my,
2149+ kex->peer,
2150+ (server_host_key_blob ? server_host_key_blob : empty),
2151+ kex->min, kex->nbits, kex->max,
2152+ dh_p, dh_g,
2153+ pub_key,
2154+ dh_server_pub,
2155+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
2156+ hash, &hashlen)) != 0)
2157+ fatal("Failed to calculate hash: %s", ssh_err(r));
2158+
2159+ gssbuf.value = hash;
2160+ gssbuf.length = hashlen;
2161+
2162+ /* Verify that the hash matches the MIC we just got. */
2163+ if (GSS_ERROR(ssh_gssapi_checkmic(ctxt, &gssbuf, &msg_tok)))
2164+ sshpkt_disconnect(ssh, "Hash's MIC didn't verify");
2165+
2166+ gss_release_buffer(&min_status, &msg_tok);
1873+ 2167+
1874+ /* save session id */ 2168+ /* save session id */
1875+ if (ssh->kex->session_id == NULL) { 2169+ if (kex->session_id == NULL) {
1876+ ssh->kex->session_id_len = hashlen; 2170+ kex->session_id_len = hashlen;
1877+ ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); 2171+ kex->session_id = xmalloc(kex->session_id_len);
1878+ memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); 2172+ memcpy(kex->session_id, hash, kex->session_id_len);
1879+ } 2173+ }
1880+ 2174+
1881+ if (ssh->kex->gss_deleg_creds) 2175+ if (kex->gss_deleg_creds)
1882+ ssh_gssapi_credentials_updated(ctxt); 2176+ ssh_gssapi_credentials_updated(ctxt);
1883+ 2177+
1884+ if (gss_kex_context == NULL) 2178+ if (gss_kex_context == NULL)
@@ -1886,18 +2180,28 @@ index 000000000..3c8ae08dd
1886+ else 2180+ else
1887+ ssh_gssapi_delete_ctx(&ctxt); 2181+ ssh_gssapi_delete_ctx(&ctxt);
1888+ 2182+
1889+ kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); 2183+ /* Finally derive the keys and send them */
1890+ BN_clear_free(shared_secret); 2184+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
1891+ return kex_send_newkeys(ssh); 2185+ r = kex_send_newkeys(ssh);
2186+out:
2187+ sshbuf_free(buf);
2188+ sshbuf_free(server_blob);
2189+ sshbuf_free(empty);
2190+ explicit_bzero(hash, sizeof(hash));
2191+ DH_free(kex->dh);
2192+ kex->dh = NULL;
2193+ BN_clear_free(dh_server_pub);
2194+ sshbuf_free(shared_secret);
2195+ sshbuf_free(server_host_key_blob);
2196+ return r;
1892+} 2197+}
1893+ 2198+#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */
1894+#endif /* GSSAPI */
1895diff --git a/kexgsss.c b/kexgsss.c 2199diff --git a/kexgsss.c b/kexgsss.c
1896new file mode 100644 2200new file mode 100644
1897index 000000000..18070f1d7 2201index 000000000..60bc02deb
1898--- /dev/null 2202--- /dev/null
1899+++ b/kexgsss.c 2203+++ b/kexgsss.c
1900@@ -0,0 +1,300 @@ 2204@@ -0,0 +1,474 @@
1901+/* 2205+/*
1902+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. 2206+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
1903+ * 2207+ *
@@ -1924,7 +2228,7 @@ index 000000000..18070f1d7
1924+ 2228+
1925+#include "includes.h" 2229+#include "includes.h"
1926+ 2230+
1927+#ifdef GSSAPI 2231+#if defined(GSSAPI) && defined(WITH_OPENSSL)
1928+ 2232+
1929+#include <string.h> 2233+#include <string.h>
1930+ 2234+
@@ -1942,40 +2246,41 @@ index 000000000..18070f1d7
1942+#include "dh.h" 2246+#include "dh.h"
1943+#include "ssh-gss.h" 2247+#include "ssh-gss.h"
1944+#include "monitor_wrap.h" 2248+#include "monitor_wrap.h"
1945+#include "misc.h" 2249+#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */
1946+#include "servconf.h" 2250+#include "servconf.h"
2251+#include "ssh-gss.h"
1947+#include "digest.h" 2252+#include "digest.h"
2253+#include "ssherr.h"
1948+ 2254+
1949+extern ServerOptions options; 2255+extern ServerOptions options;
1950+ 2256+
1951+int 2257+int
1952+kexgss_server(struct ssh *ssh) 2258+kexgss_server(struct ssh *ssh)
1953+{ 2259+{
2260+ struct kex *kex = ssh->kex;
1954+ OM_uint32 maj_status, min_status; 2261+ OM_uint32 maj_status, min_status;
1955+ 2262+
1956+ /* 2263+ /*
1957+ * Some GSSAPI implementations use the input value of ret_flags (an 2264+ * Some GSSAPI implementations use the input value of ret_flags (an
1958+ * output variable) as a means of triggering mechanism specific 2265+ * output variable) as a means of triggering mechanism specific
1959+ * features. Initializing it to zero avoids inadvertently 2266+ * features. Initializing it to zero avoids inadvertently
1960+ * activating this non-standard behaviour. 2267+ * activating this non-standard behaviour.
1961+ */ 2268+ */
1962+ 2269+
1963+ OM_uint32 ret_flags = 0; 2270+ OM_uint32 ret_flags = 0;
1964+ gss_buffer_desc gssbuf, recv_tok, msg_tok; 2271+ gss_buffer_desc gssbuf, recv_tok, msg_tok;
1965+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER; 2272+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
1966+ Gssctxt *ctxt = NULL; 2273+ Gssctxt *ctxt = NULL;
1967+ u_int slen, klen, kout; 2274+ struct sshbuf *shared_secret = NULL;
1968+ u_char *kbuf; 2275+ struct sshbuf *client_pubkey = NULL;
1969+ DH *dh; 2276+ struct sshbuf *server_pubkey = NULL;
1970+ int min = -1, max = -1, nbits = -1; 2277+ struct sshbuf *empty = sshbuf_new();
1971+ const BIGNUM *pub_key, *dh_p, *dh_g;
1972+ BIGNUM *shared_secret = NULL;
1973+ BIGNUM *dh_client_pub = NULL;
1974+ int type = 0; 2278+ int type = 0;
1975+ gss_OID oid; 2279+ gss_OID oid;
1976+ char *mechs; 2280+ char *mechs;
1977+ u_char hash[SSH_DIGEST_MAX_LENGTH]; 2281+ u_char hash[SSH_DIGEST_MAX_LENGTH];
1978+ size_t hashlen; 2282+ size_t hashlen;
2283+ int r;
1979+ 2284+
1980+ /* Initialise GSSAPI */ 2285+ /* Initialise GSSAPI */
1981+ 2286+
@@ -1988,8 +2293,8 @@ index 000000000..18070f1d7
1988+ free(mechs); 2293+ free(mechs);
1989+ } 2294+ }
1990+ 2295+
1991+ debug2("%s: Identifying %s", __func__, ssh->kex->name); 2296+ debug2("%s: Identifying %s", __func__, kex->name);
1992+ oid = ssh_gssapi_id_kex(NULL, ssh->kex->name, ssh->kex->kex_type); 2297+ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
1993+ if (oid == GSS_C_NO_OID) 2298+ if (oid == GSS_C_NO_OID)
1994+ fatal("Unknown gssapi mechanism"); 2299+ fatal("Unknown gssapi mechanism");
1995+ 2300+
@@ -1998,94 +2303,82 @@ index 000000000..18070f1d7
1998+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid)))) 2303+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
1999+ fatal("Unable to acquire credentials for the server"); 2304+ fatal("Unable to acquire credentials for the server");
2000+ 2305+
2001+ switch (ssh->kex->kex_type) {
2002+ case KEX_GSS_GRP1_SHA1:
2003+ dh = dh_new_group1();
2004+ break;
2005+ case KEX_GSS_GRP14_SHA1:
2006+ dh = dh_new_group14();
2007+ break;
2008+ case KEX_GSS_GEX_SHA1:
2009+ debug("Doing group exchange");
2010+ packet_read_expect(SSH2_MSG_KEXGSS_GROUPREQ);
2011+ min = packet_get_int();
2012+ nbits = packet_get_int();
2013+ max = packet_get_int();
2014+ packet_check_eom();
2015+ if (max < min || nbits < min || max < nbits)
2016+ fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
2017+ min, nbits, max);
2018+ dh = PRIVSEP(choose_dh(MAX(DH_GRP_MIN, min),
2019+ nbits, MIN(DH_GRP_MAX, max)));
2020+ if (dh == NULL)
2021+ packet_disconnect("Protocol error: no matching group found");
2022+ DH_get0_pqg(dh, &dh_p, NULL, &dh_g);
2023+
2024+ packet_start(SSH2_MSG_KEXGSS_GROUP);
2025+ packet_put_bignum2(dh_p);
2026+ packet_put_bignum2(dh_g);
2027+ packet_send();
2028+
2029+ packet_write_wait();
2030+ break;
2031+ default:
2032+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type);
2033+ }
2034+
2035+ dh_gen_key(dh, ssh->kex->we_need * 8);
2036+
2037+ do { 2306+ do {
2038+ debug("Wait SSH2_MSG_GSSAPI_INIT"); 2307+ debug("Wait SSH2_MSG_KEXGSS_INIT");
2039+ type = packet_read(); 2308+ type = ssh_packet_read(ssh);
2040+ switch(type) { 2309+ switch(type) {
2041+ case SSH2_MSG_KEXGSS_INIT: 2310+ case SSH2_MSG_KEXGSS_INIT:
2042+ if (dh_client_pub != NULL) 2311+ if (client_pubkey != NULL)
2043+ fatal("Received KEXGSS_INIT after initialising"); 2312+ fatal("Received KEXGSS_INIT after initialising");
2044+ recv_tok.value = packet_get_string(&slen); 2313+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
2045+ recv_tok.length = slen; 2314+ &recv_tok)) != 0 ||
2046+ 2315+ (r = sshpkt_getb_froms(ssh, &client_pubkey)) != 0 ||
2047+ if ((dh_client_pub = BN_new()) == NULL) 2316+ (r = sshpkt_get_end(ssh)) != 0)
2048+ fatal("dh_client_pub == NULL"); 2317+ fatal("sshpkt failed: %s", ssh_err(r));
2049+ 2318+
2050+ packet_get_bignum2(dh_client_pub); 2319+ switch (kex->kex_type) {
2320+ case KEX_GSS_GRP1_SHA1:
2321+ case KEX_GSS_GRP14_SHA1:
2322+ case KEX_GSS_GRP14_SHA256:
2323+ case KEX_GSS_GRP16_SHA512:
2324+ r = kex_dh_enc(kex, client_pubkey, &server_pubkey,
2325+ &shared_secret);
2326+ break;
2327+ case KEX_GSS_NISTP256_SHA256:
2328+ r = kex_ecdh_enc(kex, client_pubkey, &server_pubkey,
2329+ &shared_secret);
2330+ break;
2331+ case KEX_GSS_C25519_SHA256:
2332+ r = kex_c25519_enc(kex, client_pubkey, &server_pubkey,
2333+ &shared_secret);
2334+ break;
2335+ default:
2336+ fatal("%s: Unexpected KEX type %d", __func__, kex->kex_type);
2337+ }
2338+ if (r != 0)
2339+ goto out;
2051+ 2340+
2052+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */ 2341+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
2053+ break; 2342+ break;
2054+ case SSH2_MSG_KEXGSS_CONTINUE: 2343+ case SSH2_MSG_KEXGSS_CONTINUE:
2055+ recv_tok.value = packet_get_string(&slen); 2344+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
2056+ recv_tok.length = slen; 2345+ &recv_tok)) != 0 ||
2346+ (r = sshpkt_get_end(ssh)) != 0)
2347+ fatal("sshpkt failed: %s", ssh_err(r));
2057+ break; 2348+ break;
2058+ default: 2349+ default:
2059+ packet_disconnect( 2350+ sshpkt_disconnect(ssh,
2060+ "Protocol error: didn't expect packet type %d", 2351+ "Protocol error: didn't expect packet type %d",
2061+ type); 2352+ type);
2062+ } 2353+ }
2063+ 2354+
2064+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok, 2355+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok,
2065+ &send_tok, &ret_flags)); 2356+ &send_tok, &ret_flags));
2066+ 2357+
2067+ free(recv_tok.value); 2358+ gss_release_buffer(&min_status, &recv_tok);
2068+ 2359+
2069+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0) 2360+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
2070+ fatal("Zero length token output when incomplete"); 2361+ fatal("Zero length token output when incomplete");
2071+ 2362+
2072+ if (dh_client_pub == NULL) 2363+ if (client_pubkey == NULL)
2073+ fatal("No client public key"); 2364+ fatal("No client public key");
2074+ 2365+
2075+ if (maj_status & GSS_S_CONTINUE_NEEDED) { 2366+ if (maj_status & GSS_S_CONTINUE_NEEDED) {
2076+ debug("Sending GSSAPI_CONTINUE"); 2367+ debug("Sending GSSAPI_CONTINUE");
2077+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); 2368+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
2078+ packet_put_string(send_tok.value, send_tok.length); 2369+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 ||
2079+ packet_send(); 2370+ (r = sshpkt_send(ssh)) != 0)
2371+ fatal("sshpkt failed: %s", ssh_err(r));
2080+ gss_release_buffer(&min_status, &send_tok); 2372+ gss_release_buffer(&min_status, &send_tok);
2081+ } 2373+ }
2082+ } while (maj_status & GSS_S_CONTINUE_NEEDED); 2374+ } while (maj_status & GSS_S_CONTINUE_NEEDED);
2083+ 2375+
2084+ if (GSS_ERROR(maj_status)) { 2376+ if (GSS_ERROR(maj_status)) {
2085+ if (send_tok.length > 0) { 2377+ if (send_tok.length > 0) {
2086+ packet_start(SSH2_MSG_KEXGSS_CONTINUE); 2378+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
2087+ packet_put_string(send_tok.value, send_tok.length); 2379+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 ||
2088+ packet_send(); 2380+ (r = sshpkt_send(ssh)) != 0)
2381+ fatal("sshpkt failed: %s", ssh_err(r));
2089+ } 2382+ }
2090+ fatal("accept_ctx died"); 2383+ fatal("accept_ctx died");
2091+ } 2384+ }
@@ -2095,123 +2388,320 @@ index 000000000..18070f1d7
2095+ 2388+
2096+ if (!(ret_flags & GSS_C_INTEG_FLAG)) 2389+ if (!(ret_flags & GSS_C_INTEG_FLAG))
2097+ fatal("Integrity flag wasn't set"); 2390+ fatal("Integrity flag wasn't set");
2098+
2099+ if (!dh_pub_is_valid(dh, dh_client_pub))
2100+ packet_disconnect("bad client public DH value");
2101+ 2391+
2102+ klen = DH_size(dh); 2392+ hashlen = sizeof(hash);
2103+ kbuf = xmalloc(klen); 2393+ if ((r = kex_gen_hash(
2104+ kout = DH_compute_key(kbuf, dh_client_pub, dh); 2394+ kex->hash_alg,
2105+ if (kout < 0) 2395+ kex->client_version,
2106+ fatal("DH_compute_key: failed"); 2396+ kex->server_version,
2397+ kex->peer,
2398+ kex->my,
2399+ empty,
2400+ client_pubkey,
2401+ server_pubkey,
2402+ shared_secret,
2403+ hash, &hashlen)) != 0)
2404+ goto out;
2107+ 2405+
2108+ shared_secret = BN_new(); 2406+ gssbuf.value = hash;
2109+ if (shared_secret == NULL) 2407+ gssbuf.length = hashlen;
2110+ fatal("kexgss_server: BN_new failed");
2111+ 2408+
2112+ if (BN_bin2bn(kbuf, kout, shared_secret) == NULL) 2409+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))))
2113+ fatal("kexgss_server: BN_bin2bn failed"); 2410+ fatal("Couldn't get MIC");
2114+ 2411+
2115+ memset(kbuf, 0, klen); 2412+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 ||
2116+ free(kbuf); 2413+ (r = sshpkt_put_stringb(ssh, server_pubkey)) != 0 ||
2414+ (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0)
2415+ fatal("sshpkt failed: %s", ssh_err(r));
2117+ 2416+
2118+ DH_get0_key(dh, &pub_key, NULL); 2417+ if (send_tok.length != 0) {
2119+ DH_get0_pqg(dh, &dh_p, NULL, &dh_g); 2418+ if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */
2419+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0)
2420+ fatal("sshpkt failed: %s", ssh_err(r));
2421+ } else {
2422+ if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */
2423+ fatal("sshpkt failed: %s", ssh_err(r));
2424+ }
2425+ if ((r = sshpkt_send(ssh)) != 0)
2426+ fatal("sshpkt_send failed: %s", ssh_err(r));
2120+ 2427+
2121+ hashlen = sizeof(hash); 2428+ gss_release_buffer(&min_status, &send_tok);
2122+ switch (ssh->kex->kex_type) { 2429+ gss_release_buffer(&min_status, &msg_tok);
2123+ case KEX_GSS_GRP1_SHA1: 2430+
2124+ case KEX_GSS_GRP14_SHA1: 2431+ if (gss_kex_context == NULL)
2125+ kex_dh_hash( 2432+ gss_kex_context = ctxt;
2126+ ssh->kex->hash_alg, 2433+ else
2127+ ssh->kex->client_version_string, ssh->kex->server_version_string, 2434+ ssh_gssapi_delete_ctx(&ctxt);
2128+ sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), 2435+
2129+ sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), 2436+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
2130+ NULL, 0, /* Change this if we start sending host keys */ 2437+ r = kex_send_newkeys(ssh);
2131+ dh_client_pub, pub_key, shared_secret, 2438+
2132+ hash, &hashlen 2439+ /* If this was a rekey, then save out any delegated credentials we
2133+ ); 2440+ * just exchanged. */
2134+ break; 2441+ if (options.gss_store_rekey)
2135+ case KEX_GSS_GEX_SHA1: 2442+ ssh_gssapi_rekey_creds();
2136+ kexgex_hash( 2443+out:
2137+ ssh->kex->hash_alg, 2444+ sshbuf_free(empty);
2138+ ssh->kex->client_version_string, ssh->kex->server_version_string, 2445+ explicit_bzero(hash, sizeof(hash));
2139+ sshbuf_ptr(ssh->kex->peer), sshbuf_len(ssh->kex->peer), 2446+ sshbuf_free(shared_secret);
2140+ sshbuf_ptr(ssh->kex->my), sshbuf_len(ssh->kex->my), 2447+ sshbuf_free(client_pubkey);
2141+ NULL, 0, 2448+ sshbuf_free(server_pubkey);
2142+ min, nbits, max, 2449+ return r;
2143+ dh_p, dh_g, 2450+}
2144+ dh_client_pub, 2451+
2145+ pub_key, 2452+int
2146+ shared_secret, 2453+kexgssgex_server(struct ssh *ssh)
2147+ hash, &hashlen 2454+{
2148+ ); 2455+ struct kex *kex = ssh->kex;
2149+ break; 2456+ OM_uint32 maj_status, min_status;
2150+ default: 2457+
2151+ fatal("%s: Unexpected KEX type %d", __func__, ssh->kex->kex_type); 2458+ /*
2459+ * Some GSSAPI implementations use the input value of ret_flags (an
2460+ * output variable) as a means of triggering mechanism specific
2461+ * features. Initializing it to zero avoids inadvertently
2462+ * activating this non-standard behaviour.
2463+ */
2464+
2465+ OM_uint32 ret_flags = 0;
2466+ gss_buffer_desc gssbuf, recv_tok, msg_tok;
2467+ gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
2468+ Gssctxt *ctxt = NULL;
2469+ struct sshbuf *shared_secret = NULL;
2470+ int type = 0;
2471+ gss_OID oid;
2472+ char *mechs;
2473+ u_char hash[SSH_DIGEST_MAX_LENGTH];
2474+ size_t hashlen;
2475+ BIGNUM *dh_client_pub = NULL;
2476+ const BIGNUM *pub_key, *dh_p, *dh_g;
2477+ int min = -1, max = -1, nbits = -1;
2478+ int cmin = -1, cmax = -1; /* client proposal */
2479+ struct sshbuf *empty = sshbuf_new();
2480+ int r;
2481+
2482+ /* Initialise GSSAPI */
2483+
2484+ /* If we're rekeying, privsep means that some of the private structures
2485+ * in the GSSAPI code are no longer available. This kludges them back
2486+ * into life
2487+ */
2488+ if (!ssh_gssapi_oid_table_ok())
2489+ if ((mechs = ssh_gssapi_server_mechanisms()))
2490+ free(mechs);
2491+
2492+ debug2("%s: Identifying %s", __func__, kex->name);
2493+ oid = ssh_gssapi_id_kex(NULL, kex->name, kex->kex_type);
2494+ if (oid == GSS_C_NO_OID)
2495+ fatal("Unknown gssapi mechanism");
2496+
2497+ debug2("%s: Acquiring credentials", __func__);
2498+
2499+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_server_ctx(&ctxt, oid))))
2500+ fatal("Unable to acquire credentials for the server");
2501+
2502+ /* 5. S generates an ephemeral key pair (do the allocations early) */
2503+ debug("Doing group exchange");
2504+ ssh_packet_read_expect(ssh, SSH2_MSG_KEXGSS_GROUPREQ);
2505+ /* store client proposal to provide valid signature */
2506+ if ((r = sshpkt_get_u32(ssh, &cmin)) != 0 ||
2507+ (r = sshpkt_get_u32(ssh, &nbits)) != 0 ||
2508+ (r = sshpkt_get_u32(ssh, &cmax)) != 0 ||
2509+ (r = sshpkt_get_end(ssh)) != 0)
2510+ fatal("sshpkt failed: %s", ssh_err(r));
2511+ kex->nbits = nbits;
2512+ kex->min = cmin;
2513+ kex->max = cmax;
2514+ min = MAX(DH_GRP_MIN, cmin);
2515+ max = MIN(DH_GRP_MAX, cmax);
2516+ nbits = MAXIMUM(DH_GRP_MIN, nbits);
2517+ nbits = MINIMUM(DH_GRP_MAX, nbits);
2518+ if (max < min || nbits < min || max < nbits)
2519+ fatal("GSS_GEX, bad parameters: %d !< %d !< %d",
2520+ min, nbits, max);
2521+ kex->dh = PRIVSEP(choose_dh(min, nbits, max));
2522+ if (kex->dh == NULL) {
2523+ sshpkt_disconnect(ssh, "Protocol error: no matching group found");
2524+ fatal("Protocol error: no matching group found");
2152+ } 2525+ }
2153+ 2526+
2154+ BN_clear_free(dh_client_pub); 2527+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
2528+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_GROUP)) != 0 ||
2529+ (r = sshpkt_put_bignum2(ssh, dh_p)) != 0 ||
2530+ (r = sshpkt_put_bignum2(ssh, dh_g)) != 0 ||
2531+ (r = sshpkt_send(ssh)) != 0)
2532+ fatal("sshpkt failed: %s", ssh_err(r));
2533+
2534+ if ((r = ssh_packet_write_wait(ssh)) != 0)
2535+ fatal("ssh_packet_write_wait: %s", ssh_err(r));
2536+
2537+ /* Compute our exchange value in parallel with the client */
2538+ if ((r = dh_gen_key(kex->dh, kex->we_need * 8)) != 0)
2539+ goto out;
2540+
2541+ do {
2542+ debug("Wait SSH2_MSG_GSSAPI_INIT");
2543+ type = ssh_packet_read(ssh);
2544+ switch(type) {
2545+ case SSH2_MSG_KEXGSS_INIT:
2546+ if (dh_client_pub != NULL)
2547+ fatal("Received KEXGSS_INIT after initialising");
2548+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
2549+ &recv_tok)) != 0 ||
2550+ (r = sshpkt_get_bignum2(ssh, &dh_client_pub)) != 0 ||
2551+ (r = sshpkt_get_end(ssh)) != 0)
2552+ fatal("sshpkt failed: %s", ssh_err(r));
2553+
2554+ /* Send SSH_MSG_KEXGSS_HOSTKEY here, if we want */
2555+ break;
2556+ case SSH2_MSG_KEXGSS_CONTINUE:
2557+ if ((r = ssh_gssapi_sshpkt_get_buffer_desc(ssh,
2558+ &recv_tok)) != 0 ||
2559+ (r = sshpkt_get_end(ssh)) != 0)
2560+ fatal("sshpkt failed: %s", ssh_err(r));
2561+ break;
2562+ default:
2563+ sshpkt_disconnect(ssh,
2564+ "Protocol error: didn't expect packet type %d",
2565+ type);
2566+ }
2567+
2568+ maj_status = PRIVSEP(ssh_gssapi_accept_ctx(ctxt, &recv_tok,
2569+ &send_tok, &ret_flags));
2570+
2571+ gss_release_buffer(&min_status, &recv_tok);
2572+
2573+ if (maj_status != GSS_S_COMPLETE && send_tok.length == 0)
2574+ fatal("Zero length token output when incomplete");
2575+
2576+ if (dh_client_pub == NULL)
2577+ fatal("No client public key");
2578+
2579+ if (maj_status & GSS_S_CONTINUE_NEEDED) {
2580+ debug("Sending GSSAPI_CONTINUE");
2581+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
2582+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 ||
2583+ (r = sshpkt_send(ssh)) != 0)
2584+ fatal("sshpkt failed: %s", ssh_err(r));
2585+ gss_release_buffer(&min_status, &send_tok);
2586+ }
2587+ } while (maj_status & GSS_S_CONTINUE_NEEDED);
2588+
2589+ if (GSS_ERROR(maj_status)) {
2590+ if (send_tok.length > 0) {
2591+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_CONTINUE)) != 0 ||
2592+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0 ||
2593+ (r = sshpkt_send(ssh)) != 0)
2594+ fatal("sshpkt failed: %s", ssh_err(r));
2595+ }
2596+ fatal("accept_ctx died");
2597+ }
2155+ 2598+
2156+ if (ssh->kex->session_id == NULL) { 2599+ if (!(ret_flags & GSS_C_MUTUAL_FLAG))
2157+ ssh->kex->session_id_len = hashlen; 2600+ fatal("Mutual Authentication flag wasn't set");
2158+ ssh->kex->session_id = xmalloc(ssh->kex->session_id_len); 2601+
2159+ memcpy(ssh->kex->session_id, hash, ssh->kex->session_id_len); 2602+ if (!(ret_flags & GSS_C_INTEG_FLAG))
2603+ fatal("Integrity flag wasn't set");
2604+
2605+ /* calculate shared secret */
2606+ if ((shared_secret = sshbuf_new()) == NULL) {
2607+ r = SSH_ERR_ALLOC_FAIL;
2608+ goto out;
2160+ } 2609+ }
2610+ if ((r = kex_dh_compute_key(kex, dh_client_pub, shared_secret)) != 0)
2611+ goto out;
2612+
2613+ DH_get0_key(kex->dh, &pub_key, NULL);
2614+ DH_get0_pqg(kex->dh, &dh_p, NULL, &dh_g);
2615+ hashlen = sizeof(hash);
2616+ if ((r = kexgex_hash(
2617+ kex->hash_alg,
2618+ kex->client_version,
2619+ kex->server_version,
2620+ kex->peer,
2621+ kex->my,
2622+ empty,
2623+ cmin, nbits, cmax,
2624+ dh_p, dh_g,
2625+ dh_client_pub,
2626+ pub_key,
2627+ sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
2628+ hash, &hashlen)) != 0)
2629+ fatal("kexgex_hash failed: %s", ssh_err(r));
2161+ 2630+
2162+ gssbuf.value = hash; 2631+ gssbuf.value = hash;
2163+ gssbuf.length = hashlen; 2632+ gssbuf.length = hashlen;
2164+ 2633+
2165+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt,&gssbuf,&msg_tok)))) 2634+ if (GSS_ERROR(PRIVSEP(ssh_gssapi_sign(ctxt, &gssbuf, &msg_tok))))
2166+ fatal("Couldn't get MIC"); 2635+ fatal("Couldn't get MIC");
2167+ 2636+
2168+ packet_start(SSH2_MSG_KEXGSS_COMPLETE); 2637+ if ((r = sshpkt_start(ssh, SSH2_MSG_KEXGSS_COMPLETE)) != 0 ||
2169+ packet_put_bignum2(pub_key); 2638+ (r = sshpkt_put_bignum2(ssh, pub_key)) != 0 ||
2170+ packet_put_string(msg_tok.value,msg_tok.length); 2639+ (r = sshpkt_put_string(ssh, msg_tok.value, msg_tok.length)) != 0)
2640+ fatal("sshpkt failed: %s", ssh_err(r));
2171+ 2641+
2172+ if (send_tok.length != 0) { 2642+ if (send_tok.length != 0) {
2173+ packet_put_char(1); /* true */ 2643+ if ((r = sshpkt_put_u8(ssh, 1)) != 0 || /* true */
2174+ packet_put_string(send_tok.value, send_tok.length); 2644+ (r = sshpkt_put_string(ssh, send_tok.value, send_tok.length)) != 0)
2645+ fatal("sshpkt failed: %s", ssh_err(r));
2175+ } else { 2646+ } else {
2176+ packet_put_char(0); /* false */ 2647+ if ((r = sshpkt_put_u8(ssh, 0)) != 0) /* false */
2648+ fatal("sshpkt failed: %s", ssh_err(r));
2177+ } 2649+ }
2178+ packet_send(); 2650+ if ((r = sshpkt_send(ssh)) != 0)
2651+ fatal("sshpkt failed: %s", ssh_err(r));
2179+ 2652+
2180+ gss_release_buffer(&min_status, &send_tok); 2653+ gss_release_buffer(&min_status, &send_tok);
2181+ gss_release_buffer(&min_status, &msg_tok); 2654+ gss_release_buffer(&min_status, &msg_tok);
2182+ 2655+
2183+ if (gss_kex_context == NULL) 2656+ if (gss_kex_context == NULL)
2184+ gss_kex_context = ctxt; 2657+ gss_kex_context = ctxt;
2185+ else 2658+ else
2186+ ssh_gssapi_delete_ctx(&ctxt); 2659+ ssh_gssapi_delete_ctx(&ctxt);
2187+ 2660+
2188+ DH_free(dh); 2661+ /* Finally derive the keys and send them */
2189+ 2662+ if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
2190+ kex_derive_keys_bn(ssh, hash, hashlen, shared_secret); 2663+ r = kex_send_newkeys(ssh);
2191+ BN_clear_free(shared_secret);
2192+ kex_send_newkeys(ssh);
2193+ 2664+
2194+ /* If this was a rekey, then save out any delegated credentials we 2665+ /* If this was a rekey, then save out any delegated credentials we
2195+ * just exchanged. */ 2666+ * just exchanged. */
2196+ if (options.gss_store_rekey) 2667+ if (options.gss_store_rekey)
2197+ ssh_gssapi_rekey_creds(); 2668+ ssh_gssapi_rekey_creds();
2198+ return 0; 2669+out:
2670+ sshbuf_free(empty);
2671+ explicit_bzero(hash, sizeof(hash));
2672+ DH_free(kex->dh);
2673+ kex->dh = NULL;
2674+ BN_clear_free(dh_client_pub);
2675+ sshbuf_free(shared_secret);
2676+ return r;
2199+} 2677+}
2200+#endif /* GSSAPI */ 2678+#endif /* defined(GSSAPI) && defined(WITH_OPENSSL) */
2679diff --git a/mac.c b/mac.c
2680index 51dc11d76..3d11eba62 100644
2681--- a/mac.c
2682+++ b/mac.c
2683@@ -29,6 +29,7 @@
2684
2685 #include <string.h>
2686 #include <stdio.h>
2687+#include <stdlib.h>
2688
2689 #include "digest.h"
2690 #include "hmac.h"
2201diff --git a/monitor.c b/monitor.c 2691diff --git a/monitor.c b/monitor.c
2202index 531b2993a..eabc1e89b 100644 2692index 60e529444..0766d6ef5 100644
2203--- a/monitor.c 2693--- a/monitor.c
2204+++ b/monitor.c 2694+++ b/monitor.c
2205@@ -145,6 +145,8 @@ int mm_answer_gss_setup_ctx(int, struct sshbuf *); 2695@@ -147,6 +147,8 @@ int mm_answer_gss_setup_ctx(struct ssh *, int, struct sshbuf *);
2206 int mm_answer_gss_accept_ctx(int, struct sshbuf *); 2696 int mm_answer_gss_accept_ctx(struct ssh *, int, struct sshbuf *);
2207 int mm_answer_gss_userok(int, struct sshbuf *); 2697 int mm_answer_gss_userok(struct ssh *, int, struct sshbuf *);
2208 int mm_answer_gss_checkmic(int, struct sshbuf *); 2698 int mm_answer_gss_checkmic(struct ssh *, int, struct sshbuf *);
2209+int mm_answer_gss_sign(int, struct sshbuf *); 2699+int mm_answer_gss_sign(struct ssh *, int, struct sshbuf *);
2210+int mm_answer_gss_updatecreds(int, struct sshbuf *); 2700+int mm_answer_gss_updatecreds(struct ssh *, int, struct sshbuf *);
2211 #endif 2701 #endif
2212 2702
2213 #ifdef SSH_AUDIT_EVENTS 2703 #ifdef SSH_AUDIT_EVENTS
2214@@ -215,11 +217,18 @@ struct mon_table mon_dispatch_proto20[] = { 2704@@ -219,11 +221,18 @@ struct mon_table mon_dispatch_proto20[] = {
2215 {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx}, 2705 {MONITOR_REQ_GSSSTEP, 0, mm_answer_gss_accept_ctx},
2216 {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok}, 2706 {MONITOR_REQ_GSSUSEROK, MON_ONCE|MON_AUTHDECIDE, mm_answer_gss_userok},
2217 {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic}, 2707 {MONITOR_REQ_GSSCHECKMIC, MON_ONCE, mm_answer_gss_checkmic},
@@ -2230,7 +2720,7 @@ index 531b2993a..eabc1e89b 100644
2230 #ifdef WITH_OPENSSL 2720 #ifdef WITH_OPENSSL
2231 {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 2721 {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
2232 #endif 2722 #endif
2233@@ -289,6 +298,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor) 2723@@ -292,6 +301,10 @@ monitor_child_preauth(struct ssh *ssh, struct monitor *pmonitor)
2234 /* Permit requests for moduli and signatures */ 2724 /* Permit requests for moduli and signatures */
2235 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 2725 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
2236 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 2726 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
@@ -2241,32 +2731,36 @@ index 531b2993a..eabc1e89b 100644
2241 2731
2242 /* The first few requests do not require asynchronous access */ 2732 /* The first few requests do not require asynchronous access */
2243 while (!authenticated) { 2733 while (!authenticated) {
2244@@ -401,6 +414,10 @@ monitor_child_postauth(struct monitor *pmonitor) 2734@@ -405,6 +418,10 @@ monitor_child_postauth(struct ssh *ssh, struct monitor *pmonitor)
2245 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 2735 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
2246 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 2736 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
2247 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 2737 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
2248+#ifdef GSSAPI 2738+#ifdef GSSAPI
2249+ /* and for the GSSAPI key exchange */ 2739+ /* and for the GSSAPI key exchange */
2250+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1); 2740+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSSETUP, 1);
2251+#endif 2741+#endif
2252 2742
2253 if (auth_opts->permit_pty_flag) { 2743 if (auth_opts->permit_pty_flag) {
2254 monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); 2744 monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
2255@@ -1666,6 +1683,13 @@ monitor_apply_keystate(struct monitor *pmonitor) 2745@@ -1687,6 +1704,17 @@ monitor_apply_keystate(struct ssh *ssh, struct monitor *pmonitor)
2746 # ifdef OPENSSL_HAS_ECC
2747 kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
2256 # endif 2748 # endif
2257 #endif /* WITH_OPENSSL */ 2749+# ifdef GSSAPI
2258 kex->kex[KEX_C25519_SHA256] = kexc25519_server;
2259+#ifdef GSSAPI
2260+ if (options.gss_keyex) { 2750+ if (options.gss_keyex) {
2261+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; 2751+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
2262+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; 2752+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
2263+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; 2753+ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server;
2754+ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server;
2755+ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server;
2756+ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server;
2757+ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server;
2264+ } 2758+ }
2265+#endif 2759+# endif
2266 kex->load_host_public_key=&get_hostkey_public_by_type; 2760 #endif /* WITH_OPENSSL */
2267 kex->load_host_private_key=&get_hostkey_private_by_type; 2761 kex->kex[KEX_C25519_SHA256] = kex_gen_server;
2268 kex->host_key_index=&get_hostkey_index; 2762 kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
2269@@ -1756,8 +1780,8 @@ mm_answer_gss_setup_ctx(int sock, struct sshbuf *m) 2763@@ -1780,8 +1808,8 @@ mm_answer_gss_setup_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
2270 u_char *p; 2764 u_char *p;
2271 int r; 2765 int r;
2272 2766
@@ -2277,7 +2771,7 @@ index 531b2993a..eabc1e89b 100644
2277 2771
2278 if ((r = sshbuf_get_string(m, &p, &len)) != 0) 2772 if ((r = sshbuf_get_string(m, &p, &len)) != 0)
2279 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 2773 fatal("%s: buffer error: %s", __func__, ssh_err(r));
2280@@ -1789,8 +1813,8 @@ mm_answer_gss_accept_ctx(int sock, struct sshbuf *m) 2774@@ -1813,8 +1841,8 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
2281 OM_uint32 flags = 0; /* GSI needs this */ 2775 OM_uint32 flags = 0; /* GSI needs this */
2282 int r; 2776 int r;
2283 2777
@@ -2288,7 +2782,7 @@ index 531b2993a..eabc1e89b 100644
2288 2782
2289 if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0) 2783 if ((r = ssh_gssapi_get_buffer_desc(m, &in)) != 0)
2290 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 2784 fatal("%s: buffer error: %s", __func__, ssh_err(r));
2291@@ -1810,6 +1834,7 @@ mm_answer_gss_accept_ctx(int sock, struct sshbuf *m) 2785@@ -1834,6 +1862,7 @@ mm_answer_gss_accept_ctx(struct ssh *ssh, int sock, struct sshbuf *m)
2292 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); 2786 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
2293 monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 2787 monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
2294 monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); 2788 monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
@@ -2296,7 +2790,7 @@ index 531b2993a..eabc1e89b 100644
2296 } 2790 }
2297 return (0); 2791 return (0);
2298 } 2792 }
2299@@ -1821,8 +1846,8 @@ mm_answer_gss_checkmic(int sock, struct sshbuf *m) 2793@@ -1845,8 +1874,8 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m)
2300 OM_uint32 ret; 2794 OM_uint32 ret;
2301 int r; 2795 int r;
2302 2796
@@ -2307,8 +2801,12 @@ index 531b2993a..eabc1e89b 100644
2307 2801
2308 if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 || 2802 if ((r = ssh_gssapi_get_buffer_desc(m, &gssbuf)) != 0 ||
2309 (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0) 2803 (r = ssh_gssapi_get_buffer_desc(m, &mic)) != 0)
2310@@ -1851,10 +1876,11 @@ mm_answer_gss_userok(int sock, struct sshbuf *m) 2804@@ -1872,13 +1901,17 @@ mm_answer_gss_checkmic(struct ssh *ssh, int sock, struct sshbuf *m)
2311 int r, authenticated; 2805 int
2806 mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m)
2807 {
2808- int r, authenticated;
2809+ int r, authenticated, kex;
2312 const char *displayname; 2810 const char *displayname;
2313 2811
2314- if (!options.gss_authentication) 2812- if (!options.gss_authentication)
@@ -2317,24 +2815,40 @@ index 531b2993a..eabc1e89b 100644
2317+ fatal("%s: GSSAPI not enabled", __func__); 2815+ fatal("%s: GSSAPI not enabled", __func__);
2318 2816
2319- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user); 2817- authenticated = authctxt->valid && ssh_gssapi_userok(authctxt->user);
2320+ authenticated = authctxt->valid && 2818+ if ((r = sshbuf_get_u32(m, &kex)) != 0)
2321+ ssh_gssapi_userok(authctxt->user, authctxt->pw); 2819+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
2820+
2821+ authenticated = authctxt->valid &&
2822+ ssh_gssapi_userok(authctxt->user, authctxt->pw, kex);
2322 2823
2323 sshbuf_reset(m); 2824 sshbuf_reset(m);
2324 if ((r = sshbuf_put_u32(m, authenticated)) != 0) 2825 if ((r = sshbuf_put_u32(m, authenticated)) != 0)
2325@@ -1871,5 +1897,83 @@ mm_answer_gss_userok(int sock, struct sshbuf *m) 2826@@ -1887,7 +1920,11 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m)
2827 debug3("%s: sending result %d", __func__, authenticated);
2828 mm_request_send(sock, MONITOR_ANS_GSSUSEROK, m);
2829
2830- auth_method = "gssapi-with-mic";
2831+ if (kex) {
2832+ auth_method = "gssapi-keyex";
2833+ } else {
2834+ auth_method = "gssapi-with-mic";
2835+ }
2836
2837 if ((displayname = ssh_gssapi_displayname()) != NULL)
2838 auth2_record_info(authctxt, "%s", displayname);
2839@@ -1895,5 +1932,85 @@ mm_answer_gss_userok(struct ssh *ssh, int sock, struct sshbuf *m)
2326 /* Monitor loop will terminate if authenticated */ 2840 /* Monitor loop will terminate if authenticated */
2327 return (authenticated); 2841 return (authenticated);
2328 } 2842 }
2329+ 2843+
2330+int 2844+int
2331+mm_answer_gss_sign(int socket, struct sshbuf *m) 2845+mm_answer_gss_sign(struct ssh *ssh, int socket, struct sshbuf *m)
2332+{ 2846+{
2333+ gss_buffer_desc data; 2847+ gss_buffer_desc data;
2334+ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER; 2848+ gss_buffer_desc hash = GSS_C_EMPTY_BUFFER;
2335+ OM_uint32 major, minor; 2849+ OM_uint32 major, minor;
2336+ size_t len; 2850+ size_t len;
2337+ u_char *p; 2851+ u_char *p = NULL;
2338+ int r; 2852+ int r;
2339+ 2853+
2340+ if (!options.gss_authentication && !options.gss_keyex) 2854+ if (!options.gss_authentication && !options.gss_keyex)
@@ -2344,8 +2858,9 @@ index 531b2993a..eabc1e89b 100644
2344+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); 2858+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
2345+ data.value = p; 2859+ data.value = p;
2346+ data.length = len; 2860+ data.length = len;
2347+ if (data.length != 20) 2861+ /* Lengths of SHA-1, SHA-256 and SHA-512 hashes that are used */
2348+ fatal("%s: data length incorrect: %d", __func__, 2862+ if (data.length != 20 && data.length != 32 && data.length != 64)
2863+ fatal("%s: data length incorrect: %d", __func__,
2349+ (int) data.length); 2864+ (int) data.length);
2350+ 2865+
2351+ /* Save the session ID on the first time around */ 2866+ /* Save the session ID on the first time around */
@@ -2359,6 +2874,7 @@ index 531b2993a..eabc1e89b 100644
2359+ free(data.value); 2874+ free(data.value);
2360+ 2875+
2361+ sshbuf_reset(m); 2876+ sshbuf_reset(m);
2877+
2362+ if ((r = sshbuf_put_u32(m, major)) != 0 || 2878+ if ((r = sshbuf_put_u32(m, major)) != 0 ||
2363+ (r = sshbuf_put_string(m, hash.value, hash.length)) != 0) 2879+ (r = sshbuf_put_string(m, hash.value, hash.length)) != 0)
2364+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); 2880+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
@@ -2369,7 +2885,7 @@ index 531b2993a..eabc1e89b 100644
2369+ 2885+
2370+ /* Turn on getpwnam permissions */ 2886+ /* Turn on getpwnam permissions */
2371+ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 2887+ monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
2372+ 2888+
2373+ /* And credential updating, for when rekeying */ 2889+ /* And credential updating, for when rekeying */
2374+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1); 2890+ monitor_permit(mon_dispatch, MONITOR_REQ_GSSUPCREDS, 1);
2375+ 2891+
@@ -2377,16 +2893,16 @@ index 531b2993a..eabc1e89b 100644
2377+} 2893+}
2378+ 2894+
2379+int 2895+int
2380+mm_answer_gss_updatecreds(int socket, struct sshbuf *m) { 2896+mm_answer_gss_updatecreds(struct ssh *ssh, int socket, struct sshbuf *m) {
2381+ ssh_gssapi_ccache store; 2897+ ssh_gssapi_ccache store;
2382+ int r, ok; 2898+ int r, ok;
2383+ 2899+
2384+ if (!options.gss_authentication && !options.gss_keyex) 2900+ if (!options.gss_authentication && !options.gss_keyex)
2385+ fatal("%s: GSSAPI not enabled", __func__); 2901+ fatal("%s: GSSAPI not enabled", __func__);
2386+ 2902+
2387+ if ((r = sshbuf_get_cstring(m, &store.filename, NULL)) != 0 || 2903+ if ((r = sshbuf_get_string(m, (u_char **)&store.filename, NULL)) != 0 ||
2388+ (r = sshbuf_get_cstring(m, &store.envvar, NULL)) != 0 || 2904+ (r = sshbuf_get_string(m, (u_char **)&store.envvar, NULL)) != 0 ||
2389+ (r = sshbuf_get_cstring(m, &store.envval, NULL)) != 0) 2905+ (r = sshbuf_get_string(m, (u_char **)&store.envval, NULL)) != 0)
2390+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); 2906+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
2391+ 2907+
2392+ ok = ssh_gssapi_update_creds(&store); 2908+ ok = ssh_gssapi_update_creds(&store);
@@ -2407,33 +2923,40 @@ index 531b2993a..eabc1e89b 100644
2407 #endif /* GSSAPI */ 2923 #endif /* GSSAPI */
2408 2924
2409diff --git a/monitor.h b/monitor.h 2925diff --git a/monitor.h b/monitor.h
2410index 16047299f..44fbed589 100644 2926index 683e5e071..2b1a2d590 100644
2411--- a/monitor.h 2927--- a/monitor.h
2412+++ b/monitor.h 2928+++ b/monitor.h
2413@@ -63,6 +63,9 @@ enum monitor_reqtype { 2929@@ -63,6 +63,8 @@ enum monitor_reqtype {
2414 MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111, 2930 MONITOR_REQ_PAM_FREE_CTX = 110, MONITOR_ANS_PAM_FREE_CTX = 111,
2415 MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113, 2931 MONITOR_REQ_AUDIT_EVENT = 112, MONITOR_REQ_AUDIT_COMMAND = 113,
2416 2932
2417+ MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, 2933+ MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151,
2418+ MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, 2934+ MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153,
2419+
2420 }; 2935 };
2421 2936
2422 struct monitor { 2937 struct ssh;
2423diff --git a/monitor_wrap.c b/monitor_wrap.c 2938diff --git a/monitor_wrap.c b/monitor_wrap.c
2424index 732fb3476..1865a122a 100644 2939index 186e8f022..8e4c1c1f8 100644
2425--- a/monitor_wrap.c 2940--- a/monitor_wrap.c
2426+++ b/monitor_wrap.c 2941+++ b/monitor_wrap.c
2427@@ -984,7 +984,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 2942@@ -978,13 +978,15 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
2428 } 2943 }
2429 2944
2430 int 2945 int
2431-mm_ssh_gssapi_userok(char *user) 2946-mm_ssh_gssapi_userok(char *user)
2432+mm_ssh_gssapi_userok(char *user, struct passwd *pw) 2947+mm_ssh_gssapi_userok(char *user, struct passwd *pw, int kex)
2433 { 2948 {
2434 struct sshbuf *m; 2949 struct sshbuf *m;
2435 int r, authenticated = 0; 2950 int r, authenticated = 0;
2436@@ -1003,4 +1003,55 @@ mm_ssh_gssapi_userok(char *user) 2951
2952 if ((m = sshbuf_new()) == NULL)
2953 fatal("%s: sshbuf_new failed", __func__);
2954+ if ((r = sshbuf_put_u32(m, kex)) != 0)
2955+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
2956
2957 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, m);
2958 mm_request_receive_expect(pmonitor->m_recvfd,
2959@@ -997,4 +999,57 @@ mm_ssh_gssapi_userok(char *user)
2437 debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); 2960 debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
2438 return (authenticated); 2961 return (authenticated);
2439 } 2962 }
@@ -2459,7 +2982,7 @@ index 732fb3476..1865a122a 100644
2459+ 2982+
2460+ sshbuf_free(m); 2983+ sshbuf_free(m);
2461+ 2984+
2462+ return(major); 2985+ return (major);
2463+} 2986+}
2464+ 2987+
2465+int 2988+int
@@ -2470,6 +2993,7 @@ index 732fb3476..1865a122a 100644
2470+ 2993+
2471+ if ((m = sshbuf_new()) == NULL) 2994+ if ((m = sshbuf_new()) == NULL)
2472+ fatal("%s: sshbuf_new failed", __func__); 2995+ fatal("%s: sshbuf_new failed", __func__);
2996+
2473+ if ((r = sshbuf_put_cstring(m, 2997+ if ((r = sshbuf_put_cstring(m,
2474+ store->filename ? store->filename : "")) != 0 || 2998+ store->filename ? store->filename : "")) != 0 ||
2475+ (r = sshbuf_put_cstring(m, 2999+ (r = sshbuf_put_cstring(m,
@@ -2483,6 +3007,7 @@ index 732fb3476..1865a122a 100644
2483+ 3007+
2484+ if ((r = sshbuf_get_u32(m, &ok)) != 0) 3008+ if ((r = sshbuf_get_u32(m, &ok)) != 0)
2485+ fatal("%s: buffer error: %s", __func__, ssh_err(r)); 3009+ fatal("%s: buffer error: %s", __func__, ssh_err(r));
3010+
2486+ sshbuf_free(m); 3011+ sshbuf_free(m);
2487+ 3012+
2488+ return (ok); 3013+ return (ok);
@@ -2490,61 +3015,43 @@ index 732fb3476..1865a122a 100644
2490+ 3015+
2491 #endif /* GSSAPI */ 3016 #endif /* GSSAPI */
2492diff --git a/monitor_wrap.h b/monitor_wrap.h 3017diff --git a/monitor_wrap.h b/monitor_wrap.h
2493index 644da081d..7f93144ff 100644 3018index fdebb3aa4..69164a8c0 100644
2494--- a/monitor_wrap.h 3019--- a/monitor_wrap.h
2495+++ b/monitor_wrap.h 3020+++ b/monitor_wrap.h
2496@@ -60,8 +60,10 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t, 3021@@ -61,8 +61,10 @@ int mm_sshkey_verify(const struct sshkey *, const u_char *, size_t,
2497 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID); 3022 OM_uint32 mm_ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
2498 OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *, 3023 OM_uint32 mm_ssh_gssapi_accept_ctx(Gssctxt *,
2499 gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *); 3024 gss_buffer_desc *, gss_buffer_desc *, OM_uint32 *);
2500-int mm_ssh_gssapi_userok(char *user); 3025-int mm_ssh_gssapi_userok(char *user);
2501+int mm_ssh_gssapi_userok(char *user, struct passwd *); 3026+int mm_ssh_gssapi_userok(char *user, struct passwd *, int kex);
2502 OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); 3027 OM_uint32 mm_ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
2503+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); 3028+OM_uint32 mm_ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
2504+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *); 3029+int mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *);
2505 #endif 3030 #endif
2506 3031
2507 #ifdef USE_PAM 3032 #ifdef USE_PAM
2508diff --git a/opacket.c b/opacket.c
2509index e637d7a71..7672c0b59 100644
2510--- a/opacket.c
2511+++ b/opacket.c
2512@@ -80,7 +80,7 @@ ssh_packet_put_raw(struct ssh *ssh, const void *buf, u_int len)
2513
2514 #ifdef WITH_OPENSSL
2515 void
2516-ssh_packet_put_bignum2(struct ssh *ssh, BIGNUM * value)
2517+ssh_packet_put_bignum2(struct ssh *ssh, const BIGNUM * value)
2518 {
2519 int r;
2520
2521diff --git a/opacket.h b/opacket.h
2522index f92fe586e..1cf66a2d3 100644
2523--- a/opacket.h
2524+++ b/opacket.h
2525@@ -7,7 +7,7 @@ void ssh_packet_start(struct ssh *, u_char);
2526 void ssh_packet_put_char(struct ssh *, int ch);
2527 void ssh_packet_put_int(struct ssh *, u_int value);
2528 void ssh_packet_put_int64(struct ssh *, u_int64_t value);
2529-void ssh_packet_put_bignum2(struct ssh *, BIGNUM * value);
2530+void ssh_packet_put_bignum2(struct ssh *, const BIGNUM * value);
2531 void ssh_packet_put_ecpoint(struct ssh *, const EC_GROUP *, const EC_POINT *);
2532 void ssh_packet_put_string(struct ssh *, const void *buf, u_int len);
2533 void ssh_packet_put_cstring(struct ssh *, const char *str);
2534diff --git a/readconf.c b/readconf.c 3033diff --git a/readconf.c b/readconf.c
2535index 433811521..36bc5e59a 100644 3034index ec497e79f..4d699e5f1 100644
2536--- a/readconf.c 3035--- a/readconf.c
2537+++ b/readconf.c 3036+++ b/readconf.c
2538@@ -161,6 +161,8 @@ typedef enum { 3037@@ -67,6 +67,7 @@
3038 #include "uidswap.h"
3039 #include "myproposal.h"
3040 #include "digest.h"
3041+#include "ssh-gss.h"
3042
3043 /* Format of the configuration file:
3044
3045@@ -162,6 +163,8 @@ typedef enum {
2539 oClearAllForwardings, oNoHostAuthenticationForLocalhost, 3046 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
2540 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 3047 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
2541 oAddressFamily, oGssAuthentication, oGssDelegateCreds, 3048 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
2542+ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey, 3049+ oGssTrustDns, oGssKeyEx, oGssClientIdentity, oGssRenewalRekey,
2543+ oGssServerIdentity, 3050+ oGssServerIdentity, oGssKexAlgorithms,
2544 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 3051 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
2545 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist, 3052 oSendEnv, oSetEnv, oControlPath, oControlMaster, oControlPersist,
2546 oHashKnownHosts, 3053 oHashKnownHosts,
2547@@ -201,10 +203,20 @@ static struct { 3054@@ -202,10 +205,22 @@ static struct {
2548 /* Sometimes-unsupported options */ 3055 /* Sometimes-unsupported options */
2549 #if defined(GSSAPI) 3056 #if defined(GSSAPI)
2550 { "gssapiauthentication", oGssAuthentication }, 3057 { "gssapiauthentication", oGssAuthentication },
@@ -2554,6 +3061,7 @@ index 433811521..36bc5e59a 100644
2554+ { "gssapiclientidentity", oGssClientIdentity }, 3061+ { "gssapiclientidentity", oGssClientIdentity },
2555+ { "gssapiserveridentity", oGssServerIdentity }, 3062+ { "gssapiserveridentity", oGssServerIdentity },
2556+ { "gssapirenewalforcesrekey", oGssRenewalRekey }, 3063+ { "gssapirenewalforcesrekey", oGssRenewalRekey },
3064+ { "gssapikexalgorithms", oGssKexAlgorithms },
2557 # else 3065 # else
2558 { "gssapiauthentication", oUnsupported }, 3066 { "gssapiauthentication", oUnsupported },
2559+ { "gssapikeyexchange", oUnsupported }, 3067+ { "gssapikeyexchange", oUnsupported },
@@ -2562,10 +3070,11 @@ index 433811521..36bc5e59a 100644
2562+ { "gssapiclientidentity", oUnsupported }, 3070+ { "gssapiclientidentity", oUnsupported },
2563+ { "gssapiserveridentity", oUnsupported }, 3071+ { "gssapiserveridentity", oUnsupported },
2564+ { "gssapirenewalforcesrekey", oUnsupported }, 3072+ { "gssapirenewalforcesrekey", oUnsupported },
3073+ { "gssapikexalgorithms", oUnsupported },
2565 #endif 3074 #endif
2566 #ifdef ENABLE_PKCS11 3075 #ifdef ENABLE_PKCS11
2567 { "smartcarddevice", oPKCS11Provider }, 3076 { "pkcs11provider", oPKCS11Provider },
2568@@ -974,10 +986,30 @@ parse_time: 3077@@ -983,10 +998,42 @@ parse_time:
2569 intptr = &options->gss_authentication; 3078 intptr = &options->gss_authentication;
2570 goto parse_flag; 3079 goto parse_flag;
2571 3080
@@ -2593,10 +3102,22 @@ index 433811521..36bc5e59a 100644
2593+ intptr = &options->gss_renewal_rekey; 3102+ intptr = &options->gss_renewal_rekey;
2594+ goto parse_flag; 3103+ goto parse_flag;
2595+ 3104+
3105+ case oGssKexAlgorithms:
3106+ arg = strdelim(&s);
3107+ if (!arg || *arg == '\0')
3108+ fatal("%.200s line %d: Missing argument.",
3109+ filename, linenum);
3110+ if (!kex_gss_names_valid(arg))
3111+ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.",
3112+ filename, linenum, arg ? arg : "<NONE>");
3113+ if (*activep && options->gss_kex_algorithms == NULL)
3114+ options->gss_kex_algorithms = xstrdup(arg);
3115+ break;
3116+
2596 case oBatchMode: 3117 case oBatchMode:
2597 intptr = &options->batch_mode; 3118 intptr = &options->batch_mode;
2598 goto parse_flag; 3119 goto parse_flag;
2599@@ -1842,7 +1874,12 @@ initialize_options(Options * options) 3120@@ -1854,7 +1901,13 @@ initialize_options(Options * options)
2600 options->pubkey_authentication = -1; 3121 options->pubkey_authentication = -1;
2601 options->challenge_response_authentication = -1; 3122 options->challenge_response_authentication = -1;
2602 options->gss_authentication = -1; 3123 options->gss_authentication = -1;
@@ -2606,10 +3127,11 @@ index 433811521..36bc5e59a 100644
2606+ options->gss_renewal_rekey = -1; 3127+ options->gss_renewal_rekey = -1;
2607+ options->gss_client_identity = NULL; 3128+ options->gss_client_identity = NULL;
2608+ options->gss_server_identity = NULL; 3129+ options->gss_server_identity = NULL;
3130+ options->gss_kex_algorithms = NULL;
2609 options->password_authentication = -1; 3131 options->password_authentication = -1;
2610 options->kbd_interactive_authentication = -1; 3132 options->kbd_interactive_authentication = -1;
2611 options->kbd_interactive_devices = NULL; 3133 options->kbd_interactive_devices = NULL;
2612@@ -1988,8 +2025,14 @@ fill_default_options(Options * options) 3134@@ -2000,8 +2053,18 @@ fill_default_options(Options * options)
2613 options->challenge_response_authentication = 1; 3135 options->challenge_response_authentication = 1;
2614 if (options->gss_authentication == -1) 3136 if (options->gss_authentication == -1)
2615 options->gss_authentication = 0; 3137 options->gss_authentication = 0;
@@ -2621,14 +3143,33 @@ index 433811521..36bc5e59a 100644
2621+ options->gss_trust_dns = 0; 3143+ options->gss_trust_dns = 0;
2622+ if (options->gss_renewal_rekey == -1) 3144+ if (options->gss_renewal_rekey == -1)
2623+ options->gss_renewal_rekey = 0; 3145+ options->gss_renewal_rekey = 0;
3146+#ifdef GSSAPI
3147+ if (options->gss_kex_algorithms == NULL)
3148+ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
3149+#endif
2624 if (options->password_authentication == -1) 3150 if (options->password_authentication == -1)
2625 options->password_authentication = 1; 3151 options->password_authentication = 1;
2626 if (options->kbd_interactive_authentication == -1) 3152 if (options->kbd_interactive_authentication == -1)
3153@@ -2616,7 +2679,14 @@ dump_client_config(Options *o, const char *host)
3154 dump_cfg_fmtint(oGatewayPorts, o->fwd_opts.gateway_ports);
3155 #ifdef GSSAPI
3156 dump_cfg_fmtint(oGssAuthentication, o->gss_authentication);
3157+ dump_cfg_fmtint(oGssKeyEx, o->gss_keyex);
3158 dump_cfg_fmtint(oGssDelegateCreds, o->gss_deleg_creds);
3159+ dump_cfg_fmtint(oGssTrustDns, o->gss_trust_dns);
3160+ dump_cfg_fmtint(oGssRenewalRekey, o->gss_renewal_rekey);
3161+ dump_cfg_string(oGssClientIdentity, o->gss_client_identity);
3162+ dump_cfg_string(oGssServerIdentity, o->gss_server_identity);
3163+ dump_cfg_string(oGssKexAlgorithms, o->gss_kex_algorithms ?
3164+ o->gss_kex_algorithms : GSS_KEX_DEFAULT_KEX);
3165 #endif /* GSSAPI */
3166 dump_cfg_fmtint(oHashKnownHosts, o->hash_known_hosts);
3167 dump_cfg_fmtint(oHostbasedAuthentication, o->hostbased_authentication);
2627diff --git a/readconf.h b/readconf.h 3168diff --git a/readconf.h b/readconf.h
2628index fc7e38251..8e4900d01 100644 3169index 8e36bf32a..0bff6d80a 100644
2629--- a/readconf.h 3170--- a/readconf.h
2630+++ b/readconf.h 3171+++ b/readconf.h
2631@@ -40,7 +40,12 @@ typedef struct { 3172@@ -40,7 +40,13 @@ typedef struct {
2632 int challenge_response_authentication; 3173 int challenge_response_authentication;
2633 /* Try S/Key or TIS, authentication. */ 3174 /* Try S/Key or TIS, authentication. */
2634 int gss_authentication; /* Try GSS authentication */ 3175 int gss_authentication; /* Try GSS authentication */
@@ -2638,14 +3179,23 @@ index fc7e38251..8e4900d01 100644
2638+ int gss_renewal_rekey; /* Credential renewal forces rekey */ 3179+ int gss_renewal_rekey; /* Credential renewal forces rekey */
2639+ char *gss_client_identity; /* Principal to initiate GSSAPI with */ 3180+ char *gss_client_identity; /* Principal to initiate GSSAPI with */
2640+ char *gss_server_identity; /* GSSAPI target principal */ 3181+ char *gss_server_identity; /* GSSAPI target principal */
3182+ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */
2641 int password_authentication; /* Try password 3183 int password_authentication; /* Try password
2642 * authentication. */ 3184 * authentication. */
2643 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ 3185 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
2644diff --git a/servconf.c b/servconf.c 3186diff --git a/servconf.c b/servconf.c
2645index 932d363bb..4668b8a45 100644 3187index ffac5d2c7..ffdad31e7 100644
2646--- a/servconf.c 3188--- a/servconf.c
2647+++ b/servconf.c 3189+++ b/servconf.c
2648@@ -124,8 +124,10 @@ initialize_server_options(ServerOptions *options) 3190@@ -64,6 +64,7 @@
3191 #include "auth.h"
3192 #include "myproposal.h"
3193 #include "digest.h"
3194+#include "ssh-gss.h"
3195
3196 static void add_listen_addr(ServerOptions *, const char *,
3197 const char *, int);
3198@@ -124,8 +125,11 @@ initialize_server_options(ServerOptions *options)
2649 options->kerberos_ticket_cleanup = -1; 3199 options->kerberos_ticket_cleanup = -1;
2650 options->kerberos_get_afs_token = -1; 3200 options->kerberos_get_afs_token = -1;
2651 options->gss_authentication=-1; 3201 options->gss_authentication=-1;
@@ -2653,10 +3203,11 @@ index 932d363bb..4668b8a45 100644
2653 options->gss_cleanup_creds = -1; 3203 options->gss_cleanup_creds = -1;
2654 options->gss_strict_acceptor = -1; 3204 options->gss_strict_acceptor = -1;
2655+ options->gss_store_rekey = -1; 3205+ options->gss_store_rekey = -1;
3206+ options->gss_kex_algorithms = NULL;
2656 options->password_authentication = -1; 3207 options->password_authentication = -1;
2657 options->kbd_interactive_authentication = -1; 3208 options->kbd_interactive_authentication = -1;
2658 options->challenge_response_authentication = -1; 3209 options->challenge_response_authentication = -1;
2659@@ -337,10 +339,14 @@ fill_default_server_options(ServerOptions *options) 3210@@ -351,10 +355,18 @@ fill_default_server_options(ServerOptions *options)
2660 options->kerberos_get_afs_token = 0; 3211 options->kerberos_get_afs_token = 0;
2661 if (options->gss_authentication == -1) 3212 if (options->gss_authentication == -1)
2662 options->gss_authentication = 0; 3213 options->gss_authentication = 0;
@@ -2668,18 +3219,22 @@ index 932d363bb..4668b8a45 100644
2668 options->gss_strict_acceptor = 1; 3219 options->gss_strict_acceptor = 1;
2669+ if (options->gss_store_rekey == -1) 3220+ if (options->gss_store_rekey == -1)
2670+ options->gss_store_rekey = 0; 3221+ options->gss_store_rekey = 0;
3222+#ifdef GSSAPI
3223+ if (options->gss_kex_algorithms == NULL)
3224+ options->gss_kex_algorithms = strdup(GSS_KEX_DEFAULT_KEX);
3225+#endif
2671 if (options->password_authentication == -1) 3226 if (options->password_authentication == -1)
2672 options->password_authentication = 1; 3227 options->password_authentication = 1;
2673 if (options->kbd_interactive_authentication == -1) 3228 if (options->kbd_interactive_authentication == -1)
2674@@ -485,6 +491,7 @@ typedef enum { 3229@@ -498,6 +510,7 @@ typedef enum {
2675 sHostKeyAlgorithms, 3230 sHostKeyAlgorithms,
2676 sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile, 3231 sClientAliveInterval, sClientAliveCountMax, sAuthorizedKeysFile,
2677 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor, 3232 sGssAuthentication, sGssCleanupCreds, sGssStrictAcceptor,
2678+ sGssKeyEx, sGssStoreRekey, 3233+ sGssKeyEx, sGssKexAlgorithms, sGssStoreRekey,
2679 sAcceptEnv, sSetEnv, sPermitTunnel, 3234 sAcceptEnv, sSetEnv, sPermitTunnel,
2680 sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, 3235 sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory,
2681 sUsePrivilegeSeparation, sAllowAgentForwarding, 3236 sUsePrivilegeSeparation, sAllowAgentForwarding,
2682@@ -559,12 +566,20 @@ static struct { 3237@@ -572,12 +585,22 @@ static struct {
2683 #ifdef GSSAPI 3238 #ifdef GSSAPI
2684 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 3239 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
2685 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 3240 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
@@ -2687,6 +3242,7 @@ index 932d363bb..4668b8a45 100644
2687 { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL }, 3242 { "gssapistrictacceptorcheck", sGssStrictAcceptor, SSHCFG_GLOBAL },
2688+ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL }, 3243+ { "gssapikeyexchange", sGssKeyEx, SSHCFG_GLOBAL },
2689+ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL }, 3244+ { "gssapistorecredentialsonrekey", sGssStoreRekey, SSHCFG_GLOBAL },
3245+ { "gssapikexalgorithms", sGssKexAlgorithms, SSHCFG_GLOBAL },
2690 #else 3246 #else
2691 { "gssapiauthentication", sUnsupported, SSHCFG_ALL }, 3247 { "gssapiauthentication", sUnsupported, SSHCFG_ALL },
2692 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL }, 3248 { "gssapicleanupcredentials", sUnsupported, SSHCFG_GLOBAL },
@@ -2694,13 +3250,14 @@ index 932d363bb..4668b8a45 100644
2694 { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL }, 3250 { "gssapistrictacceptorcheck", sUnsupported, SSHCFG_GLOBAL },
2695+ { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL }, 3251+ { "gssapikeyexchange", sUnsupported, SSHCFG_GLOBAL },
2696+ { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL }, 3252+ { "gssapistorecredentialsonrekey", sUnsupported, SSHCFG_GLOBAL },
3253+ { "gssapikexalgorithms", sUnsupported, SSHCFG_GLOBAL },
2697 #endif 3254 #endif
2698+ { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL }, 3255+ { "gssusesessionccache", sUnsupported, SSHCFG_GLOBAL },
2699+ { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL }, 3256+ { "gssapiusesessioncredcache", sUnsupported, SSHCFG_GLOBAL },
2700 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 3257 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
2701 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 3258 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
2702 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 3259 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
2703@@ -1468,6 +1483,10 @@ process_server_config_line(ServerOptions *options, char *line, 3260@@ -1485,6 +1508,10 @@ process_server_config_line(ServerOptions *options, char *line,
2704 intptr = &options->gss_authentication; 3261 intptr = &options->gss_authentication;
2705 goto parse_flag; 3262 goto parse_flag;
2706 3263
@@ -2711,7 +3268,7 @@ index 932d363bb..4668b8a45 100644
2711 case sGssCleanupCreds: 3268 case sGssCleanupCreds:
2712 intptr = &options->gss_cleanup_creds; 3269 intptr = &options->gss_cleanup_creds;
2713 goto parse_flag; 3270 goto parse_flag;
2714@@ -1476,6 +1495,10 @@ process_server_config_line(ServerOptions *options, char *line, 3271@@ -1493,6 +1520,22 @@ process_server_config_line(ServerOptions *options, char *line,
2715 intptr = &options->gss_strict_acceptor; 3272 intptr = &options->gss_strict_acceptor;
2716 goto parse_flag; 3273 goto parse_flag;
2717 3274
@@ -2719,25 +3276,37 @@ index 932d363bb..4668b8a45 100644
2719+ intptr = &options->gss_store_rekey; 3276+ intptr = &options->gss_store_rekey;
2720+ goto parse_flag; 3277+ goto parse_flag;
2721+ 3278+
3279+ case sGssKexAlgorithms:
3280+ arg = strdelim(&cp);
3281+ if (!arg || *arg == '\0')
3282+ fatal("%.200s line %d: Missing argument.",
3283+ filename, linenum);
3284+ if (!kex_gss_names_valid(arg))
3285+ fatal("%.200s line %d: Bad GSSAPI KexAlgorithms '%s'.",
3286+ filename, linenum, arg ? arg : "<NONE>");
3287+ if (*activep && options->gss_kex_algorithms == NULL)
3288+ options->gss_kex_algorithms = xstrdup(arg);
3289+ break;
3290+
2722 case sPasswordAuthentication: 3291 case sPasswordAuthentication:
2723 intptr = &options->password_authentication; 3292 intptr = &options->password_authentication;
2724 goto parse_flag; 3293 goto parse_flag;
2725@@ -2560,7 +2583,10 @@ dump_config(ServerOptions *o) 3294@@ -2579,6 +2622,10 @@ dump_config(ServerOptions *o)
2726 #endif
2727 #ifdef GSSAPI 3295 #ifdef GSSAPI
2728 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 3296 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
2729+ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
2730 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds); 3297 dump_cfg_fmtint(sGssCleanupCreds, o->gss_cleanup_creds);
3298+ dump_cfg_fmtint(sGssKeyEx, o->gss_keyex);
2731+ dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor); 3299+ dump_cfg_fmtint(sGssStrictAcceptor, o->gss_strict_acceptor);
2732+ dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey); 3300+ dump_cfg_fmtint(sGssStoreRekey, o->gss_store_rekey);
3301+ dump_cfg_string(sGssKexAlgorithms, o->gss_kex_algorithms);
2733 #endif 3302 #endif
2734 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); 3303 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
2735 dump_cfg_fmtint(sKbdInteractiveAuthentication, 3304 dump_cfg_fmtint(sKbdInteractiveAuthentication,
2736diff --git a/servconf.h b/servconf.h 3305diff --git a/servconf.h b/servconf.h
2737index 0175e00e8..3b76da816 100644 3306index 54e0a8d8d..a476d5220 100644
2738--- a/servconf.h 3307--- a/servconf.h
2739+++ b/servconf.h 3308+++ b/servconf.h
2740@@ -125,8 +125,10 @@ typedef struct { 3309@@ -126,8 +126,11 @@ typedef struct {
2741 int kerberos_get_afs_token; /* If true, try to get AFS token if 3310 int kerberos_get_afs_token; /* If true, try to get AFS token if
2742 * authenticated with Kerberos. */ 3311 * authenticated with Kerberos. */
2743 int gss_authentication; /* If true, permit GSSAPI authentication */ 3312 int gss_authentication; /* If true, permit GSSAPI authentication */
@@ -2745,11 +3314,38 @@ index 0175e00e8..3b76da816 100644
2745 int gss_cleanup_creds; /* If true, destroy cred cache on logout */ 3314 int gss_cleanup_creds; /* If true, destroy cred cache on logout */
2746 int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */ 3315 int gss_strict_acceptor; /* If true, restrict the GSSAPI acceptor name */
2747+ int gss_store_rekey; 3316+ int gss_store_rekey;
3317+ char *gss_kex_algorithms; /* GSSAPI kex methods to be offered by client. */
2748 int password_authentication; /* If true, permit password 3318 int password_authentication; /* If true, permit password
2749 * authentication. */ 3319 * authentication. */
2750 int kbd_interactive_authentication; /* If true, permit */ 3320 int kbd_interactive_authentication; /* If true, permit */
3321diff --git a/session.c b/session.c
3322index ac06b08e9..ac3d9d19d 100644
3323--- a/session.c
3324+++ b/session.c
3325@@ -2674,13 +2674,19 @@ do_cleanup(struct ssh *ssh, Authctxt *authctxt)
3326
3327 #ifdef KRB5
3328 if (options.kerberos_ticket_cleanup &&
3329- authctxt->krb5_ctx)
3330+ authctxt->krb5_ctx) {
3331+ temporarily_use_uid(authctxt->pw);
3332 krb5_cleanup_proc(authctxt);
3333+ restore_uid();
3334+ }
3335 #endif
3336
3337 #ifdef GSSAPI
3338- if (options.gss_cleanup_creds)
3339+ if (options.gss_cleanup_creds) {
3340+ temporarily_use_uid(authctxt->pw);
3341 ssh_gssapi_cleanup_creds();
3342+ restore_uid();
3343+ }
3344 #endif
3345
3346 /* remove agent socket */
2751diff --git a/ssh-gss.h b/ssh-gss.h 3347diff --git a/ssh-gss.h b/ssh-gss.h
2752index 36180d07a..350ce7882 100644 3348index 36180d07a..70dd36658 100644
2753--- a/ssh-gss.h 3349--- a/ssh-gss.h
2754+++ b/ssh-gss.h 3350+++ b/ssh-gss.h
2755@@ -1,6 +1,6 @@ 3351@@ -1,6 +1,6 @@
@@ -2760,7 +3356,7 @@ index 36180d07a..350ce7882 100644
2760 * 3356 *
2761 * Redistribution and use in source and binary forms, with or without 3357 * Redistribution and use in source and binary forms, with or without
2762 * modification, are permitted provided that the following conditions 3358 * modification, are permitted provided that the following conditions
2763@@ -61,10 +61,22 @@ 3359@@ -61,10 +61,30 @@
2764 3360
2765 #define SSH_GSS_OIDTYPE 0x06 3361 #define SSH_GSS_OIDTYPE 0x06
2766 3362
@@ -2773,7 +3369,15 @@ index 36180d07a..350ce7882 100644
2773+#define SSH2_MSG_KEXGSS_GROUP 41 3369+#define SSH2_MSG_KEXGSS_GROUP 41
2774+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-" 3370+#define KEX_GSS_GRP1_SHA1_ID "gss-group1-sha1-"
2775+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-" 3371+#define KEX_GSS_GRP14_SHA1_ID "gss-group14-sha1-"
3372+#define KEX_GSS_GRP14_SHA256_ID "gss-group14-sha256-"
3373+#define KEX_GSS_GRP16_SHA512_ID "gss-group16-sha512-"
2776+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-" 3374+#define KEX_GSS_GEX_SHA1_ID "gss-gex-sha1-"
3375+#define KEX_GSS_NISTP256_SHA256_ID "gss-nistp256-sha256-"
3376+#define KEX_GSS_C25519_SHA256_ID "gss-curve25519-sha256-"
3377+
3378+#define GSS_KEX_DEFAULT_KEX \
3379+ KEX_GSS_GEX_SHA1_ID "," \
3380+ KEX_GSS_GRP14_SHA1_ID
2777+ 3381+
2778 typedef struct { 3382 typedef struct {
2779 char *filename; 3383 char *filename;
@@ -2783,7 +3387,7 @@ index 36180d07a..350ce7882 100644
2783 void *data; 3387 void *data;
2784 } ssh_gssapi_ccache; 3388 } ssh_gssapi_ccache;
2785 3389
2786@@ -72,8 +84,11 @@ typedef struct { 3390@@ -72,8 +92,11 @@ typedef struct {
2787 gss_buffer_desc displayname; 3391 gss_buffer_desc displayname;
2788 gss_buffer_desc exportedname; 3392 gss_buffer_desc exportedname;
2789 gss_cred_id_t creds; 3393 gss_cred_id_t creds;
@@ -2795,7 +3399,7 @@ index 36180d07a..350ce7882 100644
2795 } ssh_gssapi_client; 3399 } ssh_gssapi_client;
2796 3400
2797 typedef struct ssh_gssapi_mech_struct { 3401 typedef struct ssh_gssapi_mech_struct {
2798@@ -84,6 +99,7 @@ typedef struct ssh_gssapi_mech_struct { 3402@@ -84,6 +107,7 @@ typedef struct ssh_gssapi_mech_struct {
2799 int (*userok) (ssh_gssapi_client *, char *); 3403 int (*userok) (ssh_gssapi_client *, char *);
2800 int (*localname) (ssh_gssapi_client *, char **); 3404 int (*localname) (ssh_gssapi_client *, char **);
2801 void (*storecreds) (ssh_gssapi_client *); 3405 void (*storecreds) (ssh_gssapi_client *);
@@ -2803,7 +3407,7 @@ index 36180d07a..350ce7882 100644
2803 } ssh_gssapi_mech; 3407 } ssh_gssapi_mech;
2804 3408
2805 typedef struct { 3409 typedef struct {
2806@@ -94,10 +110,11 @@ typedef struct { 3410@@ -94,10 +118,11 @@ typedef struct {
2807 gss_OID oid; /* client */ 3411 gss_OID oid; /* client */
2808 gss_cred_id_t creds; /* server */ 3412 gss_cred_id_t creds; /* server */
2809 gss_name_t client; /* server */ 3413 gss_name_t client; /* server */
@@ -2816,7 +3420,15 @@ index 36180d07a..350ce7882 100644
2816 3420
2817 int ssh_gssapi_check_oid(Gssctxt *, void *, size_t); 3421 int ssh_gssapi_check_oid(Gssctxt *, void *, size_t);
2818 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t); 3422 void ssh_gssapi_set_oid_data(Gssctxt *, void *, size_t);
2819@@ -123,17 +140,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **); 3423@@ -109,6 +134,7 @@ OM_uint32 ssh_gssapi_test_oid_supported(OM_uint32 *, gss_OID, int *);
3424
3425 struct sshbuf;
3426 int ssh_gssapi_get_buffer_desc(struct sshbuf *, gss_buffer_desc *);
3427+int ssh_gssapi_sshpkt_get_buffer_desc(struct ssh *, gss_buffer_desc *);
3428
3429 OM_uint32 ssh_gssapi_import_name(Gssctxt *, const char *);
3430 OM_uint32 ssh_gssapi_init_ctx(Gssctxt *, int,
3431@@ -123,17 +149,33 @@ void ssh_gssapi_delete_ctx(Gssctxt **);
2820 OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t); 3432 OM_uint32 ssh_gssapi_sign(Gssctxt *, gss_buffer_t, gss_buffer_t);
2821 void ssh_gssapi_buildmic(struct sshbuf *, const char *, 3433 void ssh_gssapi_buildmic(struct sshbuf *, const char *,
2822 const char *, const char *); 3434 const char *, const char *);
@@ -2826,17 +3438,17 @@ index 36180d07a..350ce7882 100644
2826+int ssh_gssapi_credentials_updated(Gssctxt *); 3438+int ssh_gssapi_credentials_updated(Gssctxt *);
2827 3439
2828 /* In the server */ 3440 /* In the server */
2829+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *, 3441+typedef int ssh_gssapi_check_fn(Gssctxt **, gss_OID, const char *,
2830+ const char *); 3442+ const char *);
2831+char *ssh_gssapi_client_mechanisms(const char *, const char *); 3443+char *ssh_gssapi_client_mechanisms(const char *, const char *, const char *);
2832+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *, 3444+char *ssh_gssapi_kex_mechs(gss_OID_set, ssh_gssapi_check_fn *, const char *,
2833+ const char *); 3445+ const char *, const char *);
2834+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int); 3446+gss_OID ssh_gssapi_id_kex(Gssctxt *, char *, int);
2835+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *, 3447+int ssh_gssapi_server_check_mech(Gssctxt **,gss_OID, const char *,
2836+ const char *); 3448+ const char *);
2837 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID); 3449 OM_uint32 ssh_gssapi_server_ctx(Gssctxt **, gss_OID);
2838-int ssh_gssapi_userok(char *name); 3450-int ssh_gssapi_userok(char *name);
2839+int ssh_gssapi_userok(char *name, struct passwd *); 3451+int ssh_gssapi_userok(char *name, struct passwd *, int kex);
2840 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t); 3452 OM_uint32 ssh_gssapi_checkmic(Gssctxt *, gss_buffer_t, gss_buffer_t);
2841 void ssh_gssapi_do_child(char ***, u_int *); 3453 void ssh_gssapi_do_child(char ***, u_int *);
2842 void ssh_gssapi_cleanup_creds(void); 3454 void ssh_gssapi_cleanup_creds(void);
@@ -2852,8 +3464,57 @@ index 36180d07a..350ce7882 100644
2852 #endif /* GSSAPI */ 3464 #endif /* GSSAPI */
2853 3465
2854 #endif /* _SSH_GSS_H */ 3466 #endif /* _SSH_GSS_H */
3467diff --git a/ssh.1 b/ssh.1
3468index 9480eba8d..a1c7d2305 100644
3469--- a/ssh.1
3470+++ b/ssh.1
3471@@ -497,7 +497,13 @@ For full details of the options listed below, and their possible values, see
3472 .It GatewayPorts
3473 .It GlobalKnownHostsFile
3474 .It GSSAPIAuthentication
3475+.It GSSAPIKeyExchange
3476+.It GSSAPIClientIdentity
3477 .It GSSAPIDelegateCredentials
3478+.It GSSAPIKexAlgorithms
3479+.It GSSAPIRenewalForcesRekey
3480+.It GSSAPIServerIdentity
3481+.It GSSAPITrustDns
3482 .It HashKnownHosts
3483 .It Host
3484 .It HostbasedAuthentication
3485@@ -573,6 +579,8 @@ flag),
3486 (supported message integrity codes),
3487 .Ar kex
3488 (key exchange algorithms),
3489+.Ar kex-gss
3490+(GSSAPI key exchange algorithms),
3491 .Ar key
3492 (key types),
3493 .Ar key-cert
3494diff --git a/ssh.c b/ssh.c
3495index 91e7c3511..42be7d88f 100644
3496--- a/ssh.c
3497+++ b/ssh.c
3498@@ -736,6 +736,8 @@ main(int ac, char **av)
3499 cp = mac_alg_list('\n');
3500 else if (strcmp(optarg, "kex") == 0)
3501 cp = kex_alg_list('\n');
3502+ else if (strcmp(optarg, "kex-gss") == 0)
3503+ cp = kex_gss_alg_list('\n');
3504 else if (strcmp(optarg, "key") == 0)
3505 cp = sshkey_alg_list(0, 0, 0, '\n');
3506 else if (strcmp(optarg, "key-cert") == 0)
3507@@ -748,7 +750,7 @@ main(int ac, char **av)
3508 cp = xstrdup("2");
3509 else if (strcmp(optarg, "help") == 0) {
3510 cp = xstrdup(
3511- "cipher\ncipher-auth\nkex\nkey\n"
3512+ "cipher\ncipher-auth\nkex\nkex-gss\nkey\n"
3513 "key-cert\nkey-plain\nmac\n"
3514 "protocol-version\nsig");
3515 }
2855diff --git a/ssh_config b/ssh_config 3516diff --git a/ssh_config b/ssh_config
2856index c12f5ef52..bcb9f153d 100644 3517index 5e8ef548b..1ff999b68 100644
2857--- a/ssh_config 3518--- a/ssh_config
2858+++ b/ssh_config 3519+++ b/ssh_config
2859@@ -24,6 +24,8 @@ 3520@@ -24,6 +24,8 @@
@@ -2866,61 +3527,95 @@ index c12f5ef52..bcb9f153d 100644
2866 # CheckHostIP yes 3527 # CheckHostIP yes
2867 # AddressFamily any 3528 # AddressFamily any
2868diff --git a/ssh_config.5 b/ssh_config.5 3529diff --git a/ssh_config.5 b/ssh_config.5
2869index 4d5b01d3e..16c79368a 100644 3530index 412629637..c3c8b274a 100644
2870--- a/ssh_config.5 3531--- a/ssh_config.5
2871+++ b/ssh_config.5 3532+++ b/ssh_config.5
2872@@ -736,10 +736,42 @@ The default is 3533@@ -754,10 +754,67 @@ The default is
2873 Specifies whether user authentication based on GSSAPI is allowed. 3534 Specifies whether user authentication based on GSSAPI is allowed.
2874 The default is 3535 The default is
2875 .Cm no . 3536 .Cm no .
2876+.It Cm GSSAPIKeyExchange
2877+Specifies whether key exchange based on GSSAPI may be used. When using
2878+GSSAPI key exchange the server need not have a host key.
2879+The default is
2880+.Cm no .
2881+.It Cm GSSAPIClientIdentity 3537+.It Cm GSSAPIClientIdentity
2882+If set, specifies the GSSAPI client identity that ssh should use when 3538+If set, specifies the GSSAPI client identity that ssh should use when
2883+connecting to the server. The default is unset, which means that the default 3539+connecting to the server. The default is unset, which means that the default
2884+identity will be used. 3540+identity will be used.
2885+.It Cm GSSAPIServerIdentity
2886+If set, specifies the GSSAPI server identity that ssh should expect when
2887+connecting to the server. The default is unset, which means that the
2888+expected GSSAPI server identity will be determined from the target
2889+hostname.
2890 .It Cm GSSAPIDelegateCredentials 3541 .It Cm GSSAPIDelegateCredentials
2891 Forward (delegate) credentials to the server. 3542 Forward (delegate) credentials to the server.
2892 The default is 3543 The default is
2893 .Cm no . 3544 .Cm no .
3545+.It Cm GSSAPIKeyExchange
3546+Specifies whether key exchange based on GSSAPI may be used. When using
3547+GSSAPI key exchange the server need not have a host key.
3548+The default is
3549+.Dq no .
2894+.It Cm GSSAPIRenewalForcesRekey 3550+.It Cm GSSAPIRenewalForcesRekey
2895+If set to 3551+If set to
2896+.Cm yes 3552+.Dq yes
2897+then renewal of the client's GSSAPI credentials will force the rekeying of the 3553+then renewal of the client's GSSAPI credentials will force the rekeying of the
2898+ssh connection. With a compatible server, this can delegate the renewed 3554+ssh connection. With a compatible server, this will delegate the renewed
2899+credentials to a session on the server. 3555+credentials to a session on the server.
3556+.Pp
3557+Checks are made to ensure that credentials are only propagated when the new
3558+credentials match the old ones on the originating client and where the
3559+receiving server still has the old set in its cache.
3560+.Pp
2900+The default is 3561+The default is
2901+.Cm no . 3562+.Dq no .
3563+.Pp
3564+For this to work
3565+.Cm GSSAPIKeyExchange
3566+needs to be enabled in the server and also used by the client.
3567+.It Cm GSSAPIServerIdentity
3568+If set, specifies the GSSAPI server identity that ssh should expect when
3569+connecting to the server. The default is unset, which means that the
3570+expected GSSAPI server identity will be determined from the target
3571+hostname.
2902+.It Cm GSSAPITrustDns 3572+.It Cm GSSAPITrustDns
2903+Set to 3573+Set to
2904+.Cm yes 3574+.Dq yes
2905+to indicate that the DNS is trusted to securely canonicalize 3575+to indicate that the DNS is trusted to securely canonicalize
2906+the name of the host being connected to. If 3576+the name of the host being connected to. If
2907+.Cm no , 3577+.Dq no ,
2908+the hostname entered on the 3578+the hostname entered on the
2909+command line will be passed untouched to the GSSAPI library. 3579+command line will be passed untouched to the GSSAPI library.
2910+The default is 3580+The default is
2911+.Cm no . 3581+.Dq no .
3582+.It Cm GSSAPIKexAlgorithms
3583+The list of key exchange algorithms that are offered for GSSAPI
3584+key exchange. Possible values are
3585+.Bd -literal -offset 3n
3586+gss-gex-sha1-,
3587+gss-group1-sha1-,
3588+gss-group14-sha1-,
3589+gss-group14-sha256-,
3590+gss-group16-sha512-,
3591+gss-nistp256-sha256-,
3592+gss-curve25519-sha256-
3593+.Ed
3594+.Pp
3595+The default is
3596+.Dq gss-gex-sha1-,gss-group14-sha1- .
3597+This option only applies to protocol version 2 connections using GSSAPI.
2912 .It Cm HashKnownHosts 3598 .It Cm HashKnownHosts
2913 Indicates that 3599 Indicates that
2914 .Xr ssh 1 3600 .Xr ssh 1
2915diff --git a/sshconnect2.c b/sshconnect2.c 3601diff --git a/sshconnect2.c b/sshconnect2.c
2916index 1675f3935..8c872a4fb 100644 3602index dffee90b1..4020371ae 100644
2917--- a/sshconnect2.c 3603--- a/sshconnect2.c
2918+++ b/sshconnect2.c 3604+++ b/sshconnect2.c
2919@@ -162,6 +162,11 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 3605@@ -78,8 +78,6 @@
2920 struct kex *kex; 3606 #endif
3607
3608 /* import */
3609-extern char *client_version_string;
3610-extern char *server_version_string;
3611 extern Options options;
3612
3613 /*
3614@@ -161,6 +159,11 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
3615 char *s, *all_key;
2921 int r; 3616 int r;
2922 3617
2923+#ifdef GSSAPI 3618+#if defined(GSSAPI) && defined(WITH_OPENSSL)
2924+ char *orig = NULL, *gss = NULL; 3619+ char *orig = NULL, *gss = NULL;
2925+ char *gss_host = NULL; 3620+ char *gss_host = NULL;
2926+#endif 3621+#endif
@@ -2928,11 +3623,11 @@ index 1675f3935..8c872a4fb 100644
2928 xxx_host = host; 3623 xxx_host = host;
2929 xxx_hostaddr = hostaddr; 3624 xxx_hostaddr = hostaddr;
2930 3625
2931@@ -194,6 +199,35 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 3626@@ -193,6 +196,35 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
2932 order_hostkeyalgs(host, hostaddr, port)); 3627 order_hostkeyalgs(host, hostaddr, port));
2933 } 3628 }
2934 3629
2935+#ifdef GSSAPI 3630+#if defined(GSSAPI) && defined(WITH_OPENSSL)
2936+ if (options.gss_keyex) { 3631+ if (options.gss_keyex) {
2937+ /* Add the GSSAPI mechanisms currently supported on this 3632+ /* Add the GSSAPI mechanisms currently supported on this
2938+ * client to the key exchange algorithm proposal */ 3633+ * client to the key exchange algorithm proposal */
@@ -2941,19 +3636,19 @@ index 1675f3935..8c872a4fb 100644
2941+ if (options.gss_server_identity) 3636+ if (options.gss_server_identity)
2942+ gss_host = xstrdup(options.gss_server_identity); 3637+ gss_host = xstrdup(options.gss_server_identity);
2943+ else if (options.gss_trust_dns) 3638+ else if (options.gss_trust_dns)
2944+ gss_host = remote_hostname(active_state); 3639+ gss_host = remote_hostname(ssh);
2945+ else 3640+ else
2946+ gss_host = xstrdup(host); 3641+ gss_host = xstrdup(host);
2947+ 3642+
2948+ gss = ssh_gssapi_client_mechanisms(gss_host, 3643+ gss = ssh_gssapi_client_mechanisms(gss_host,
2949+ options.gss_client_identity); 3644+ options.gss_client_identity, options.gss_kex_algorithms);
2950+ if (gss) { 3645+ if (gss) {
2951+ debug("Offering GSSAPI proposal: %s", gss); 3646+ debug("Offering GSSAPI proposal: %s", gss);
2952+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS], 3647+ xasprintf(&myproposal[PROPOSAL_KEX_ALGS],
2953+ "%s,%s", gss, orig); 3648+ "%s,%s", gss, orig);
2954+ 3649+
2955+ /* If we've got GSSAPI algorithms, then we also 3650+ /* If we've got GSSAPI algorithms, then we also support the
2956+ * support the 'null' hostkey, as a last resort */ 3651+ * 'null' hostkey, as a last resort */
2957+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS]; 3652+ orig = myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS];
2958+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS], 3653+ xasprintf(&myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS],
2959+ "%s,null", orig); 3654+ "%s,null", orig);
@@ -2962,38 +3657,43 @@ index 1675f3935..8c872a4fb 100644
2962+#endif 3657+#endif
2963+ 3658+
2964 if (options.rekey_limit || options.rekey_interval) 3659 if (options.rekey_limit || options.rekey_interval)
2965 packet_set_rekey_limits(options.rekey_limit, 3660 ssh_packet_set_rekey_limits(ssh, options.rekey_limit,
2966 options.rekey_interval); 3661 options.rekey_interval);
2967@@ -215,15 +249,41 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 3662@@ -211,16 +243,46 @@ ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
3663 # ifdef OPENSSL_HAS_ECC
3664 ssh->kex->kex[KEX_ECDH_SHA2] = kex_gen_client;
2968 # endif 3665 # endif
2969 #endif 3666+# ifdef GSSAPI
2970 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
2971+#ifdef GSSAPI
2972+ if (options.gss_keyex) { 3667+ if (options.gss_keyex) {
2973+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client; 3668+ ssh->kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_client;
2974+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client; 3669+ ssh->kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_client;
2975+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_client; 3670+ ssh->kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_client;
3671+ ssh->kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_client;
3672+ ssh->kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_client;
3673+ ssh->kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_client;
3674+ ssh->kex->kex[KEX_GSS_C25519_SHA256] = kexgss_client;
2976+ } 3675+ }
2977+#endif 3676+# endif
2978 kex->client_version_string=client_version_string; 3677 #endif
2979 kex->server_version_string=server_version_string; 3678 ssh->kex->kex[KEX_C25519_SHA256] = kex_gen_client;
2980 kex->verify_host_key=&verify_host_key_callback; 3679 ssh->kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_client;
3680 ssh->kex->verify_host_key=&verify_host_key_callback;
2981 3681
2982+#ifdef GSSAPI 3682+#if defined(GSSAPI) && defined(WITH_OPENSSL)
2983+ if (options.gss_keyex) { 3683+ if (options.gss_keyex) {
2984+ kex->gss_deleg_creds = options.gss_deleg_creds; 3684+ ssh->kex->gss_deleg_creds = options.gss_deleg_creds;
2985+ kex->gss_trust_dns = options.gss_trust_dns; 3685+ ssh->kex->gss_trust_dns = options.gss_trust_dns;
2986+ kex->gss_client = options.gss_client_identity; 3686+ ssh->kex->gss_client = options.gss_client_identity;
2987+ kex->gss_host = gss_host; 3687+ ssh->kex->gss_host = gss_host;
2988+ } 3688+ }
2989+#endif 3689+#endif
2990+ 3690+
2991 ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); 3691 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done);
2992 3692
2993 /* remove ext-info from the KEX proposals for rekeying */ 3693 /* remove ext-info from the KEX proposals for rekeying */
2994 myproposal[PROPOSAL_KEX_ALGS] = 3694 myproposal[PROPOSAL_KEX_ALGS] =
2995 compat_kex_proposal(options.kex_algorithms); 3695 compat_kex_proposal(options.kex_algorithms);
2996+#ifdef GSSAPI 3696+#if defined(GSSAPI) && defined(WITH_OPENSSL)
2997+ /* repair myproposal after it was crumpled by the */ 3697+ /* repair myproposal after it was crumpled by the */
2998+ /* ext-info removal above */ 3698+ /* ext-info removal above */
2999+ if (gss) { 3699+ if (gss) {
@@ -3003,82 +3703,83 @@ index 1675f3935..8c872a4fb 100644
3003+ free(gss); 3703+ free(gss);
3004+ } 3704+ }
3005+#endif 3705+#endif
3006 if ((r = kex_prop2buf(kex->my, myproposal)) != 0) 3706 if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0)
3007 fatal("kex_prop2buf: %s", ssh_err(r)); 3707 fatal("kex_prop2buf: %s", ssh_err(r));
3008 3708
3009@@ -314,6 +374,7 @@ int input_gssapi_token(int type, u_int32_t, struct ssh *); 3709@@ -317,6 +379,7 @@ static int input_gssapi_response(int type, u_int32_t, struct ssh *);
3010 int input_gssapi_hash(int type, u_int32_t, struct ssh *); 3710 static int input_gssapi_token(int type, u_int32_t, struct ssh *);
3011 int input_gssapi_error(int, u_int32_t, struct ssh *); 3711 static int input_gssapi_error(int, u_int32_t, struct ssh *);
3012 int input_gssapi_errtok(int, u_int32_t, struct ssh *); 3712 static int input_gssapi_errtok(int, u_int32_t, struct ssh *);
3013+int userauth_gsskeyex(Authctxt *authctxt); 3713+static int userauth_gsskeyex(struct ssh *);
3014 #endif 3714 #endif
3015 3715
3016 void userauth(Authctxt *, char *); 3716 void userauth(struct ssh *, char *);
3017@@ -330,6 +391,11 @@ static char *authmethods_get(void); 3717@@ -333,6 +396,11 @@ static char *authmethods_get(void);
3018 3718
3019 Authmethod authmethods[] = { 3719 Authmethod authmethods[] = {
3020 #ifdef GSSAPI 3720 #ifdef GSSAPI
3021+ {"gssapi-keyex", 3721+ {"gssapi-keyex",
3022+ userauth_gsskeyex, 3722+ userauth_gsskeyex,
3023+ NULL, 3723+ NULL,
3024+ &options.gss_authentication, 3724+ &options.gss_keyex,
3025+ NULL}, 3725+ NULL},
3026 {"gssapi-with-mic", 3726 {"gssapi-with-mic",
3027 userauth_gssapi, 3727 userauth_gssapi,
3028 NULL, 3728 userauth_gssapi_cleanup,
3029@@ -686,25 +752,40 @@ userauth_gssapi(Authctxt *authctxt) 3729@@ -698,12 +766,25 @@ userauth_gssapi(struct ssh *ssh)
3030 static u_int mech = 0;
3031 OM_uint32 min; 3730 OM_uint32 min;
3032 int r, ok = 0; 3731 int r, ok = 0;
3732 gss_OID mech = NULL;
3033+ char *gss_host; 3733+ char *gss_host;
3034+ 3734+
3035+ if (options.gss_server_identity) 3735+ if (options.gss_server_identity)
3036+ gss_host = xstrdup(options.gss_server_identity); 3736+ gss_host = xstrdup(options.gss_server_identity);
3037+ else if (options.gss_trust_dns) 3737+ else if (options.gss_trust_dns)
3038+ gss_host = remote_hostname(active_state); 3738+ gss_host = remote_hostname(ssh);
3039+ else 3739+ else
3040+ gss_host = xstrdup(authctxt->host); 3740+ gss_host = xstrdup(authctxt->host);
3041 3741
3042 /* Try one GSSAPI method at a time, rather than sending them all at 3742 /* Try one GSSAPI method at a time, rather than sending them all at
3043 * once. */ 3743 * once. */
3044 3744
3045 if (gss_supported == NULL) 3745 if (authctxt->gss_supported_mechs == NULL)
3046- gss_indicate_mechs(&min, &gss_supported); 3746- gss_indicate_mechs(&min, &authctxt->gss_supported_mechs);
3047+ if (GSS_ERROR(gss_indicate_mechs(&min, &gss_supported))) { 3747+ if (GSS_ERROR(gss_indicate_mechs(&min,
3048+ gss_supported = NULL; 3748+ &authctxt->gss_supported_mechs))) {
3749+ authctxt->gss_supported_mechs = NULL;
3049+ free(gss_host); 3750+ free(gss_host);
3050+ return 0; 3751+ return 0;
3051+ } 3752+ }
3052 3753
3053 /* Check to see if the mechanism is usable before we offer it */ 3754 /* Check to see whether the mechanism is usable before we offer it */
3054 while (mech < gss_supported->count && !ok) { 3755 while (authctxt->mech_tried < authctxt->gss_supported_mechs->count &&
3756@@ -712,13 +793,15 @@ userauth_gssapi(struct ssh *ssh)
3757 elements[authctxt->mech_tried];
3055 /* My DER encoding requires length<128 */ 3758 /* My DER encoding requires length<128 */
3056 if (gss_supported->elements[mech].length < 128 && 3759 if (mech->length < 128 && ssh_gssapi_check_mechanism(&gssctxt,
3057 ssh_gssapi_check_mechanism(&gssctxt, 3760- mech, authctxt->host)) {
3058- &gss_supported->elements[mech], authctxt->host)) { 3761+ mech, gss_host, options.gss_client_identity)) {
3059+ &gss_supported->elements[mech], gss_host,
3060+ options.gss_client_identity)) {
3061 ok = 1; /* Mechanism works */ 3762 ok = 1; /* Mechanism works */
3062 } else { 3763 } else {
3063 mech++; 3764 authctxt->mech_tried++;
3064 } 3765 }
3065 } 3766 }
3066 3767
3067+ free(gss_host); 3768+ free(gss_host);
3068+ 3769+
3069 if (!ok) 3770 if (!ok || mech == NULL)
3070 return 0; 3771 return 0;
3071 3772
3072@@ -935,6 +1016,54 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh) 3773@@ -958,6 +1041,55 @@ input_gssapi_error(int type, u_int32_t plen, struct ssh *ssh)
3073 free(lang); 3774 free(lang);
3074 return r; 3775 return r;
3075 } 3776 }
3076+ 3777+
3077+int 3778+int
3078+userauth_gsskeyex(Authctxt *authctxt) 3779+userauth_gsskeyex(struct ssh *ssh)
3079+{ 3780+{
3080+ struct ssh *ssh = active_state; /* XXX */ 3781+ struct sshbuf *b = NULL;
3081+ struct sshbuf *b; 3782+ Authctxt *authctxt = ssh->authctxt;
3082+ gss_buffer_desc gssbuf; 3783+ gss_buffer_desc gssbuf;
3083+ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER; 3784+ gss_buffer_desc mic = GSS_C_EMPTY_BUFFER;
3084+ OM_uint32 ms; 3785+ OM_uint32 ms;
@@ -3089,12 +3790,13 @@ index 1675f3935..8c872a4fb 100644
3089+ return (0); 3790+ return (0);
3090+ 3791+
3091+ if (gss_kex_context == NULL) { 3792+ if (gss_kex_context == NULL) {
3092+ debug("No valid Key exchange context"); 3793+ debug("No valid Key exchange context");
3093+ return (0); 3794+ return (0);
3094+ } 3795+ }
3095+ 3796+
3096+ if ((b = sshbuf_new()) == NULL) 3797+ if ((b = sshbuf_new()) == NULL)
3097+ fatal("%s: sshbuf_new failed", __func__); 3798+ fatal("%s: sshbuf_new failed", __func__);
3799+
3098+ ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service, 3800+ ssh_gssapi_buildmic(b, authctxt->server_user, authctxt->service,
3099+ "gssapi-keyex"); 3801+ "gssapi-keyex");
3100+ 3802+
@@ -3123,9 +3825,9 @@ index 1675f3935..8c872a4fb 100644
3123+ 3825+
3124 #endif /* GSSAPI */ 3826 #endif /* GSSAPI */
3125 3827
3126 int 3828 static int
3127diff --git a/sshd.c b/sshd.c 3829diff --git a/sshd.c b/sshd.c
3128index ba26287ba..539a000fd 100644 3830index cbd3bce91..98680721b 100644
3129--- a/sshd.c 3831--- a/sshd.c
3130+++ b/sshd.c 3832+++ b/sshd.c
3131@@ -123,6 +123,10 @@ 3833@@ -123,6 +123,10 @@
@@ -3139,21 +3841,28 @@ index ba26287ba..539a000fd 100644
3139 /* Re-exec fds */ 3841 /* Re-exec fds */
3140 #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) 3842 #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
3141 #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) 3843 #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
3142@@ -1810,10 +1814,13 @@ main(int ac, char **av) 3844@@ -796,8 +800,8 @@ notify_hostkeys(struct ssh *ssh)
3845 }
3846 debug3("%s: sent %u hostkeys", __func__, nkeys);
3847 if (nkeys == 0)
3848- fatal("%s: no hostkeys", __func__);
3849- if ((r = sshpkt_send(ssh)) != 0)
3850+ debug3("%s: no hostkeys", __func__);
3851+ else if ((r = sshpkt_send(ssh)) != 0)
3852 sshpkt_fatal(ssh, r, "%s: send", __func__);
3853 sshbuf_free(buf);
3854 }
3855@@ -1769,7 +1773,8 @@ main(int ac, char **av)
3143 free(fp); 3856 free(fp);
3144 } 3857 }
3145 accumulate_host_timing_secret(cfg, NULL); 3858 accumulate_host_timing_secret(cfg, NULL);
3146+#ifndef GSSAPI 3859- if (!sensitive_data.have_ssh2_key) {
3147+ /* The GSSAPI key exchange can run without a host key */ 3860+ /* The GSSAPI key exchange can run without a host key */
3148 if (!sensitive_data.have_ssh2_key) { 3861+ if (!sensitive_data.have_ssh2_key && !options.gss_keyex) {
3149 logit("sshd: no hostkeys available -- exiting."); 3862 logit("sshd: no hostkeys available -- exiting.");
3150 exit(1); 3863 exit(1);
3151 } 3864 }
3152+#endif 3865@@ -2064,6 +2069,60 @@ main(int ac, char **av)
3153
3154 /*
3155 * Load certificates. They are stored in an array at identical
3156@@ -2104,6 +2111,60 @@ main(int ac, char **av)
3157 rdomain == NULL ? "" : "\""); 3866 rdomain == NULL ? "" : "\"");
3158 free(laddr); 3867 free(laddr);
3159 3868
@@ -3214,18 +3923,18 @@ index ba26287ba..539a000fd 100644
3214 /* 3923 /*
3215 * We don't want to listen forever unless the other side 3924 * We don't want to listen forever unless the other side
3216 * successfully authenticates itself. So we set up an alarm which is 3925 * successfully authenticates itself. So we set up an alarm which is
3217@@ -2287,6 +2348,48 @@ do_ssh2_kex(void) 3926@@ -2260,6 +2319,48 @@ do_ssh2_kex(struct ssh *ssh)
3218 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( 3927 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
3219 list_hostkey_types()); 3928 list_hostkey_types());
3220 3929
3221+#ifdef GSSAPI 3930+#if defined(GSSAPI) && defined(WITH_OPENSSL)
3222+ { 3931+ {
3223+ char *orig; 3932+ char *orig;
3224+ char *gss = NULL; 3933+ char *gss = NULL;
3225+ char *newstr = NULL; 3934+ char *newstr = NULL;
3226+ orig = myproposal[PROPOSAL_KEX_ALGS]; 3935+ orig = myproposal[PROPOSAL_KEX_ALGS];
3227+ 3936+
3228+ /* 3937+ /*
3229+ * If we don't have a host key, then there's no point advertising 3938+ * If we don't have a host key, then there's no point advertising
3230+ * the other key exchange algorithms 3939+ * the other key exchange algorithms
3231+ */ 3940+ */
@@ -3245,10 +3954,10 @@ index ba26287ba..539a000fd 100644
3245+ else if (orig) 3954+ else if (orig)
3246+ newstr = orig; 3955+ newstr = orig;
3247+ 3956+
3248+ /* 3957+ /*
3249+ * If we've got GSSAPI mechanisms, then we've got the 'null' host 3958+ * If we've got GSSAPI mechanisms, then we've got the 'null' host
3250+ * key alg, but we can't tell people about it unless its the only 3959+ * key alg, but we can't tell people about it unless its the only
3251+ * host key algorithm we support 3960+ * host key algorithm we support
3252+ */ 3961+ */
3253+ if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0) 3962+ if (gss && (strlen(myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS])) == 0)
3254+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null"; 3963+ myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = "null";
@@ -3261,22 +3970,28 @@ index ba26287ba..539a000fd 100644
3261+#endif 3970+#endif
3262+ 3971+
3263 /* start key exchange */ 3972 /* start key exchange */
3264 if ((r = kex_setup(active_state, myproposal)) != 0) 3973 if ((r = kex_setup(ssh, myproposal)) != 0)
3265 fatal("kex_setup: %s", ssh_err(r)); 3974 fatal("kex_setup: %s", ssh_err(r));
3266@@ -2304,6 +2407,13 @@ do_ssh2_kex(void) 3975@@ -2275,7 +2376,18 @@ do_ssh2_kex(struct ssh *ssh)
3976 # ifdef OPENSSL_HAS_ECC
3977 kex->kex[KEX_ECDH_SHA2] = kex_gen_server;
3267 # endif 3978 # endif
3268 #endif 3979-#endif
3269 kex->kex[KEX_C25519_SHA256] = kexc25519_server; 3980+# ifdef GSSAPI
3270+#ifdef GSSAPI
3271+ if (options.gss_keyex) { 3981+ if (options.gss_keyex) {
3272+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server; 3982+ kex->kex[KEX_GSS_GRP1_SHA1] = kexgss_server;
3273+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server; 3983+ kex->kex[KEX_GSS_GRP14_SHA1] = kexgss_server;
3274+ kex->kex[KEX_GSS_GEX_SHA1] = kexgss_server; 3984+ kex->kex[KEX_GSS_GRP14_SHA256] = kexgss_server;
3985+ kex->kex[KEX_GSS_GRP16_SHA512] = kexgss_server;
3986+ kex->kex[KEX_GSS_GEX_SHA1] = kexgssgex_server;
3987+ kex->kex[KEX_GSS_NISTP256_SHA256] = kexgss_server;
3988+ kex->kex[KEX_GSS_C25519_SHA256] = kexgss_server;
3275+ } 3989+ }
3276+#endif 3990+# endif
3277 kex->server = 1; 3991+#endif /* WITH_OPENSSL */
3278 kex->client_version_string=client_version_string; 3992 kex->kex[KEX_C25519_SHA256] = kex_gen_server;
3279 kex->server_version_string=server_version_string; 3993 kex->kex[KEX_KEM_SNTRUP4591761X25519_SHA512] = kex_gen_server;
3994 kex->load_host_public_key=&get_hostkey_public_by_type;
3280diff --git a/sshd_config b/sshd_config 3995diff --git a/sshd_config b/sshd_config
3281index 19b7c91a1..2c48105f8 100644 3996index 19b7c91a1..2c48105f8 100644
3282--- a/sshd_config 3997--- a/sshd_config
@@ -3291,35 +4006,55 @@ index 19b7c91a1..2c48105f8 100644
3291 # Set this to 'yes' to enable PAM authentication, account processing, 4006 # Set this to 'yes' to enable PAM authentication, account processing,
3292 # and session processing. If this is enabled, PAM authentication will 4007 # and session processing. If this is enabled, PAM authentication will
3293diff --git a/sshd_config.5 b/sshd_config.5 4008diff --git a/sshd_config.5 b/sshd_config.5
3294index c6484370b..985eef5a2 100644 4009index b224f2929..2baa6622b 100644
3295--- a/sshd_config.5 4010--- a/sshd_config.5
3296+++ b/sshd_config.5 4011+++ b/sshd_config.5
3297@@ -648,6 +648,11 @@ The default is 4012@@ -653,6 +653,11 @@ Specifies whether to automatically destroy the user's credentials cache
3298 Specifies whether user authentication based on GSSAPI is allowed. 4013 on logout.
3299 The default is 4014 The default is
3300 .Cm no . 4015 .Cm yes .
3301+.It Cm GSSAPIKeyExchange 4016+.It Cm GSSAPIKeyExchange
3302+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange 4017+Specifies whether key exchange based on GSSAPI is allowed. GSSAPI key exchange
3303+doesn't rely on ssh keys to verify host identity. 4018+doesn't rely on ssh keys to verify host identity.
3304+The default is 4019+The default is
3305+.Cm no . 4020+.Cm no .
3306 .It Cm GSSAPICleanupCredentials 4021 .It Cm GSSAPIStrictAcceptorCheck
3307 Specifies whether to automatically destroy the user's credentials cache 4022 Determines whether to be strict about the identity of the GSSAPI acceptor
3308 on logout. 4023 a client authenticates against.
3309@@ -667,6 +672,11 @@ machine's default store. 4024@@ -667,6 +672,31 @@ machine's default store.
3310 This facility is provided to assist with operation on multi homed machines. 4025 This facility is provided to assist with operation on multi homed machines.
3311 The default is 4026 The default is
3312 .Cm yes . 4027 .Cm yes .
3313+.It Cm GSSAPIStoreCredentialsOnRekey 4028+.It Cm GSSAPIStoreCredentialsOnRekey
3314+Controls whether the user's GSSAPI credentials should be updated following a 4029+Controls whether the user's GSSAPI credentials should be updated following a
3315+successful connection rekeying. This option can be used to accepted renewed 4030+successful connection rekeying. This option can be used to accepted renewed
3316+or updated credentials from a compatible client. The default is 4031+or updated credentials from a compatible client. The default is
3317+.Cm no . 4032+.Dq no .
4033+.Pp
4034+For this to work
4035+.Cm GSSAPIKeyExchange
4036+needs to be enabled in the server and also used by the client.
4037+.It Cm GSSAPIKexAlgorithms
4038+The list of key exchange algorithms that are accepted by GSSAPI
4039+key exchange. Possible values are
4040+.Bd -literal -offset 3n
4041+gss-gex-sha1-,
4042+gss-group1-sha1-,
4043+gss-group14-sha1-,
4044+gss-group14-sha256-,
4045+gss-group16-sha512-,
4046+gss-nistp256-sha256-,
4047+gss-curve25519-sha256-
4048+.Ed
4049+.Pp
4050+The default is
4051+.Dq gss-gex-sha1-,gss-group14-sha1- .
4052+This option only applies to protocol version 2 connections using GSSAPI.
3318 .It Cm HostbasedAcceptedKeyTypes 4053 .It Cm HostbasedAcceptedKeyTypes
3319 Specifies the key types that will be accepted for hostbased authentication 4054 Specifies the key types that will be accepted for hostbased authentication
3320 as a list of comma-separated patterns. 4055 as a list of comma-separated patterns.
3321diff --git a/sshkey.c b/sshkey.c 4056diff --git a/sshkey.c b/sshkey.c
3322index 6555c5ef8..a85c185fc 100644 4057index ad1957762..789cd61ef 100644
3323--- a/sshkey.c 4058--- a/sshkey.c
3324+++ b/sshkey.c 4059+++ b/sshkey.c
3325@@ -135,6 +135,7 @@ static const struct keytype keytypes[] = { 4060@@ -135,6 +135,7 @@ static const struct keytype keytypes[] = {
@@ -3340,10 +4075,10 @@ index 6555c5ef8..a85c185fc 100644
3340 if (!include_sigonly && kt->sigonly) 4075 if (!include_sigonly && kt->sigonly)
3341 continue; 4076 continue;
3342diff --git a/sshkey.h b/sshkey.h 4077diff --git a/sshkey.h b/sshkey.h
3343index f6a007fdf..f54deb0c0 100644 4078index a91e60436..c11106c93 100644
3344--- a/sshkey.h 4079--- a/sshkey.h
3345+++ b/sshkey.h 4080+++ b/sshkey.h
3346@@ -64,6 +64,7 @@ enum sshkey_types { 4081@@ -65,6 +65,7 @@ enum sshkey_types {
3347 KEY_ED25519_CERT, 4082 KEY_ED25519_CERT,
3348 KEY_XMSS, 4083 KEY_XMSS,
3349 KEY_XMSS_CERT, 4084 KEY_XMSS_CERT,
diff --git a/debian/patches/have-progressmeter-force-update-at-beginning-and-end-transfer.patch b/debian/patches/have-progressmeter-force-update-at-beginning-and-end-transfer.patch
deleted file mode 100644
index 767dbf2b5..000000000
--- a/debian/patches/have-progressmeter-force-update-at-beginning-and-end-transfer.patch
+++ /dev/null
@@ -1,120 +0,0 @@
1From 2a8f710447442e9a03e71c022859112ec2d77d17 Mon Sep 17 00:00:00 2001
2From: "dtucker@openbsd.org" <dtucker@openbsd.org>
3Date: Thu, 24 Jan 2019 16:52:17 +0000
4Subject: upstream: Have progressmeter force an update at the beginning and
5
6end of each transfer. Fixes the problem recently introduces where very quick
7transfers do not display the progressmeter at all. Spotted by naddy@
8
9OpenBSD-Commit-ID: 68dc46c259e8fdd4f5db3ec2a130f8e4590a7a9a
10
11Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=bdc6c63c80b55bcbaa66b5fde31c1cb1d09a41eb
12Last-Update: 2019-02-08
13
14Patch-Name: have-progressmeter-force-update-at-beginning-and-end-transfer.patch
15---
16 progressmeter.c | 13 +++++--------
17 progressmeter.h | 4 ++--
18 scp.c | 2 +-
19 sftp-client.c | 2 +-
20 4 files changed, 9 insertions(+), 12 deletions(-)
21
22diff --git a/progressmeter.c b/progressmeter.c
23index add462dde..e385c1254 100644
24--- a/progressmeter.c
25+++ b/progressmeter.c
26@@ -1,4 +1,4 @@
27-/* $OpenBSD: progressmeter.c,v 1.46 2019/01/23 08:01:46 dtucker Exp $ */
28+/* $OpenBSD: progressmeter.c,v 1.47 2019/01/24 16:52:17 dtucker Exp $ */
29 /*
30 * Copyright (c) 2003 Nils Nordman. All rights reserved.
31 *
32@@ -59,9 +59,6 @@ static void format_rate(char *, int, off_t);
33 static void sig_winch(int);
34 static void setscreensize(void);
35
36-/* updates the progressmeter to reflect the current state of the transfer */
37-void refresh_progress_meter(void);
38-
39 /* signal handler for updating the progress meter */
40 static void sig_alarm(int);
41
42@@ -120,7 +117,7 @@ format_size(char *buf, int size, off_t bytes)
43 }
44
45 void
46-refresh_progress_meter(void)
47+refresh_progress_meter(int force_update)
48 {
49 char buf[MAX_WINSIZE + 1];
50 off_t transferred;
51@@ -131,7 +128,7 @@ refresh_progress_meter(void)
52 int hours, minutes, seconds;
53 int file_len;
54
55- if ((!alarm_fired && !win_resized) || !can_output())
56+ if ((!force_update && !alarm_fired && !win_resized) || !can_output())
57 return;
58 alarm_fired = 0;
59
60@@ -254,7 +251,7 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr)
61 bytes_per_second = 0;
62
63 setscreensize();
64- refresh_progress_meter();
65+ refresh_progress_meter(1);
66
67 signal(SIGALRM, sig_alarm);
68 signal(SIGWINCH, sig_winch);
69@@ -271,7 +268,7 @@ stop_progress_meter(void)
70
71 /* Ensure we complete the progress */
72 if (cur_pos != end_pos)
73- refresh_progress_meter();
74+ refresh_progress_meter(1);
75
76 atomicio(vwrite, STDOUT_FILENO, "\n", 1);
77 }
78diff --git a/progressmeter.h b/progressmeter.h
79index 8f6678060..1703ea75b 100644
80--- a/progressmeter.h
81+++ b/progressmeter.h
82@@ -1,4 +1,4 @@
83-/* $OpenBSD: progressmeter.h,v 1.4 2019/01/23 08:01:46 dtucker Exp $ */
84+/* $OpenBSD: progressmeter.h,v 1.5 2019/01/24 16:52:17 dtucker Exp $ */
85 /*
86 * Copyright (c) 2002 Nils Nordman. All rights reserved.
87 *
88@@ -24,5 +24,5 @@
89 */
90
91 void start_progress_meter(const char *, off_t, off_t *);
92-void refresh_progress_meter(void);
93+void refresh_progress_meter(int);
94 void stop_progress_meter(void);
95diff --git a/scp.c b/scp.c
96index 80308573c..1971c80cd 100644
97--- a/scp.c
98+++ b/scp.c
99@@ -593,7 +593,7 @@ scpio(void *_cnt, size_t s)
100 off_t *cnt = (off_t *)_cnt;
101
102 *cnt += s;
103- refresh_progress_meter();
104+ refresh_progress_meter(0);
105 if (limit_kbps > 0)
106 bandwidth_limit(&bwlimit, s);
107 return 0;
108diff --git a/sftp-client.c b/sftp-client.c
109index 2bc698f86..cf2887a40 100644
110--- a/sftp-client.c
111+++ b/sftp-client.c
112@@ -101,7 +101,7 @@ sftpio(void *_bwlimit, size_t amount)
113 {
114 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
115
116- refresh_progress_meter();
117+ refresh_progress_meter(0);
118 if (bwlimit != NULL)
119 bandwidth_limit(bwlimit, amount);
120 return 0;
diff --git a/debian/patches/keepalive-extensions.patch b/debian/patches/keepalive-extensions.patch
index 4207302c3..fbfe6a1fb 100644
--- a/debian/patches/keepalive-extensions.patch
+++ b/debian/patches/keepalive-extensions.patch
@@ -1,4 +1,4 @@
1From 7ba31c6ff505278fb9f33b695605ca3a093caba2 Mon Sep 17 00:00:00 2001 1From 4d8dd12bab7bbc954815d7953a0c86ce1687bd34 Mon Sep 17 00:00:00 2001
2From: Richard Kettlewell <rjk@greenend.org.uk> 2From: Richard Kettlewell <rjk@greenend.org.uk>
3Date: Sun, 9 Feb 2014 16:09:52 +0000 3Date: Sun, 9 Feb 2014 16:09:52 +0000
4Subject: Various keepalive extensions 4Subject: Various keepalive extensions
@@ -26,10 +26,10 @@ Patch-Name: keepalive-extensions.patch
26 3 files changed, 34 insertions(+), 4 deletions(-) 26 3 files changed, 34 insertions(+), 4 deletions(-)
27 27
28diff --git a/readconf.c b/readconf.c 28diff --git a/readconf.c b/readconf.c
29index 5e655e924..052d4b1ac 100644 29index 29f3bd98d..3d0b6ff90 100644
30--- a/readconf.c 30--- a/readconf.c
31+++ b/readconf.c 31+++ b/readconf.c
32@@ -175,6 +175,7 @@ typedef enum { 32@@ -177,6 +177,7 @@ typedef enum {
33 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys, 33 oStreamLocalBindMask, oStreamLocalBindUnlink, oRevokedHostKeys,
34 oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes, 34 oFingerprintHash, oUpdateHostkeys, oHostbasedKeyTypes,
35 oPubkeyAcceptedKeyTypes, oCASignatureAlgorithms, oProxyJump, 35 oPubkeyAcceptedKeyTypes, oCASignatureAlgorithms, oProxyJump,
@@ -37,7 +37,7 @@ index 5e655e924..052d4b1ac 100644
37 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported 37 oIgnore, oIgnoredUnknownOption, oDeprecated, oUnsupported
38 } OpCodes; 38 } OpCodes;
39 39
40@@ -322,6 +323,8 @@ static struct { 40@@ -326,6 +327,8 @@ static struct {
41 { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes }, 41 { "pubkeyacceptedkeytypes", oPubkeyAcceptedKeyTypes },
42 { "ignoreunknown", oIgnoreUnknown }, 42 { "ignoreunknown", oIgnoreUnknown },
43 { "proxyjump", oProxyJump }, 43 { "proxyjump", oProxyJump },
@@ -46,7 +46,7 @@ index 5e655e924..052d4b1ac 100644
46 46
47 { NULL, oBadOption } 47 { NULL, oBadOption }
48 }; 48 };
49@@ -1415,6 +1418,8 @@ parse_keytypes: 49@@ -1440,6 +1443,8 @@ parse_keytypes:
50 goto parse_flag; 50 goto parse_flag;
51 51
52 case oServerAliveInterval: 52 case oServerAliveInterval:
@@ -55,7 +55,7 @@ index 5e655e924..052d4b1ac 100644
55 intptr = &options->server_alive_interval; 55 intptr = &options->server_alive_interval;
56 goto parse_time; 56 goto parse_time;
57 57
58@@ -2101,8 +2106,13 @@ fill_default_options(Options * options) 58@@ -2133,8 +2138,13 @@ fill_default_options(Options * options)
59 options->rekey_interval = 0; 59 options->rekey_interval = 0;
60 if (options->verify_host_key_dns == -1) 60 if (options->verify_host_key_dns == -1)
61 options->verify_host_key_dns = 0; 61 options->verify_host_key_dns = 0;
@@ -72,10 +72,10 @@ index 5e655e924..052d4b1ac 100644
72 options->server_alive_count_max = 3; 72 options->server_alive_count_max = 3;
73 if (options->control_master == -1) 73 if (options->control_master == -1)
74diff --git a/ssh_config.5 b/ssh_config.5 74diff --git a/ssh_config.5 b/ssh_config.5
75index 16c79368a..54e143c93 100644 75index c3c8b274a..250c92d04 100644
76--- a/ssh_config.5 76--- a/ssh_config.5
77+++ b/ssh_config.5 77+++ b/ssh_config.5
78@@ -247,8 +247,12 @@ Valid arguments are 78@@ -265,8 +265,12 @@ Valid arguments are
79 If set to 79 If set to
80 .Cm yes , 80 .Cm yes ,
81 passphrase/password querying will be disabled. 81 passphrase/password querying will be disabled.
@@ -89,7 +89,7 @@ index 16c79368a..54e143c93 100644
89 The argument must be 89 The argument must be
90 .Cm yes 90 .Cm yes
91 or 91 or
92@@ -1485,7 +1489,14 @@ from the server, 92@@ -1535,7 +1539,14 @@ from the server,
93 will send a message through the encrypted 93 will send a message through the encrypted
94 channel to request a response from the server. 94 channel to request a response from the server.
95 The default 95 The default
@@ -105,7 +105,7 @@ index 16c79368a..54e143c93 100644
105 .It Cm SetEnv 105 .It Cm SetEnv
106 Directly specify one or more environment variables and their contents to 106 Directly specify one or more environment variables and their contents to
107 be sent to the server. 107 be sent to the server.
108@@ -1565,6 +1576,12 @@ Specifies whether the system should send TCP keepalive messages to the 108@@ -1615,6 +1626,12 @@ Specifies whether the system should send TCP keepalive messages to the
109 other side. 109 other side.
110 If they are sent, death of the connection or crash of one 110 If they are sent, death of the connection or crash of one
111 of the machines will be properly noticed. 111 of the machines will be properly noticed.
@@ -119,10 +119,10 @@ index 16c79368a..54e143c93 100644
119 connections will die if the route is down temporarily, and some people 119 connections will die if the route is down temporarily, and some people
120 find it annoying. 120 find it annoying.
121diff --git a/sshd_config.5 b/sshd_config.5 121diff --git a/sshd_config.5 b/sshd_config.5
122index 985eef5a2..e7e55dd71 100644 122index 2baa6622b..2ef671d1b 100644
123--- a/sshd_config.5 123--- a/sshd_config.5
124+++ b/sshd_config.5 124+++ b/sshd_config.5
125@@ -1577,6 +1577,9 @@ This avoids infinitely hanging sessions. 125@@ -1597,6 +1597,9 @@ This avoids infinitely hanging sessions.
126 .Pp 126 .Pp
127 To disable TCP keepalive messages, the value should be set to 127 To disable TCP keepalive messages, the value should be set to
128 .Cm no . 128 .Cm no .
diff --git a/debian/patches/mention-ssh-keygen-on-keychange.patch b/debian/patches/mention-ssh-keygen-on-keychange.patch
index 75ed46db7..21e8d7947 100644
--- a/debian/patches/mention-ssh-keygen-on-keychange.patch
+++ b/debian/patches/mention-ssh-keygen-on-keychange.patch
@@ -1,4 +1,4 @@
1From bb8bb2621914ad600202e38d5b9b4f4544b191e5 Mon Sep 17 00:00:00 2001 1From 15b7cc25dea4efdef7fdd129d0e3d1a091afd67b Mon Sep 17 00:00:00 2001
2From: Scott Moser <smoser@ubuntu.com> 2From: Scott Moser <smoser@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:10:03 +0000 3Date: Sun, 9 Feb 2014 16:10:03 +0000
4Subject: Mention ssh-keygen in ssh fingerprint changed warning 4Subject: Mention ssh-keygen in ssh fingerprint changed warning
@@ -14,10 +14,10 @@ Patch-Name: mention-ssh-keygen-on-keychange.patch
14 1 file changed, 8 insertions(+), 1 deletion(-) 14 1 file changed, 8 insertions(+), 1 deletion(-)
15 15
16diff --git a/sshconnect.c b/sshconnect.c 16diff --git a/sshconnect.c b/sshconnect.c
17index 700ea6c3c..158e8146f 100644 17index 103d84e38..0b6f6af4b 100644
18--- a/sshconnect.c 18--- a/sshconnect.c
19+++ b/sshconnect.c 19+++ b/sshconnect.c
20@@ -1121,9 +1121,13 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, 20@@ -986,9 +986,13 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
21 error("%s. This could either mean that", key_msg); 21 error("%s. This could either mean that", key_msg);
22 error("DNS SPOOFING is happening or the IP address for the host"); 22 error("DNS SPOOFING is happening or the IP address for the host");
23 error("and its host key have changed at the same time."); 23 error("and its host key have changed at the same time.");
@@ -32,7 +32,7 @@ index 700ea6c3c..158e8146f 100644
32 } 32 }
33 /* The host key has changed. */ 33 /* The host key has changed. */
34 warn_changed_key(host_key); 34 warn_changed_key(host_key);
35@@ -1132,6 +1136,9 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, 35@@ -997,6 +1001,9 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
36 error("Offending %s key in %s:%lu", 36 error("Offending %s key in %s:%lu",
37 sshkey_type(host_found->key), 37 sshkey_type(host_found->key),
38 host_found->file, host_found->line); 38 host_found->file, host_found->line);
diff --git a/debian/patches/no-openssl-version-status.patch b/debian/patches/no-openssl-version-status.patch
index 3b2e05e58..dcc672726 100644
--- a/debian/patches/no-openssl-version-status.patch
+++ b/debian/patches/no-openssl-version-status.patch
@@ -1,4 +1,4 @@
1From 690051b3aa4ff72af57e4a82d640858357eef820 Mon Sep 17 00:00:00 2001 1From 1f61e987ccec2a2af15044196c1a6730959ead98 Mon Sep 17 00:00:00 2001
2From: Kurt Roeckx <kurt@roeckx.be> 2From: Kurt Roeckx <kurt@roeckx.be>
3Date: Sun, 9 Feb 2014 16:10:14 +0000 3Date: Sun, 9 Feb 2014 16:10:14 +0000
4Subject: Don't check the status field of the OpenSSL version 4Subject: Don't check the status field of the OpenSSL version
@@ -23,7 +23,7 @@ Patch-Name: no-openssl-version-status.patch
23 2 files changed, 4 insertions(+), 3 deletions(-) 23 2 files changed, 4 insertions(+), 3 deletions(-)
24 24
25diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c 25diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c
26index 8b4a36274..ea0b0c9fb 100644 26index a37ca61bf..c1749210d 100644
27--- a/openbsd-compat/openssl-compat.c 27--- a/openbsd-compat/openssl-compat.c
28+++ b/openbsd-compat/openssl-compat.c 28+++ b/openbsd-compat/openssl-compat.c
29@@ -34,7 +34,7 @@ 29@@ -34,7 +34,7 @@
diff --git a/debian/patches/openbsd-docs.patch b/debian/patches/openbsd-docs.patch
index cdb905b2e..e46967c72 100644
--- a/debian/patches/openbsd-docs.patch
+++ b/debian/patches/openbsd-docs.patch
@@ -1,4 +1,4 @@
1From 96c85e746d4f94c7d2748a200e5817ad8a987918 Mon Sep 17 00:00:00 2001 1From 47beec5c944ea9add7d267110fc9dcf15e7b8932 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:09 +0000 3Date: Sun, 9 Feb 2014 16:10:09 +0000
4Subject: Adjust various OpenBSD-specific references in manual pages 4Subject: Adjust various OpenBSD-specific references in manual pages
@@ -44,10 +44,10 @@ index ef0de0850..149846c8c 100644
44 .Sh SEE ALSO 44 .Sh SEE ALSO
45 .Xr ssh-keygen 1 , 45 .Xr ssh-keygen 1 ,
46diff --git a/ssh-keygen.1 b/ssh-keygen.1 46diff --git a/ssh-keygen.1 b/ssh-keygen.1
47index bfa2eb5f3..da6b5ed76 100644 47index 124456577..9b877b860 100644
48--- a/ssh-keygen.1 48--- a/ssh-keygen.1
49+++ b/ssh-keygen.1 49+++ b/ssh-keygen.1
50@@ -176,9 +176,7 @@ key in 50@@ -178,9 +178,7 @@ key in
51 .Pa ~/.ssh/id_ed25519 51 .Pa ~/.ssh/id_ed25519
52 or 52 or
53 .Pa ~/.ssh/id_rsa . 53 .Pa ~/.ssh/id_rsa .
@@ -58,7 +58,7 @@ index bfa2eb5f3..da6b5ed76 100644
58 .Pp 58 .Pp
59 Normally this program generates the key and asks for a file in which 59 Normally this program generates the key and asks for a file in which
60 to store the private key. 60 to store the private key.
61@@ -229,9 +227,7 @@ If 61@@ -243,9 +241,7 @@ If
62 .Fl f 62 .Fl f
63 has also been specified, its argument is used as a prefix to the 63 has also been specified, its argument is used as a prefix to the
64 default path for the resulting host key files. 64 default path for the resulting host key files.
@@ -69,7 +69,7 @@ index bfa2eb5f3..da6b5ed76 100644
69 .It Fl a Ar rounds 69 .It Fl a Ar rounds
70 When saving a private key this option specifies the number of KDF 70 When saving a private key this option specifies the number of KDF
71 (key derivation function) rounds used. 71 (key derivation function) rounds used.
72@@ -677,7 +673,7 @@ option. 72@@ -703,7 +699,7 @@ option.
73 Valid generator values are 2, 3, and 5. 73 Valid generator values are 2, 3, and 5.
74 .Pp 74 .Pp
75 Screened DH groups may be installed in 75 Screened DH groups may be installed in
@@ -78,7 +78,7 @@ index bfa2eb5f3..da6b5ed76 100644
78 It is important that this file contains moduli of a range of bit lengths and 78 It is important that this file contains moduli of a range of bit lengths and
79 that both ends of a connection share common moduli. 79 that both ends of a connection share common moduli.
80 .Sh CERTIFICATES 80 .Sh CERTIFICATES
81@@ -877,7 +873,7 @@ on all machines 81@@ -903,7 +899,7 @@ on all machines
82 where the user wishes to log in using public key authentication. 82 where the user wishes to log in using public key authentication.
83 There is no need to keep the contents of this file secret. 83 There is no need to keep the contents of this file secret.
84 .Pp 84 .Pp
@@ -88,10 +88,10 @@ index bfa2eb5f3..da6b5ed76 100644
88 The file format is described in 88 The file format is described in
89 .Xr moduli 5 . 89 .Xr moduli 5 .
90diff --git a/ssh.1 b/ssh.1 90diff --git a/ssh.1 b/ssh.1
91index 81f29af43..5dfad6daa 100644 91index 64ead5f57..e4aeae7b4 100644
92--- a/ssh.1 92--- a/ssh.1
93+++ b/ssh.1 93+++ b/ssh.1
94@@ -860,6 +860,10 @@ implements public key authentication protocol automatically, 94@@ -873,6 +873,10 @@ implements public key authentication protocol automatically,
95 using one of the DSA, ECDSA, Ed25519 or RSA algorithms. 95 using one of the DSA, ECDSA, Ed25519 or RSA algorithms.
96 The HISTORY section of 96 The HISTORY section of
97 .Xr ssl 8 97 .Xr ssl 8
@@ -133,7 +133,7 @@ index 57a7fd66b..4abc01d66 100644
133 .Xr sshd_config 5 , 133 .Xr sshd_config 5 ,
134 .Xr inetd 8 , 134 .Xr inetd 8 ,
135diff --git a/sshd_config.5 b/sshd_config.5 135diff --git a/sshd_config.5 b/sshd_config.5
136index 37e6be38f..23f71fd1d 100644 136index addea54a0..f995e4ab0 100644
137--- a/sshd_config.5 137--- a/sshd_config.5
138+++ b/sshd_config.5 138+++ b/sshd_config.5
139@@ -395,8 +395,7 @@ Certificates signed using other algorithms will not be accepted for 139@@ -395,8 +395,7 @@ Certificates signed using other algorithms will not be accepted for
diff --git a/debian/patches/package-versioning.patch b/debian/patches/package-versioning.patch
index 809c78846..0d2be82dc 100644
--- a/debian/patches/package-versioning.patch
+++ b/debian/patches/package-versioning.patch
@@ -1,4 +1,4 @@
1From b258a00bedcf29200b394c671c6deb1e53157f32 Mon Sep 17 00:00:00 2001 1From 85e700a732e9a308eeee67f5a284e19fd6befbb8 Mon Sep 17 00:00:00 2001
2From: Matthew Vernon <matthew@debian.org> 2From: Matthew Vernon <matthew@debian.org>
3Date: Sun, 9 Feb 2014 16:10:05 +0000 3Date: Sun, 9 Feb 2014 16:10:05 +0000
4Subject: Include the Debian version in our identification 4Subject: Include the Debian version in our identification
@@ -9,47 +9,33 @@ generally just try attacks rather than bothering to scan for
9vulnerable-looking version strings. (However, see debian-banner.patch.) 9vulnerable-looking version strings. (However, see debian-banner.patch.)
10 10
11Forwarded: not-needed 11Forwarded: not-needed
12Last-Update: 2017-10-04 12Last-Update: 2019-06-05
13 13
14Patch-Name: package-versioning.patch 14Patch-Name: package-versioning.patch
15--- 15---
16 sshconnect.c | 2 +- 16 kex.c | 2 +-
17 sshd.c | 2 +- 17 version.h | 7 ++++++-
18 version.h | 7 ++++++- 18 2 files changed, 7 insertions(+), 2 deletions(-)
19 3 files changed, 8 insertions(+), 3 deletions(-)
20 19
21diff --git a/sshconnect.c b/sshconnect.c 20diff --git a/kex.c b/kex.c
22index 158e8146f..b9418e277 100644 21index a2a4794e8..be354206d 100644
23--- a/sshconnect.c 22--- a/kex.c
24+++ b/sshconnect.c 23+++ b/kex.c
25@@ -609,7 +609,7 @@ send_client_banner(int connection_out, int minor1) 24@@ -1186,7 +1186,7 @@ kex_exchange_identification(struct ssh *ssh, int timeout_ms,
26 { 25 if (version_addendum != NULL && *version_addendum == '\0')
27 /* Send our own protocol version identification. */ 26 version_addendum = NULL;
28 xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", 27 if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n",
29- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION); 28- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
30+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_RELEASE); 29+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_RELEASE,
31 if (atomicio(vwrite, connection_out, client_version_string, 30 version_addendum == NULL ? "" : " ",
32 strlen(client_version_string)) != strlen(client_version_string)) 31 version_addendum == NULL ? "" : version_addendum)) != 0) {
33 fatal("write: %.100s", strerror(errno)); 32 error("%s: sshbuf_putf: %s", __func__, ssh_err(r));
34diff --git a/sshd.c b/sshd.c
35index 2bc6679e5..9481272fc 100644
36--- a/sshd.c
37+++ b/sshd.c
38@@ -384,7 +384,7 @@ sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out)
39 char remote_version[256]; /* Must be at least as big as buf. */
40
41 xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n",
42- PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
43+ PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_RELEASE,
44 *options.version_addendum == '\0' ? "" : " ",
45 options.version_addendum);
46
47diff --git a/version.h b/version.h 33diff --git a/version.h b/version.h
48index 422dfbc3a..5e1ce0426 100644 34index 806ead9a6..599c859e6 100644
49--- a/version.h 35--- a/version.h
50+++ b/version.h 36+++ b/version.h
51@@ -3,4 +3,9 @@ 37@@ -3,4 +3,9 @@
52 #define SSH_VERSION "OpenSSH_7.9" 38 #define SSH_VERSION "OpenSSH_8.0"
53 39
54 #define SSH_PORTABLE "p1" 40 #define SSH_PORTABLE "p1"
55-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE 41-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE
diff --git a/debian/patches/request-rsa-sha2-cert-signatures.patch b/debian/patches/request-rsa-sha2-cert-signatures.patch
deleted file mode 100644
index 2c876be31..000000000
--- a/debian/patches/request-rsa-sha2-cert-signatures.patch
+++ /dev/null
@@ -1,39 +0,0 @@
1From d94226d4fcefbc398c5583e12b5d07ca33884ba4 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Thu, 27 Dec 2018 23:02:11 +0000
4Subject: upstream: Request RSA-SHA2 signatures for
5
6rsa-sha2-{256|512}-cert-v01@openssh.com cert algorithms; ok markus@
7
8OpenBSD-Commit-ID: afc6f7ca216ccd821656d1c911d2a3deed685033
9
10Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=f429c1b2ef631f2855e51a790cf71761d752bbca
11Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=2944
12Bug-Debian: https://bugs.debian.org/923419
13Last-Update: 2019-02-28
14
15Patch-Name: request-rsa-sha2-cert-signatures.patch
16---
17 authfd.c | 8 +++++---
18 1 file changed, 5 insertions(+), 3 deletions(-)
19
20diff --git a/authfd.c b/authfd.c
21index ecdd869ab..62cbf8c19 100644
22--- a/authfd.c
23+++ b/authfd.c
24@@ -327,10 +327,12 @@ ssh_free_identitylist(struct ssh_identitylist *idl)
25 static u_int
26 agent_encode_alg(const struct sshkey *key, const char *alg)
27 {
28- if (alg != NULL && key->type == KEY_RSA) {
29- if (strcmp(alg, "rsa-sha2-256") == 0)
30+ if (alg != NULL && sshkey_type_plain(key->type) == KEY_RSA) {
31+ if (strcmp(alg, "rsa-sha2-256") == 0 ||
32+ strcmp(alg, "rsa-sha2-256-cert-v01@openssh.com") == 0)
33 return SSH_AGENT_RSA_SHA2_256;
34- else if (strcmp(alg, "rsa-sha2-512") == 0)
35+ if (strcmp(alg, "rsa-sha2-512") == 0 ||
36+ strcmp(alg, "rsa-sha2-512-cert-v01@openssh.com") == 0)
37 return SSH_AGENT_RSA_SHA2_512;
38 }
39 return 0;
diff --git a/debian/patches/restore-authorized_keys2.patch b/debian/patches/restore-authorized_keys2.patch
index fcb1ac7e3..574923e1c 100644
--- a/debian/patches/restore-authorized_keys2.patch
+++ b/debian/patches/restore-authorized_keys2.patch
@@ -1,4 +1,4 @@
1From cebe4b82b280810172877a7f3d489c506c9a0691 Mon Sep 17 00:00:00 2001 1From 1af6147744892b18e2239c085abe87f5408cbaae Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 5 Mar 2017 02:02:11 +0000 3Date: Sun, 5 Mar 2017 02:02:11 +0000
4Subject: Restore reading authorized_keys2 by default 4Subject: Restore reading authorized_keys2 by default
diff --git a/debian/patches/restore-tcp-wrappers.patch b/debian/patches/restore-tcp-wrappers.patch
index fdc6cf18a..0472ea7d0 100644
--- a/debian/patches/restore-tcp-wrappers.patch
+++ b/debian/patches/restore-tcp-wrappers.patch
@@ -1,4 +1,4 @@
1From 389e16d0109d8c49a761cd7c267438b05c9ab984 Mon Sep 17 00:00:00 2001 1From 0f9f44654708e4fde2f52c52f717d061b5e458fa Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Tue, 7 Oct 2014 13:22:41 +0100 3Date: Tue, 7 Oct 2014 13:22:41 +0100
4Subject: Restore TCP wrappers support 4Subject: Restore TCP wrappers support
@@ -18,7 +18,7 @@ but it at least probably doesn't involve dropping this feature shortly
18before a freeze. 18before a freeze.
19 19
20Forwarded: not-needed 20Forwarded: not-needed
21Last-Update: 2018-08-24 21Last-Update: 2019-06-05
22 22
23Patch-Name: restore-tcp-wrappers.patch 23Patch-Name: restore-tcp-wrappers.patch
24--- 24---
@@ -28,10 +28,10 @@ Patch-Name: restore-tcp-wrappers.patch
28 3 files changed, 89 insertions(+) 28 3 files changed, 89 insertions(+)
29 29
30diff --git a/configure.ac b/configure.ac 30diff --git a/configure.ac b/configure.ac
31index 023e7cc55..917300b43 100644 31index 2869f7042..ce16e7758 100644
32--- a/configure.ac 32--- a/configure.ac
33+++ b/configure.ac 33+++ b/configure.ac
34@@ -1517,6 +1517,62 @@ else 34@@ -1518,6 +1518,62 @@ else
35 AC_MSG_RESULT([no]) 35 AC_MSG_RESULT([no])
36 fi 36 fi
37 37
@@ -94,7 +94,7 @@ index 023e7cc55..917300b43 100644
94 # Check whether user wants to use ldns 94 # Check whether user wants to use ldns
95 LDNS_MSG="no" 95 LDNS_MSG="no"
96 AC_ARG_WITH(ldns, 96 AC_ARG_WITH(ldns,
97@@ -5329,6 +5385,7 @@ echo " PAM support: $PAM_MSG" 97@@ -5269,6 +5325,7 @@ echo " PAM support: $PAM_MSG"
98 echo " OSF SIA support: $SIA_MSG" 98 echo " OSF SIA support: $SIA_MSG"
99 echo " KerberosV support: $KRB5_MSG" 99 echo " KerberosV support: $KRB5_MSG"
100 echo " SELinux support: $SELINUX_MSG" 100 echo " SELinux support: $SELINUX_MSG"
@@ -128,7 +128,7 @@ index fb133c14b..57a7fd66b 100644
128 .Xr moduli 5 , 128 .Xr moduli 5 ,
129 .Xr sshd_config 5 , 129 .Xr sshd_config 5 ,
130diff --git a/sshd.c b/sshd.c 130diff --git a/sshd.c b/sshd.c
131index 539a000fd..673db87f6 100644 131index 98680721b..46870d3b5 100644
132--- a/sshd.c 132--- a/sshd.c
133+++ b/sshd.c 133+++ b/sshd.c
134@@ -127,6 +127,13 @@ 134@@ -127,6 +127,13 @@
@@ -145,7 +145,7 @@ index 539a000fd..673db87f6 100644
145 /* Re-exec fds */ 145 /* Re-exec fds */
146 #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1) 146 #define REEXEC_DEVCRYPTO_RESERVED_FD (STDERR_FILENO + 1)
147 #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2) 147 #define REEXEC_STARTUP_PIPE_FD (STDERR_FILENO + 2)
148@@ -2099,6 +2106,24 @@ main(int ac, char **av) 148@@ -2057,6 +2064,24 @@ main(int ac, char **av)
149 #ifdef SSH_AUDIT_EVENTS 149 #ifdef SSH_AUDIT_EVENTS
150 audit_connection_from(remote_ip, remote_port); 150 audit_connection_from(remote_ip, remote_port);
151 #endif 151 #endif
@@ -153,7 +153,7 @@ index 539a000fd..673db87f6 100644
153+ allow_severity = options.log_facility|LOG_INFO; 153+ allow_severity = options.log_facility|LOG_INFO;
154+ deny_severity = options.log_facility|LOG_WARNING; 154+ deny_severity = options.log_facility|LOG_WARNING;
155+ /* Check whether logins are denied from this host. */ 155+ /* Check whether logins are denied from this host. */
156+ if (packet_connection_is_on_socket()) { 156+ if (ssh_packet_connection_is_on_socket(ssh)) {
157+ struct request_info req; 157+ struct request_info req;
158+ 158+
159+ request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0); 159+ request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
diff --git a/debian/patches/revert-ipqos-defaults.patch b/debian/patches/revert-ipqos-defaults.patch
index a329b9be1..d0b02d792 100644
--- a/debian/patches/revert-ipqos-defaults.patch
+++ b/debian/patches/revert-ipqos-defaults.patch
@@ -1,4 +1,4 @@
1From 6b56cd57db9061296231f14d537f1ebaf25e8877 Mon Sep 17 00:00:00 2001 1From 7d50f9e5be88179325983a1f58c9d51bb58f025a Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Mon, 8 Apr 2019 10:46:29 +0100 3Date: Mon, 8 Apr 2019 10:46:29 +0100
4Subject: Revert "upstream: Update default IPQoS in ssh(1), sshd(8) to DSCP 4Subject: Revert "upstream: Update default IPQoS in ssh(1), sshd(8) to DSCP
@@ -24,10 +24,10 @@ Patch-Name: revert-ipqos-defaults.patch
24 4 files changed, 8 insertions(+), 12 deletions(-) 24 4 files changed, 8 insertions(+), 12 deletions(-)
25 25
26diff --git a/readconf.c b/readconf.c 26diff --git a/readconf.c b/readconf.c
27index 661b8bf40..6d046f063 100644 27index f35bde6e6..2ba312441 100644
28--- a/readconf.c 28--- a/readconf.c
29+++ b/readconf.c 29+++ b/readconf.c
30@@ -2133,9 +2133,9 @@ fill_default_options(Options * options) 30@@ -2165,9 +2165,9 @@ fill_default_options(Options * options)
31 if (options->visual_host_key == -1) 31 if (options->visual_host_key == -1)
32 options->visual_host_key = 0; 32 options->visual_host_key = 0;
33 if (options->ip_qos_interactive == -1) 33 if (options->ip_qos_interactive == -1)
@@ -40,10 +40,10 @@ index 661b8bf40..6d046f063 100644
40 options->request_tty = REQUEST_TTY_AUTO; 40 options->request_tty = REQUEST_TTY_AUTO;
41 if (options->proxy_use_fdpass == -1) 41 if (options->proxy_use_fdpass == -1)
42diff --git a/servconf.c b/servconf.c 42diff --git a/servconf.c b/servconf.c
43index c5dd617ef..bf2669147 100644 43index 8d2bced52..365e6ff1e 100644
44--- a/servconf.c 44--- a/servconf.c
45+++ b/servconf.c 45+++ b/servconf.c
46@@ -403,9 +403,9 @@ fill_default_server_options(ServerOptions *options) 46@@ -423,9 +423,9 @@ fill_default_server_options(ServerOptions *options)
47 if (options->permit_tun == -1) 47 if (options->permit_tun == -1)
48 options->permit_tun = SSH_TUNMODE_NO; 48 options->permit_tun = SSH_TUNMODE_NO;
49 if (options->ip_qos_interactive == -1) 49 if (options->ip_qos_interactive == -1)
@@ -56,10 +56,10 @@ index c5dd617ef..bf2669147 100644
56 options->version_addendum = xstrdup(""); 56 options->version_addendum = xstrdup("");
57 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1) 57 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
58diff --git a/ssh_config.5 b/ssh_config.5 58diff --git a/ssh_config.5 b/ssh_config.5
59index 1a8e24bd1..f6c1b3b33 100644 59index a27631ae9..a9f6d906f 100644
60--- a/ssh_config.5 60--- a/ssh_config.5
61+++ b/ssh_config.5 61+++ b/ssh_config.5
62@@ -1055,11 +1055,9 @@ If one argument is specified, it is used as the packet class unconditionally. 62@@ -1098,11 +1098,9 @@ If one argument is specified, it is used as the packet class unconditionally.
63 If two values are specified, the first is automatically selected for 63 If two values are specified, the first is automatically selected for
64 interactive sessions and the second for non-interactive sessions. 64 interactive sessions and the second for non-interactive sessions.
65 The default is 65 The default is
@@ -74,10 +74,10 @@ index 1a8e24bd1..f6c1b3b33 100644
74 .It Cm KbdInteractiveAuthentication 74 .It Cm KbdInteractiveAuthentication
75 Specifies whether to use keyboard-interactive authentication. 75 Specifies whether to use keyboard-interactive authentication.
76diff --git a/sshd_config.5 b/sshd_config.5 76diff --git a/sshd_config.5 b/sshd_config.5
77index ba50a30f1..03f813e72 100644 77index c0c4ebd66..e5380f5dc 100644
78--- a/sshd_config.5 78--- a/sshd_config.5
79+++ b/sshd_config.5 79+++ b/sshd_config.5
80@@ -866,11 +866,9 @@ If one argument is specified, it is used as the packet class unconditionally. 80@@ -886,11 +886,9 @@ If one argument is specified, it is used as the packet class unconditionally.
81 If two values are specified, the first is automatically selected for 81 If two values are specified, the first is automatically selected for
82 interactive sessions and the second for non-interactive sessions. 82 interactive sessions and the second for non-interactive sessions.
83 The default is 83 The default is
diff --git a/debian/patches/sanitize-scp-filenames-via-snmprintf.patch b/debian/patches/sanitize-scp-filenames-via-snmprintf.patch
deleted file mode 100644
index e58b8b1bd..000000000
--- a/debian/patches/sanitize-scp-filenames-via-snmprintf.patch
+++ /dev/null
@@ -1,276 +0,0 @@
1From 11b88754cadcad0ba79b4ffcc127223248dccb54 Mon Sep 17 00:00:00 2001
2From: "dtucker@openbsd.org" <dtucker@openbsd.org>
3Date: Wed, 23 Jan 2019 08:01:46 +0000
4Subject: upstream: Sanitize scp filenames via snmprintf. To do this we move
5
6the progressmeter formatting outside of signal handler context and have the
7atomicio callback called for EINTR too. bz#2434 with contributions from djm
8and jjelen at redhat.com, ok djm@
9
10OpenBSD-Commit-ID: 1af61c1f70e4f3bd8ab140b9f1fa699481db57d8
11
12CVE-2019-6109
13
14Origin: backport, https://anongit.mindrot.org/openssh.git/commit/?id=8976f1c4b2721c26e878151f52bdf346dfe2d54c
15Bug-Debian: https://bugs.debian.org/793412
16Last-Update: 2019-02-08
17
18Patch-Name: sanitize-scp-filenames-via-snmprintf.patch
19---
20 atomicio.c | 20 ++++++++++++++-----
21 progressmeter.c | 53 ++++++++++++++++++++++---------------------------
22 progressmeter.h | 3 ++-
23 scp.c | 1 +
24 sftp-client.c | 16 ++++++++-------
25 5 files changed, 51 insertions(+), 42 deletions(-)
26
27diff --git a/atomicio.c b/atomicio.c
28index f854a06f5..d91bd7621 100644
29--- a/atomicio.c
30+++ b/atomicio.c
31@@ -1,4 +1,4 @@
32-/* $OpenBSD: atomicio.c,v 1.28 2016/07/27 23:18:12 djm Exp $ */
33+/* $OpenBSD: atomicio.c,v 1.29 2019/01/23 08:01:46 dtucker Exp $ */
34 /*
35 * Copyright (c) 2006 Damien Miller. All rights reserved.
36 * Copyright (c) 2005 Anil Madhavapeddy. All rights reserved.
37@@ -65,9 +65,14 @@ atomicio6(ssize_t (*f) (int, void *, size_t), int fd, void *_s, size_t n,
38 res = (f) (fd, s + pos, n - pos);
39 switch (res) {
40 case -1:
41- if (errno == EINTR)
42+ if (errno == EINTR) {
43+ /* possible SIGALARM, update callback */
44+ if (cb != NULL && cb(cb_arg, 0) == -1) {
45+ errno = EINTR;
46+ return pos;
47+ }
48 continue;
49- if (errno == EAGAIN || errno == EWOULDBLOCK) {
50+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
51 #ifndef BROKEN_READ_COMPARISON
52 (void)poll(&pfd, 1, -1);
53 #endif
54@@ -122,9 +127,14 @@ atomiciov6(ssize_t (*f) (int, const struct iovec *, int), int fd,
55 res = (f) (fd, iov, iovcnt);
56 switch (res) {
57 case -1:
58- if (errno == EINTR)
59+ if (errno == EINTR) {
60+ /* possible SIGALARM, update callback */
61+ if (cb != NULL && cb(cb_arg, 0) == -1) {
62+ errno = EINTR;
63+ return pos;
64+ }
65 continue;
66- if (errno == EAGAIN || errno == EWOULDBLOCK) {
67+ } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
68 #ifndef BROKEN_READV_COMPARISON
69 (void)poll(&pfd, 1, -1);
70 #endif
71diff --git a/progressmeter.c b/progressmeter.c
72index fe9bf52e4..add462dde 100644
73--- a/progressmeter.c
74+++ b/progressmeter.c
75@@ -1,4 +1,4 @@
76-/* $OpenBSD: progressmeter.c,v 1.45 2016/06/30 05:17:05 dtucker Exp $ */
77+/* $OpenBSD: progressmeter.c,v 1.46 2019/01/23 08:01:46 dtucker Exp $ */
78 /*
79 * Copyright (c) 2003 Nils Nordman. All rights reserved.
80 *
81@@ -31,6 +31,7 @@
82
83 #include <errno.h>
84 #include <signal.h>
85+#include <stdarg.h>
86 #include <stdio.h>
87 #include <string.h>
88 #include <time.h>
89@@ -39,6 +40,7 @@
90 #include "progressmeter.h"
91 #include "atomicio.h"
92 #include "misc.h"
93+#include "utf8.h"
94
95 #define DEFAULT_WINSIZE 80
96 #define MAX_WINSIZE 512
97@@ -61,7 +63,7 @@ static void setscreensize(void);
98 void refresh_progress_meter(void);
99
100 /* signal handler for updating the progress meter */
101-static void update_progress_meter(int);
102+static void sig_alarm(int);
103
104 static double start; /* start progress */
105 static double last_update; /* last progress update */
106@@ -74,6 +76,7 @@ static long stalled; /* how long we have been stalled */
107 static int bytes_per_second; /* current speed in bytes per second */
108 static int win_size; /* terminal window size */
109 static volatile sig_atomic_t win_resized; /* for window resizing */
110+static volatile sig_atomic_t alarm_fired;
111
112 /* units for format_size */
113 static const char unit[] = " KMGT";
114@@ -126,9 +129,17 @@ refresh_progress_meter(void)
115 off_t bytes_left;
116 int cur_speed;
117 int hours, minutes, seconds;
118- int i, len;
119 int file_len;
120
121+ if ((!alarm_fired && !win_resized) || !can_output())
122+ return;
123+ alarm_fired = 0;
124+
125+ if (win_resized) {
126+ setscreensize();
127+ win_resized = 0;
128+ }
129+
130 transferred = *counter - (cur_pos ? cur_pos : start_pos);
131 cur_pos = *counter;
132 now = monotime_double();
133@@ -158,16 +169,11 @@ refresh_progress_meter(void)
134
135 /* filename */
136 buf[0] = '\0';
137- file_len = win_size - 35;
138+ file_len = win_size - 36;
139 if (file_len > 0) {
140- len = snprintf(buf, file_len + 1, "\r%s", file);
141- if (len < 0)
142- len = 0;
143- if (len >= file_len + 1)
144- len = file_len;
145- for (i = len; i < file_len; i++)
146- buf[i] = ' ';
147- buf[file_len] = '\0';
148+ buf[0] = '\r';
149+ snmprintf(buf+1, sizeof(buf)-1 , &file_len, "%*s",
150+ file_len * -1, file);
151 }
152
153 /* percent of transfer done */
154@@ -228,22 +234,11 @@ refresh_progress_meter(void)
155
156 /*ARGSUSED*/
157 static void
158-update_progress_meter(int ignore)
159+sig_alarm(int ignore)
160 {
161- int save_errno;
162-
163- save_errno = errno;
164-
165- if (win_resized) {
166- setscreensize();
167- win_resized = 0;
168- }
169- if (can_output())
170- refresh_progress_meter();
171-
172- signal(SIGALRM, update_progress_meter);
173+ signal(SIGALRM, sig_alarm);
174+ alarm_fired = 1;
175 alarm(UPDATE_INTERVAL);
176- errno = save_errno;
177 }
178
179 void
180@@ -259,10 +254,9 @@ start_progress_meter(const char *f, off_t filesize, off_t *ctr)
181 bytes_per_second = 0;
182
183 setscreensize();
184- if (can_output())
185- refresh_progress_meter();
186+ refresh_progress_meter();
187
188- signal(SIGALRM, update_progress_meter);
189+ signal(SIGALRM, sig_alarm);
190 signal(SIGWINCH, sig_winch);
191 alarm(UPDATE_INTERVAL);
192 }
193@@ -286,6 +280,7 @@ stop_progress_meter(void)
194 static void
195 sig_winch(int sig)
196 {
197+ signal(SIGWINCH, sig_winch);
198 win_resized = 1;
199 }
200
201diff --git a/progressmeter.h b/progressmeter.h
202index bf179dca6..8f6678060 100644
203--- a/progressmeter.h
204+++ b/progressmeter.h
205@@ -1,4 +1,4 @@
206-/* $OpenBSD: progressmeter.h,v 1.3 2015/01/14 13:54:13 djm Exp $ */
207+/* $OpenBSD: progressmeter.h,v 1.4 2019/01/23 08:01:46 dtucker Exp $ */
208 /*
209 * Copyright (c) 2002 Nils Nordman. All rights reserved.
210 *
211@@ -24,4 +24,5 @@
212 */
213
214 void start_progress_meter(const char *, off_t, off_t *);
215+void refresh_progress_meter(void);
216 void stop_progress_meter(void);
217diff --git a/scp.c b/scp.c
218index 7163d33dc..80308573c 100644
219--- a/scp.c
220+++ b/scp.c
221@@ -593,6 +593,7 @@ scpio(void *_cnt, size_t s)
222 off_t *cnt = (off_t *)_cnt;
223
224 *cnt += s;
225+ refresh_progress_meter();
226 if (limit_kbps > 0)
227 bandwidth_limit(&bwlimit, s);
228 return 0;
229diff --git a/sftp-client.c b/sftp-client.c
230index 4986d6d8d..2bc698f86 100644
231--- a/sftp-client.c
232+++ b/sftp-client.c
233@@ -101,7 +101,9 @@ sftpio(void *_bwlimit, size_t amount)
234 {
235 struct bwlimit *bwlimit = (struct bwlimit *)_bwlimit;
236
237- bandwidth_limit(bwlimit, amount);
238+ refresh_progress_meter();
239+ if (bwlimit != NULL)
240+ bandwidth_limit(bwlimit, amount);
241 return 0;
242 }
243
244@@ -121,8 +123,8 @@ send_msg(struct sftp_conn *conn, struct sshbuf *m)
245 iov[1].iov_base = (u_char *)sshbuf_ptr(m);
246 iov[1].iov_len = sshbuf_len(m);
247
248- if (atomiciov6(writev, conn->fd_out, iov, 2,
249- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_out) !=
250+ if (atomiciov6(writev, conn->fd_out, iov, 2, sftpio,
251+ conn->limit_kbps > 0 ? &conn->bwlimit_out : NULL) !=
252 sshbuf_len(m) + sizeof(mlen))
253 fatal("Couldn't send packet: %s", strerror(errno));
254
255@@ -138,8 +140,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
256
257 if ((r = sshbuf_reserve(m, 4, &p)) != 0)
258 fatal("%s: buffer error: %s", __func__, ssh_err(r));
259- if (atomicio6(read, conn->fd_in, p, 4,
260- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in) != 4) {
261+ if (atomicio6(read, conn->fd_in, p, 4, sftpio,
262+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL) != 4) {
263 if (errno == EPIPE || errno == ECONNRESET)
264 fatal("Connection closed");
265 else
266@@ -157,8 +159,8 @@ get_msg_extended(struct sftp_conn *conn, struct sshbuf *m, int initial)
267
268 if ((r = sshbuf_reserve(m, msg_len, &p)) != 0)
269 fatal("%s: buffer error: %s", __func__, ssh_err(r));
270- if (atomicio6(read, conn->fd_in, p, msg_len,
271- conn->limit_kbps > 0 ? sftpio : NULL, &conn->bwlimit_in)
272+ if (atomicio6(read, conn->fd_in, p, msg_len, sftpio,
273+ conn->limit_kbps > 0 ? &conn->bwlimit_in : NULL)
274 != msg_len) {
275 if (errno == EPIPE)
276 fatal("Connection closed");
diff --git a/debian/patches/scp-disallow-dot-or-empty-filename.patch b/debian/patches/scp-disallow-dot-or-empty-filename.patch
deleted file mode 100644
index 716f2ffa8..000000000
--- a/debian/patches/scp-disallow-dot-or-empty-filename.patch
+++ /dev/null
@@ -1,32 +0,0 @@
1From dee21e97428e69d30e2d15c71f3e7cc08bf8e4f8 Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Fri, 16 Nov 2018 03:03:10 +0000
4Subject: upstream: disallow empty incoming filename or ones that refer to the
5
6current directory; based on report/patch from Harry Sintonen
7
8OpenBSD-Commit-ID: f27651b30eaee2df49540ab68d030865c04f6de9
9
10Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=6010c0303a422a9c5fa8860c061bf7105eb7f8b2
11Bug-Debian: https://bugs.debian.org/919101
12Last-Update: 2019-01-12
13
14Patch-Name: scp-disallow-dot-or-empty-filename.patch
15---
16 scp.c | 3 ++-
17 1 file changed, 2 insertions(+), 1 deletion(-)
18
19diff --git a/scp.c b/scp.c
20index ed2864250..7163d33dc 100644
21--- a/scp.c
22+++ b/scp.c
23@@ -1114,7 +1114,8 @@ sink(int argc, char **argv)
24 SCREWUP("size out of range");
25 size = (off_t)ull;
26
27- if ((strchr(cp, '/') != NULL) || (strcmp(cp, "..") == 0)) {
28+ if (*cp == '\0' || strchr(cp, '/') != NULL ||
29+ strcmp(cp, ".") == 0 || strcmp(cp, "..") == 0) {
30 run_err("error: unexpected filename: %s", cp);
31 exit(1);
32 }
diff --git a/debian/patches/scp-handle-braces.patch b/debian/patches/scp-handle-braces.patch
deleted file mode 100644
index 0cbdcfdc0..000000000
--- a/debian/patches/scp-handle-braces.patch
+++ /dev/null
@@ -1,353 +0,0 @@
1From 7a3fa37583d4abf128f7f4c6eb1e7ffc90115eab Mon Sep 17 00:00:00 2001
2From: "djm@openbsd.org" <djm@openbsd.org>
3Date: Sun, 10 Feb 2019 11:15:52 +0000
4Subject: upstream: when checking that filenames sent by the server side
5
6match what the client requested, be prepared to handle shell-style brace
7alternations, e.g. "{foo,bar}".
8
9"looks good to me" millert@ + in snaps for the last week courtesy
10deraadt@
11
12OpenBSD-Commit-ID: 3b1ce7639b0b25b2248e3a30f561a548f6815f3e
13
14Origin: upstream, https://anongit.mindrot.org/openssh.git/commit/?id=3d896c157c722bc47adca51a58dca859225b5874
15Bug-Debian: https://bugs.debian.org/923486
16Last-Update: 2019-03-01
17
18Patch-Name: scp-handle-braces.patch
19---
20 scp.c | 280 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
21 1 file changed, 269 insertions(+), 11 deletions(-)
22
23diff --git a/scp.c b/scp.c
24index 035037bcc..3888baab0 100644
25--- a/scp.c
26+++ b/scp.c
27@@ -635,6 +635,253 @@ parse_scp_uri(const char *uri, char **userp, char **hostp, int *portp,
28 return r;
29 }
30
31+/* Appends a string to an array; returns 0 on success, -1 on alloc failure */
32+static int
33+append(char *cp, char ***ap, size_t *np)
34+{
35+ char **tmp;
36+
37+ if ((tmp = reallocarray(*ap, *np + 1, sizeof(*tmp))) == NULL)
38+ return -1;
39+ tmp[(*np)] = cp;
40+ (*np)++;
41+ *ap = tmp;
42+ return 0;
43+}
44+
45+/*
46+ * Finds the start and end of the first brace pair in the pattern.
47+ * returns 0 on success or -1 for invalid patterns.
48+ */
49+static int
50+find_brace(const char *pattern, int *startp, int *endp)
51+{
52+ int i;
53+ int in_bracket, brace_level;
54+
55+ *startp = *endp = -1;
56+ in_bracket = brace_level = 0;
57+ for (i = 0; i < INT_MAX && *endp < 0 && pattern[i] != '\0'; i++) {
58+ switch (pattern[i]) {
59+ case '\\':
60+ /* skip next character */
61+ if (pattern[i + 1] != '\0')
62+ i++;
63+ break;
64+ case '[':
65+ in_bracket = 1;
66+ break;
67+ case ']':
68+ in_bracket = 0;
69+ break;
70+ case '{':
71+ if (in_bracket)
72+ break;
73+ if (pattern[i + 1] == '}') {
74+ /* Protect a single {}, for find(1), like csh */
75+ i++; /* skip */
76+ break;
77+ }
78+ if (*startp == -1)
79+ *startp = i;
80+ brace_level++;
81+ break;
82+ case '}':
83+ if (in_bracket)
84+ break;
85+ if (*startp < 0) {
86+ /* Unbalanced brace */
87+ return -1;
88+ }
89+ if (--brace_level <= 0)
90+ *endp = i;
91+ break;
92+ }
93+ }
94+ /* unbalanced brackets/braces */
95+ if (*endp < 0 && (*startp >= 0 || in_bracket))
96+ return -1;
97+ return 0;
98+}
99+
100+/*
101+ * Assembles and records a successfully-expanded pattern, returns -1 on
102+ * alloc failure.
103+ */
104+static int
105+emit_expansion(const char *pattern, int brace_start, int brace_end,
106+ int sel_start, int sel_end, char ***patternsp, size_t *npatternsp)
107+{
108+ char *cp;
109+ int o = 0, tail_len = strlen(pattern + brace_end + 1);
110+
111+ if ((cp = malloc(brace_start + (sel_end - sel_start) +
112+ tail_len + 1)) == NULL)
113+ return -1;
114+
115+ /* Pattern before initial brace */
116+ if (brace_start > 0) {
117+ memcpy(cp, pattern, brace_start);
118+ o = brace_start;
119+ }
120+ /* Current braced selection */
121+ if (sel_end - sel_start > 0) {
122+ memcpy(cp + o, pattern + sel_start,
123+ sel_end - sel_start);
124+ o += sel_end - sel_start;
125+ }
126+ /* Remainder of pattern after closing brace */
127+ if (tail_len > 0) {
128+ memcpy(cp + o, pattern + brace_end + 1, tail_len);
129+ o += tail_len;
130+ }
131+ cp[o] = '\0';
132+ if (append(cp, patternsp, npatternsp) != 0) {
133+ free(cp);
134+ return -1;
135+ }
136+ return 0;
137+}
138+
139+/*
140+ * Expand the first encountered brace in pattern, appending the expanded
141+ * patterns it yielded to the *patternsp array.
142+ *
143+ * Returns 0 on success or -1 on allocation failure.
144+ *
145+ * Signals whether expansion was performed via *expanded and whether
146+ * pattern was invalid via *invalid.
147+ */
148+static int
149+brace_expand_one(const char *pattern, char ***patternsp, size_t *npatternsp,
150+ int *expanded, int *invalid)
151+{
152+ int i;
153+ int in_bracket, brace_start, brace_end, brace_level;
154+ int sel_start, sel_end;
155+
156+ *invalid = *expanded = 0;
157+
158+ if (find_brace(pattern, &brace_start, &brace_end) != 0) {
159+ *invalid = 1;
160+ return 0;
161+ } else if (brace_start == -1)
162+ return 0;
163+
164+ in_bracket = brace_level = 0;
165+ for (i = sel_start = brace_start + 1; i < brace_end; i++) {
166+ switch (pattern[i]) {
167+ case '{':
168+ if (in_bracket)
169+ break;
170+ brace_level++;
171+ break;
172+ case '}':
173+ if (in_bracket)
174+ break;
175+ brace_level--;
176+ break;
177+ case '[':
178+ in_bracket = 1;
179+ break;
180+ case ']':
181+ in_bracket = 0;
182+ break;
183+ case '\\':
184+ if (i < brace_end - 1)
185+ i++; /* skip */
186+ break;
187+ }
188+ if (pattern[i] == ',' || i == brace_end - 1) {
189+ if (in_bracket || brace_level > 0)
190+ continue;
191+ /* End of a selection, emit an expanded pattern */
192+
193+ /* Adjust end index for last selection */
194+ sel_end = (i == brace_end - 1) ? brace_end : i;
195+ if (emit_expansion(pattern, brace_start, brace_end,
196+ sel_start, sel_end, patternsp, npatternsp) != 0)
197+ return -1;
198+ /* move on to the next selection */
199+ sel_start = i + 1;
200+ continue;
201+ }
202+ }
203+ if (in_bracket || brace_level > 0) {
204+ *invalid = 1;
205+ return 0;
206+ }
207+ /* success */
208+ *expanded = 1;
209+ return 0;
210+}
211+
212+/* Expand braces from pattern. Returns 0 on success, -1 on failure */
213+static int
214+brace_expand(const char *pattern, char ***patternsp, size_t *npatternsp)
215+{
216+ char *cp, *cp2, **active = NULL, **done = NULL;
217+ size_t i, nactive = 0, ndone = 0;
218+ int ret = -1, invalid = 0, expanded = 0;
219+
220+ *patternsp = NULL;
221+ *npatternsp = 0;
222+
223+ /* Start the worklist with the original pattern */
224+ if ((cp = strdup(pattern)) == NULL)
225+ return -1;
226+ if (append(cp, &active, &nactive) != 0) {
227+ free(cp);
228+ return -1;
229+ }
230+ while (nactive > 0) {
231+ cp = active[nactive - 1];
232+ nactive--;
233+ if (brace_expand_one(cp, &active, &nactive,
234+ &expanded, &invalid) == -1) {
235+ free(cp);
236+ goto fail;
237+ }
238+ if (invalid)
239+ fatal("%s: invalid brace pattern \"%s\"", __func__, cp);
240+ if (expanded) {
241+ /*
242+ * Current entry expanded to new entries on the
243+ * active list; discard the progenitor pattern.
244+ */
245+ free(cp);
246+ continue;
247+ }
248+ /*
249+ * Pattern did not expand; append the finename component to
250+ * the completed list
251+ */
252+ if ((cp2 = strrchr(cp, '/')) != NULL)
253+ *cp2++ = '\0';
254+ else
255+ cp2 = cp;
256+ if (append(xstrdup(cp2), &done, &ndone) != 0) {
257+ free(cp);
258+ goto fail;
259+ }
260+ free(cp);
261+ }
262+ /* success */
263+ *patternsp = done;
264+ *npatternsp = ndone;
265+ done = NULL;
266+ ndone = 0;
267+ ret = 0;
268+ fail:
269+ for (i = 0; i < nactive; i++)
270+ free(active[i]);
271+ free(active);
272+ for (i = 0; i < ndone; i++)
273+ free(done[i]);
274+ free(done);
275+ return ret;
276+}
277+
278 void
279 toremote(int argc, char **argv)
280 {
281@@ -998,7 +1245,8 @@ sink(int argc, char **argv, const char *src)
282 unsigned long long ull;
283 int setimes, targisdir, wrerrno = 0;
284 char ch, *cp, *np, *targ, *why, *vect[1], buf[2048], visbuf[2048];
285- char *src_copy = NULL, *restrict_pattern = NULL;
286+ char **patterns = NULL;
287+ size_t n, npatterns = 0;
288 struct timeval tv[2];
289
290 #define atime tv[0]
291@@ -1028,16 +1276,13 @@ sink(int argc, char **argv, const char *src)
292 * Prepare to try to restrict incoming filenames to match
293 * the requested destination file glob.
294 */
295- if ((src_copy = strdup(src)) == NULL)
296- fatal("strdup failed");
297- if ((restrict_pattern = strrchr(src_copy, '/')) != NULL) {
298- *restrict_pattern++ = '\0';
299- }
300+ if (brace_expand(src, &patterns, &npatterns) != 0)
301+ fatal("%s: could not expand pattern", __func__);
302 }
303 for (first = 1;; first = 0) {
304 cp = buf;
305 if (atomicio(read, remin, cp, 1) != 1)
306- return;
307+ goto done;
308 if (*cp++ == '\n')
309 SCREWUP("unexpected <newline>");
310 do {
311@@ -1063,7 +1308,7 @@ sink(int argc, char **argv, const char *src)
312 }
313 if (buf[0] == 'E') {
314 (void) atomicio(vwrite, remout, "", 1);
315- return;
316+ goto done;
317 }
318 if (ch == '\n')
319 *--cp = 0;
320@@ -1138,9 +1383,14 @@ sink(int argc, char **argv, const char *src)
321 run_err("error: unexpected filename: %s", cp);
322 exit(1);
323 }
324- if (restrict_pattern != NULL &&
325- fnmatch(restrict_pattern, cp, 0) != 0)
326- SCREWUP("filename does not match request");
327+ if (npatterns > 0) {
328+ for (n = 0; n < npatterns; n++) {
329+ if (fnmatch(patterns[n], cp, 0) == 0)
330+ break;
331+ }
332+ if (n >= npatterns)
333+ SCREWUP("filename does not match request");
334+ }
335 if (targisdir) {
336 static char *namebuf;
337 static size_t cursize;
338@@ -1299,7 +1549,15 @@ bad: run_err("%s: %s", np, strerror(errno));
339 break;
340 }
341 }
342+done:
343+ for (n = 0; n < npatterns; n++)
344+ free(patterns[n]);
345+ free(patterns);
346+ return;
347 screwup:
348+ for (n = 0; n < npatterns; n++)
349+ free(patterns[n]);
350+ free(patterns);
351 run_err("protocol error: %s", why);
352 exit(1);
353 }
diff --git a/debian/patches/scp-quoting.patch b/debian/patches/scp-quoting.patch
index d054b2a82..29cf5603f 100644
--- a/debian/patches/scp-quoting.patch
+++ b/debian/patches/scp-quoting.patch
@@ -1,4 +1,4 @@
1From eefdc7046766b52e39f1b6eafcde22c1e013ce9f Mon Sep 17 00:00:00 2001 1From 76a51e544a6a6a674ff1dddf4bb6da05d9cce774 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Nicolas=20Valc=C3=A1rcel?= <nvalcarcel@ubuntu.com> 2From: =?UTF-8?q?Nicolas=20Valc=C3=A1rcel?= <nvalcarcel@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:09:59 +0000 3Date: Sun, 9 Feb 2014 16:09:59 +0000
4Subject: Adjust scp quoting in verbose mode 4Subject: Adjust scp quoting in verbose mode
@@ -17,10 +17,10 @@ Patch-Name: scp-quoting.patch
17 1 file changed, 10 insertions(+), 2 deletions(-) 17 1 file changed, 10 insertions(+), 2 deletions(-)
18 18
19diff --git a/scp.c b/scp.c 19diff --git a/scp.c b/scp.c
20index 60682c687..ed2864250 100644 20index 80bc0e8b1..a2dc410bd 100644
21--- a/scp.c 21--- a/scp.c
22+++ b/scp.c 22+++ b/scp.c
23@@ -198,8 +198,16 @@ do_local_cmd(arglist *a) 23@@ -199,8 +199,16 @@ do_local_cmd(arglist *a)
24 24
25 if (verbose_mode) { 25 if (verbose_mode) {
26 fprintf(stderr, "Executing:"); 26 fprintf(stderr, "Executing:");
diff --git a/debian/patches/seccomp-s390-flock-ipc.patch b/debian/patches/seccomp-s390-flock-ipc.patch
index e864427bd..ad00d1220 100644
--- a/debian/patches/seccomp-s390-flock-ipc.patch
+++ b/debian/patches/seccomp-s390-flock-ipc.patch
@@ -1,4 +1,4 @@
1From 690939ba320d93e6f3ab5266bea94d8fb06c8bae Mon Sep 17 00:00:00 2001 1From 9fa2ceb14b6e7e5e902cff416bc9ad3963be9883 Mon Sep 17 00:00:00 2001
2From: Eduardo Barretto <ebarretto@linux.vnet.ibm.com> 2From: Eduardo Barretto <ebarretto@linux.vnet.ibm.com>
3Date: Tue, 9 May 2017 10:53:04 -0300 3Date: Tue, 9 May 2017 10:53:04 -0300
4Subject: Allow flock and ipc syscall for s390 architecture 4Subject: Allow flock and ipc syscall for s390 architecture
diff --git a/debian/patches/seccomp-s390-ioctl-ep11-crypto.patch b/debian/patches/seccomp-s390-ioctl-ep11-crypto.patch
index ecbe1d142..fcd7285bd 100644
--- a/debian/patches/seccomp-s390-ioctl-ep11-crypto.patch
+++ b/debian/patches/seccomp-s390-ioctl-ep11-crypto.patch
@@ -1,4 +1,4 @@
1From 9ce189b9f22890421b7f8d3f49a39186d3ce3e14 Mon Sep 17 00:00:00 2001 1From 9d4508c5c1d6466c662befcb26aff09f41966102 Mon Sep 17 00:00:00 2001
2From: Eduardo Barretto <ebarretto@linux.vnet.ibm.com> 2From: Eduardo Barretto <ebarretto@linux.vnet.ibm.com>
3Date: Tue, 9 May 2017 13:33:30 -0300 3Date: Tue, 9 May 2017 13:33:30 -0300
4Subject: Enable specific ioctl call for EP11 crypto card (s390) 4Subject: Enable specific ioctl call for EP11 crypto card (s390)
diff --git a/debian/patches/selinux-role.patch b/debian/patches/selinux-role.patch
index 269a87c76..5ab339ac9 100644
--- a/debian/patches/selinux-role.patch
+++ b/debian/patches/selinux-role.patch
@@ -1,4 +1,4 @@
1From cf3f6ac19812e4d32874304b3854b055831c2124 Mon Sep 17 00:00:00 2001 1From 21e3ff3ab4791d3c94bd775da66cde29797fcb36 Mon Sep 17 00:00:00 2001
2From: Manoj Srivastava <srivasta@debian.org> 2From: Manoj Srivastava <srivasta@debian.org>
3Date: Sun, 9 Feb 2014 16:09:49 +0000 3Date: Sun, 9 Feb 2014 16:09:49 +0000
4Subject: Handle SELinux authorisation roles 4Subject: Handle SELinux authorisation roles
@@ -9,7 +9,7 @@ SELinux maintainer, so we'll keep it until we have something better.
9 9
10Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1641 10Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1641
11Bug-Debian: http://bugs.debian.org/394795 11Bug-Debian: http://bugs.debian.org/394795
12Last-Update: 2018-08-24 12Last-Update: 2019-06-05
13 13
14Patch-Name: selinux-role.patch 14Patch-Name: selinux-role.patch
15--- 15---
@@ -31,7 +31,7 @@ Patch-Name: selinux-role.patch
31 15 files changed, 99 insertions(+), 32 deletions(-) 31 15 files changed, 99 insertions(+), 32 deletions(-)
32 32
33diff --git a/auth.h b/auth.h 33diff --git a/auth.h b/auth.h
34index 977562f0a..90802a5eb 100644 34index bf393e755..8f13bdf48 100644
35--- a/auth.h 35--- a/auth.h
36+++ b/auth.h 36+++ b/auth.h
37@@ -65,6 +65,7 @@ struct Authctxt { 37@@ -65,6 +65,7 @@ struct Authctxt {
@@ -43,19 +43,19 @@ index 977562f0a..90802a5eb 100644
43 /* Method lists for multiple authentication */ 43 /* Method lists for multiple authentication */
44 char **auth_methods; /* modified from server config */ 44 char **auth_methods; /* modified from server config */
45diff --git a/auth2.c b/auth2.c 45diff --git a/auth2.c b/auth2.c
46index a77742819..3035926ba 100644 46index 7417eafa4..d60e7f1f2 100644
47--- a/auth2.c 47--- a/auth2.c
48+++ b/auth2.c 48+++ b/auth2.c
49@@ -257,7 +257,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) 49@@ -267,7 +267,7 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
50 { 50 {
51 Authctxt *authctxt = ssh->authctxt; 51 Authctxt *authctxt = ssh->authctxt;
52 Authmethod *m = NULL; 52 Authmethod *m = NULL;
53- char *user, *service, *method, *style = NULL; 53- char *user = NULL, *service = NULL, *method = NULL, *style = NULL;
54+ char *user, *service, *method, *style = NULL, *role = NULL; 54+ char *user = NULL, *service = NULL, *method = NULL, *style = NULL, *role = NULL;
55 int authenticated = 0; 55 int r, authenticated = 0;
56 double tstart = monotime_double(); 56 double tstart = monotime_double();
57 57
58@@ -270,8 +270,13 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) 58@@ -281,8 +281,13 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
59 debug("userauth-request for user %s service %s method %s", user, service, method); 59 debug("userauth-request for user %s service %s method %s", user, service, method);
60 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); 60 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
61 61
@@ -69,7 +69,7 @@ index a77742819..3035926ba 100644
69 69
70 if (authctxt->attempt++ == 0) { 70 if (authctxt->attempt++ == 0) {
71 /* setup auth context */ 71 /* setup auth context */
72@@ -298,8 +303,9 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh) 72@@ -309,8 +314,9 @@ input_userauth_request(int type, u_int32_t seq, struct ssh *ssh)
73 use_privsep ? " [net]" : ""); 73 use_privsep ? " [net]" : "");
74 authctxt->service = xstrdup(service); 74 authctxt->service = xstrdup(service);
75 authctxt->style = style ? xstrdup(style) : NULL; 75 authctxt->style = style ? xstrdup(style) : NULL;
@@ -77,22 +77,22 @@ index a77742819..3035926ba 100644
77 if (use_privsep) 77 if (use_privsep)
78- mm_inform_authserv(service, style); 78- mm_inform_authserv(service, style);
79+ mm_inform_authserv(service, style, role); 79+ mm_inform_authserv(service, style, role);
80 userauth_banner(); 80 userauth_banner(ssh);
81 if (auth2_setup_methods_lists(authctxt) != 0) 81 if (auth2_setup_methods_lists(authctxt) != 0)
82 packet_disconnect("no authentication methods enabled"); 82 ssh_packet_disconnect(ssh,
83diff --git a/monitor.c b/monitor.c 83diff --git a/monitor.c b/monitor.c
84index eabc1e89b..08fddabd7 100644 84index 0766d6ef5..5f84e880d 100644
85--- a/monitor.c 85--- a/monitor.c
86+++ b/monitor.c 86+++ b/monitor.c
87@@ -117,6 +117,7 @@ int mm_answer_sign(int, struct sshbuf *); 87@@ -117,6 +117,7 @@ int mm_answer_sign(struct ssh *, int, struct sshbuf *);
88 int mm_answer_pwnamallow(int, struct sshbuf *); 88 int mm_answer_pwnamallow(struct ssh *, int, struct sshbuf *);
89 int mm_answer_auth2_read_banner(int, struct sshbuf *); 89 int mm_answer_auth2_read_banner(struct ssh *, int, struct sshbuf *);
90 int mm_answer_authserv(int, struct sshbuf *); 90 int mm_answer_authserv(struct ssh *, int, struct sshbuf *);
91+int mm_answer_authrole(int, struct sshbuf *); 91+int mm_answer_authrole(struct ssh *, int, struct sshbuf *);
92 int mm_answer_authpassword(int, struct sshbuf *); 92 int mm_answer_authpassword(struct ssh *, int, struct sshbuf *);
93 int mm_answer_bsdauthquery(int, struct sshbuf *); 93 int mm_answer_bsdauthquery(struct ssh *, int, struct sshbuf *);
94 int mm_answer_bsdauthrespond(int, struct sshbuf *); 94 int mm_answer_bsdauthrespond(struct ssh *, int, struct sshbuf *);
95@@ -193,6 +194,7 @@ struct mon_table mon_dispatch_proto20[] = { 95@@ -197,6 +198,7 @@ struct mon_table mon_dispatch_proto20[] = {
96 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, 96 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
97 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 97 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
98 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, 98 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
@@ -100,7 +100,7 @@ index eabc1e89b..08fddabd7 100644
100 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, 100 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
101 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 101 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
102 #ifdef USE_PAM 102 #ifdef USE_PAM
103@@ -817,6 +819,7 @@ mm_answer_pwnamallow(int sock, struct sshbuf *m) 103@@ -819,6 +821,7 @@ mm_answer_pwnamallow(struct ssh *ssh, int sock, struct sshbuf *m)
104 104
105 /* Allow service/style information on the auth context */ 105 /* Allow service/style information on the auth context */
106 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); 106 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
@@ -108,7 +108,7 @@ index eabc1e89b..08fddabd7 100644
108 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); 108 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
109 109
110 #ifdef USE_PAM 110 #ifdef USE_PAM
111@@ -850,16 +853,42 @@ mm_answer_authserv(int sock, struct sshbuf *m) 111@@ -852,16 +855,42 @@ mm_answer_authserv(struct ssh *ssh, int sock, struct sshbuf *m)
112 monitor_permit_authentications(1); 112 monitor_permit_authentications(1);
113 113
114 if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 || 114 if ((r = sshbuf_get_cstring(m, &authctxt->service, NULL)) != 0 ||
@@ -135,7 +135,7 @@ index eabc1e89b..08fddabd7 100644
135+} 135+}
136+ 136+
137+int 137+int
138+mm_answer_authrole(int sock, struct sshbuf *m) 138+mm_answer_authrole(struct ssh *ssh, int sock, struct sshbuf *m)
139+{ 139+{
140+ int r; 140+ int r;
141+ 141+
@@ -154,7 +154,7 @@ index eabc1e89b..08fddabd7 100644
154 return (0); 154 return (0);
155 } 155 }
156 156
157@@ -1501,7 +1530,7 @@ mm_answer_pty(int sock, struct sshbuf *m) 157@@ -1528,7 +1557,7 @@ mm_answer_pty(struct ssh *ssh, int sock, struct sshbuf *m)
158 res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); 158 res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
159 if (res == 0) 159 if (res == 0)
160 goto error; 160 goto error;
@@ -164,23 +164,23 @@ index eabc1e89b..08fddabd7 100644
164 if ((r = sshbuf_put_u32(m, 1)) != 0 || 164 if ((r = sshbuf_put_u32(m, 1)) != 0 ||
165 (r = sshbuf_put_cstring(m, s->tty)) != 0) 165 (r = sshbuf_put_cstring(m, s->tty)) != 0)
166diff --git a/monitor.h b/monitor.h 166diff --git a/monitor.h b/monitor.h
167index 44fbed589..8f65e684d 100644 167index 2b1a2d590..4d87284aa 100644
168--- a/monitor.h 168--- a/monitor.h
169+++ b/monitor.h 169+++ b/monitor.h
170@@ -66,6 +66,8 @@ enum monitor_reqtype { 170@@ -65,6 +65,8 @@ enum monitor_reqtype {
171
171 MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151, 172 MONITOR_REQ_GSSSIGN = 150, MONITOR_ANS_GSSSIGN = 151,
172 MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153, 173 MONITOR_REQ_GSSUPCREDS = 152, MONITOR_ANS_GSSUPCREDS = 153,
173
174+ MONITOR_REQ_AUTHROLE = 154,
175+ 174+
175+ MONITOR_REQ_AUTHROLE = 154,
176 }; 176 };
177 177
178 struct monitor { 178 struct ssh;
179diff --git a/monitor_wrap.c b/monitor_wrap.c 179diff --git a/monitor_wrap.c b/monitor_wrap.c
180index 1865a122a..fd4d7eb3b 100644 180index 8e4c1c1f8..6b3a6251c 100644
181--- a/monitor_wrap.c 181--- a/monitor_wrap.c
182+++ b/monitor_wrap.c 182+++ b/monitor_wrap.c
183@@ -369,10 +369,10 @@ mm_auth2_read_banner(void) 183@@ -364,10 +364,10 @@ mm_auth2_read_banner(void)
184 return (banner); 184 return (banner);
185 } 185 }
186 186
@@ -193,7 +193,7 @@ index 1865a122a..fd4d7eb3b 100644
193 { 193 {
194 struct sshbuf *m; 194 struct sshbuf *m;
195 int r; 195 int r;
196@@ -382,7 +382,8 @@ mm_inform_authserv(char *service, char *style) 196@@ -377,7 +377,8 @@ mm_inform_authserv(char *service, char *style)
197 if ((m = sshbuf_new()) == NULL) 197 if ((m = sshbuf_new()) == NULL)
198 fatal("%s: sshbuf_new failed", __func__); 198 fatal("%s: sshbuf_new failed", __func__);
199 if ((r = sshbuf_put_cstring(m, service)) != 0 || 199 if ((r = sshbuf_put_cstring(m, service)) != 0 ||
@@ -203,7 +203,7 @@ index 1865a122a..fd4d7eb3b 100644
203 fatal("%s: buffer error: %s", __func__, ssh_err(r)); 203 fatal("%s: buffer error: %s", __func__, ssh_err(r));
204 204
205 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m); 205 mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, m);
206@@ -390,6 +391,26 @@ mm_inform_authserv(char *service, char *style) 206@@ -385,6 +386,26 @@ mm_inform_authserv(char *service, char *style)
207 sshbuf_free(m); 207 sshbuf_free(m);
208 } 208 }
209 209
@@ -231,17 +231,17 @@ index 1865a122a..fd4d7eb3b 100644
231 int 231 int
232 mm_auth_password(struct ssh *ssh, char *password) 232 mm_auth_password(struct ssh *ssh, char *password)
233diff --git a/monitor_wrap.h b/monitor_wrap.h 233diff --git a/monitor_wrap.h b/monitor_wrap.h
234index 7f93144ff..79e78cc90 100644 234index 69164a8c0..3d0e32d48 100644
235--- a/monitor_wrap.h 235--- a/monitor_wrap.h
236+++ b/monitor_wrap.h 236+++ b/monitor_wrap.h
237@@ -43,7 +43,8 @@ int mm_is_monitor(void); 237@@ -44,7 +44,8 @@ int mm_is_monitor(void);
238 DH *mm_choose_dh(int, int, int); 238 DH *mm_choose_dh(int, int, int);
239 int mm_sshkey_sign(struct sshkey *, u_char **, size_t *, const u_char *, size_t, 239 int mm_sshkey_sign(struct ssh *, struct sshkey *, u_char **, size_t *,
240 const char *, u_int compat); 240 const u_char *, size_t, const char *, u_int compat);
241-void mm_inform_authserv(char *, char *); 241-void mm_inform_authserv(char *, char *);
242+void mm_inform_authserv(char *, char *, char *); 242+void mm_inform_authserv(char *, char *, char *);
243+void mm_inform_authrole(char *); 243+void mm_inform_authrole(char *);
244 struct passwd *mm_getpwnamallow(const char *); 244 struct passwd *mm_getpwnamallow(struct ssh *, const char *);
245 char *mm_auth2_read_banner(void); 245 char *mm_auth2_read_banner(void);
246 int mm_auth_password(struct ssh *, char *); 246 int mm_auth_password(struct ssh *, char *);
247diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c 247diff --git a/openbsd-compat/port-linux.c b/openbsd-compat/port-linux.c
@@ -363,10 +363,10 @@ index ea4f9c584..60d72ffe7 100644
363 char *platform_krb5_get_principal_name(const char *); 363 char *platform_krb5_get_principal_name(const char *);
364 int platform_sys_dir_uid(uid_t); 364 int platform_sys_dir_uid(uid_t);
365diff --git a/session.c b/session.c 365diff --git a/session.c b/session.c
366index 2d0958d11..19f38637e 100644 366index ac3d9d19d..d87ea4d44 100644
367--- a/session.c 367--- a/session.c
368+++ b/session.c 368+++ b/session.c
369@@ -1380,7 +1380,7 @@ safely_chroot(const char *path, uid_t uid) 369@@ -1356,7 +1356,7 @@ safely_chroot(const char *path, uid_t uid)
370 370
371 /* Set login name, uid, gid, and groups. */ 371 /* Set login name, uid, gid, and groups. */
372 void 372 void
@@ -375,7 +375,7 @@ index 2d0958d11..19f38637e 100644
375 { 375 {
376 char uidstr[32], *chroot_path, *tmp; 376 char uidstr[32], *chroot_path, *tmp;
377 377
378@@ -1408,7 +1408,7 @@ do_setusercontext(struct passwd *pw) 378@@ -1384,7 +1384,7 @@ do_setusercontext(struct passwd *pw)
379 endgrent(); 379 endgrent();
380 #endif 380 #endif
381 381
@@ -384,7 +384,7 @@ index 2d0958d11..19f38637e 100644
384 384
385 if (!in_chroot && options.chroot_directory != NULL && 385 if (!in_chroot && options.chroot_directory != NULL &&
386 strcasecmp(options.chroot_directory, "none") != 0) { 386 strcasecmp(options.chroot_directory, "none") != 0) {
387@@ -1547,7 +1547,7 @@ do_child(struct ssh *ssh, Session *s, const char *command) 387@@ -1525,7 +1525,7 @@ do_child(struct ssh *ssh, Session *s, const char *command)
388 388
389 /* Force a password change */ 389 /* Force a password change */
390 if (s->authctxt->force_pwchange) { 390 if (s->authctxt->force_pwchange) {
@@ -393,7 +393,7 @@ index 2d0958d11..19f38637e 100644
393 child_close_fds(ssh); 393 child_close_fds(ssh);
394 do_pwchange(s); 394 do_pwchange(s);
395 exit(1); 395 exit(1);
396@@ -1565,7 +1565,7 @@ do_child(struct ssh *ssh, Session *s, const char *command) 396@@ -1543,7 +1543,7 @@ do_child(struct ssh *ssh, Session *s, const char *command)
397 /* When PAM is enabled we rely on it to do the nologin check */ 397 /* When PAM is enabled we rely on it to do the nologin check */
398 if (!options.use_pam) 398 if (!options.use_pam)
399 do_nologin(pw); 399 do_nologin(pw);
@@ -402,8 +402,8 @@ index 2d0958d11..19f38637e 100644
402 /* 402 /*
403 * PAM session modules in do_setusercontext may have 403 * PAM session modules in do_setusercontext may have
404 * generated messages, so if this in an interactive 404 * generated messages, so if this in an interactive
405@@ -1955,7 +1955,7 @@ session_pty_req(struct ssh *ssh, Session *s) 405@@ -1942,7 +1942,7 @@ session_pty_req(struct ssh *ssh, Session *s)
406 ssh_tty_parse_modes(ssh, s->ttyfd); 406 sshpkt_fatal(ssh, r, "%s: parse packet", __func__);
407 407
408 if (!use_privsep) 408 if (!use_privsep)
409- pty_setowner(s->pw, s->tty); 409- pty_setowner(s->pw, s->tty);
@@ -425,10 +425,10 @@ index ce59dabd9..675c91146 100644
425 const char *session_get_remote_name_or_ip(struct ssh *, u_int, int); 425 const char *session_get_remote_name_or_ip(struct ssh *, u_int, int);
426 426
427diff --git a/sshd.c b/sshd.c 427diff --git a/sshd.c b/sshd.c
428index 673db87f6..2bc6679e5 100644 428index 46870d3b5..e3e96426e 100644
429--- a/sshd.c 429--- a/sshd.c
430+++ b/sshd.c 430+++ b/sshd.c
431@@ -683,7 +683,7 @@ privsep_postauth(Authctxt *authctxt) 431@@ -594,7 +594,7 @@ privsep_postauth(struct ssh *ssh, Authctxt *authctxt)
432 reseed_prngs(); 432 reseed_prngs();
433 433
434 /* Drop privileges */ 434 /* Drop privileges */
diff --git a/debian/patches/series b/debian/patches/series
index b0da97283..6304f537a 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -24,11 +24,4 @@ restore-authorized_keys2.patch
24seccomp-s390-flock-ipc.patch 24seccomp-s390-flock-ipc.patch
25seccomp-s390-ioctl-ep11-crypto.patch 25seccomp-s390-ioctl-ep11-crypto.patch
26conch-old-privkey-format.patch 26conch-old-privkey-format.patch
27scp-disallow-dot-or-empty-filename.patch
28sanitize-scp-filenames-via-snmprintf.patch
29have-progressmeter-force-update-at-beginning-and-end-transfer.patch
30check-filenames-in-scp-client.patch
31fix-key-type-check.patch
32request-rsa-sha2-cert-signatures.patch
33scp-handle-braces.patch
34revert-ipqos-defaults.patch 27revert-ipqos-defaults.patch
diff --git a/debian/patches/shell-path.patch b/debian/patches/shell-path.patch
index ad574e829..2224eeead 100644
--- a/debian/patches/shell-path.patch
+++ b/debian/patches/shell-path.patch
@@ -1,4 +1,4 @@
1From cabad6b7182cd6eaa8b760718200a316e7f578ed Mon Sep 17 00:00:00 2001 1From b019e32a0ee7a79c0a08cb1199229d03b16934a7 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:00 +0000 3Date: Sun, 9 Feb 2014 16:10:00 +0000
4Subject: Look for $SHELL on the path for ProxyCommand/LocalCommand 4Subject: Look for $SHELL on the path for ProxyCommand/LocalCommand
@@ -16,10 +16,10 @@ Patch-Name: shell-path.patch
16 1 file changed, 2 insertions(+), 2 deletions(-) 16 1 file changed, 2 insertions(+), 2 deletions(-)
17 17
18diff --git a/sshconnect.c b/sshconnect.c 18diff --git a/sshconnect.c b/sshconnect.c
19index 6d819279e..700ea6c3c 100644 19index fdcdcd855..103d84e38 100644
20--- a/sshconnect.c 20--- a/sshconnect.c
21+++ b/sshconnect.c 21+++ b/sshconnect.c
22@@ -229,7 +229,7 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port, 22@@ -257,7 +257,7 @@ ssh_proxy_connect(struct ssh *ssh, const char *host, u_short port,
23 /* Execute the proxy command. Note that we gave up any 23 /* Execute the proxy command. Note that we gave up any
24 extra privileges above. */ 24 extra privileges above. */
25 signal(SIGPIPE, SIG_DFL); 25 signal(SIGPIPE, SIG_DFL);
@@ -28,7 +28,7 @@ index 6d819279e..700ea6c3c 100644
28 perror(argv[0]); 28 perror(argv[0]);
29 exit(1); 29 exit(1);
30 } 30 }
31@@ -1534,7 +1534,7 @@ ssh_local_cmd(const char *args) 31@@ -1382,7 +1382,7 @@ ssh_local_cmd(const char *args)
32 if (pid == 0) { 32 if (pid == 0) {
33 signal(SIGPIPE, SIG_DFL); 33 signal(SIGPIPE, SIG_DFL);
34 debug3("Executing %s -c \"%s\"", shell, args); 34 debug3("Executing %s -c \"%s\"", shell, args);
diff --git a/debian/patches/ssh-agent-setgid.patch b/debian/patches/ssh-agent-setgid.patch
index ed6ef3d46..e94e48a03 100644
--- a/debian/patches/ssh-agent-setgid.patch
+++ b/debian/patches/ssh-agent-setgid.patch
@@ -1,4 +1,4 @@
1From 6d4521d39a852dc5627187c045c933f4e1cb4601 Mon Sep 17 00:00:00 2001 1From 9e040aefaefa40bcbe5dcdc0f9f03555cf8fe2d0 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:13 +0000 3Date: Sun, 9 Feb 2014 16:10:13 +0000
4Subject: Document consequences of ssh-agent being setgid in ssh-agent(1) 4Subject: Document consequences of ssh-agent being setgid in ssh-agent(1)
diff --git a/debian/patches/ssh-argv0.patch b/debian/patches/ssh-argv0.patch
index bb1e10973..a5aa9259a 100644
--- a/debian/patches/ssh-argv0.patch
+++ b/debian/patches/ssh-argv0.patch
@@ -1,4 +1,4 @@
1From d1064c2689df8d0894a68ac9671d14ab125bc91b Mon Sep 17 00:00:00 2001 1From 23b4cc85184891ad61bb98045629400e48d946dd Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:10 +0000 3Date: Sun, 9 Feb 2014 16:10:10 +0000
4Subject: ssh(1): Refer to ssh-argv0(1) 4Subject: ssh(1): Refer to ssh-argv0(1)
@@ -18,10 +18,10 @@ Patch-Name: ssh-argv0.patch
18 1 file changed, 1 insertion(+) 18 1 file changed, 1 insertion(+)
19 19
20diff --git a/ssh.1 b/ssh.1 20diff --git a/ssh.1 b/ssh.1
21index 5dfad6daa..ad1ed0f86 100644 21index e4aeae7b4..8d2b08a29 100644
22--- a/ssh.1 22--- a/ssh.1
23+++ b/ssh.1 23+++ b/ssh.1
24@@ -1585,6 +1585,7 @@ if an error occurred. 24@@ -1584,6 +1584,7 @@ if an error occurred.
25 .Xr sftp 1 , 25 .Xr sftp 1 ,
26 .Xr ssh-add 1 , 26 .Xr ssh-add 1 ,
27 .Xr ssh-agent 1 , 27 .Xr ssh-agent 1 ,
diff --git a/debian/patches/ssh-vulnkey-compat.patch b/debian/patches/ssh-vulnkey-compat.patch
index ca3e090bd..8adc301fc 100644
--- a/debian/patches/ssh-vulnkey-compat.patch
+++ b/debian/patches/ssh-vulnkey-compat.patch
@@ -1,4 +1,4 @@
1From eccbd3637a2b8544fdcfdd5d1a00a9dfdac62aeb Mon Sep 17 00:00:00 2001 1From 0138f331a73d692f4543477ce7f64f9ede7d6b08 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@ubuntu.com> 2From: Colin Watson <cjwatson@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:09:50 +0000 3Date: Sun, 9 Feb 2014 16:09:50 +0000
4Subject: Accept obsolete ssh-vulnkey configuration options 4Subject: Accept obsolete ssh-vulnkey configuration options
@@ -17,10 +17,10 @@ Patch-Name: ssh-vulnkey-compat.patch
17 2 files changed, 2 insertions(+) 17 2 files changed, 2 insertions(+)
18 18
19diff --git a/readconf.c b/readconf.c 19diff --git a/readconf.c b/readconf.c
20index 36bc5e59a..5e655e924 100644 20index 4d699e5f1..29f3bd98d 100644
21--- a/readconf.c 21--- a/readconf.c
22+++ b/readconf.c 22+++ b/readconf.c
23@@ -190,6 +190,7 @@ static struct { 23@@ -192,6 +192,7 @@ static struct {
24 { "fallbacktorsh", oDeprecated }, 24 { "fallbacktorsh", oDeprecated },
25 { "globalknownhostsfile2", oDeprecated }, 25 { "globalknownhostsfile2", oDeprecated },
26 { "rhostsauthentication", oDeprecated }, 26 { "rhostsauthentication", oDeprecated },
@@ -29,10 +29,10 @@ index 36bc5e59a..5e655e924 100644
29 { "useroaming", oDeprecated }, 29 { "useroaming", oDeprecated },
30 { "usersh", oDeprecated }, 30 { "usersh", oDeprecated },
31diff --git a/servconf.c b/servconf.c 31diff --git a/servconf.c b/servconf.c
32index 4668b8a45..6caf1db38 100644 32index ffdad31e7..c01e0690e 100644
33--- a/servconf.c 33--- a/servconf.c
34+++ b/servconf.c 34+++ b/servconf.c
35@@ -600,6 +600,7 @@ static struct { 35@@ -621,6 +621,7 @@ static struct {
36 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 36 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
37 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 37 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
38 { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 38 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
diff --git a/debian/patches/syslog-level-silent.patch b/debian/patches/syslog-level-silent.patch
index 3093a41fb..aa7968090 100644
--- a/debian/patches/syslog-level-silent.patch
+++ b/debian/patches/syslog-level-silent.patch
@@ -1,4 +1,4 @@
1From e755ec70d62bfb9b02159123f4e870b00010be77 Mon Sep 17 00:00:00 2001 1From 0646a0cd5ea893cf822113d4f10c501540c18e40 Mon Sep 17 00:00:00 2001
2From: Jonathan David Amery <jdamery@ysolde.ucam.org> 2From: Jonathan David Amery <jdamery@ysolde.ucam.org>
3Date: Sun, 9 Feb 2014 16:09:54 +0000 3Date: Sun, 9 Feb 2014 16:09:54 +0000
4Subject: "LogLevel SILENT" compatibility 4Subject: "LogLevel SILENT" compatibility
@@ -33,10 +33,10 @@ index d9c2d136c..1749af6d1 100644
33 { "FATAL", SYSLOG_LEVEL_FATAL }, 33 { "FATAL", SYSLOG_LEVEL_FATAL },
34 { "ERROR", SYSLOG_LEVEL_ERROR }, 34 { "ERROR", SYSLOG_LEVEL_ERROR },
35diff --git a/ssh.c b/ssh.c 35diff --git a/ssh.c b/ssh.c
36index 0777c31e4..3140fed4c 100644 36index 42be7d88f..86f143341 100644
37--- a/ssh.c 37--- a/ssh.c
38+++ b/ssh.c 38+++ b/ssh.c
39@@ -1258,7 +1258,7 @@ main(int ac, char **av) 39@@ -1265,7 +1265,7 @@ main(int ac, char **av)
40 /* Do not allocate a tty if stdin is not a tty. */ 40 /* Do not allocate a tty if stdin is not a tty. */
41 if ((!isatty(fileno(stdin)) || stdin_null_flag) && 41 if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
42 options.request_tty != REQUEST_TTY_FORCE) { 42 options.request_tty != REQUEST_TTY_FORCE) {
diff --git a/debian/patches/systemd-readiness.patch b/debian/patches/systemd-readiness.patch
index c5dee41ad..51c7e32de 100644
--- a/debian/patches/systemd-readiness.patch
+++ b/debian/patches/systemd-readiness.patch
@@ -1,4 +1,4 @@
1From da34947128351bee9d2530574432190548f5be58 Mon Sep 17 00:00:00 2001 1From a88f67584ef5889d95c04b0294e92c11ed4904cd Mon Sep 17 00:00:00 2001
2From: Michael Biebl <biebl@debian.org> 2From: Michael Biebl <biebl@debian.org>
3Date: Mon, 21 Dec 2015 16:08:47 +0000 3Date: Mon, 21 Dec 2015 16:08:47 +0000
4Subject: Add systemd readiness notification support 4Subject: Add systemd readiness notification support
@@ -14,10 +14,10 @@ Patch-Name: systemd-readiness.patch
14 2 files changed, 33 insertions(+) 14 2 files changed, 33 insertions(+)
15 15
16diff --git a/configure.ac b/configure.ac 16diff --git a/configure.ac b/configure.ac
17index 917300b43..8a5db4cb5 100644 17index ce16e7758..de140f578 100644
18--- a/configure.ac 18--- a/configure.ac
19+++ b/configure.ac 19+++ b/configure.ac
20@@ -4586,6 +4586,29 @@ AC_ARG_WITH([kerberos5], 20@@ -4526,6 +4526,29 @@ AC_ARG_WITH([kerberos5],
21 AC_SUBST([GSSLIBS]) 21 AC_SUBST([GSSLIBS])
22 AC_SUBST([K5LIBS]) 22 AC_SUBST([K5LIBS])
23 23
@@ -47,7 +47,7 @@ index 917300b43..8a5db4cb5 100644
47 # Looking for programs, paths and files 47 # Looking for programs, paths and files
48 48
49 PRIVSEP_PATH=/var/empty 49 PRIVSEP_PATH=/var/empty
50@@ -5392,6 +5415,7 @@ echo " libldns support: $LDNS_MSG" 50@@ -5332,6 +5355,7 @@ echo " libldns support: $LDNS_MSG"
51 echo " Solaris process contract support: $SPC_MSG" 51 echo " Solaris process contract support: $SPC_MSG"
52 echo " Solaris project support: $SP_MSG" 52 echo " Solaris project support: $SP_MSG"
53 echo " Solaris privilege support: $SPP_MSG" 53 echo " Solaris privilege support: $SPP_MSG"
@@ -56,7 +56,7 @@ index 917300b43..8a5db4cb5 100644
56 echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" 56 echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
57 echo " BSD Auth support: $BSD_AUTH_MSG" 57 echo " BSD Auth support: $BSD_AUTH_MSG"
58diff --git a/sshd.c b/sshd.c 58diff --git a/sshd.c b/sshd.c
59index d7e77d343..a1c3970b3 100644 59index 1e7ece588..48162b629 100644
60--- a/sshd.c 60--- a/sshd.c
61+++ b/sshd.c 61+++ b/sshd.c
62@@ -85,6 +85,10 @@ 62@@ -85,6 +85,10 @@
@@ -70,7 +70,7 @@ index d7e77d343..a1c3970b3 100644
70 #include "xmalloc.h" 70 #include "xmalloc.h"
71 #include "ssh.h" 71 #include "ssh.h"
72 #include "ssh2.h" 72 #include "ssh2.h"
73@@ -1990,6 +1994,11 @@ main(int ac, char **av) 73@@ -1946,6 +1950,11 @@ main(int ac, char **av)
74 } 74 }
75 } 75 }
76 76
diff --git a/debian/patches/user-group-modes.patch b/debian/patches/user-group-modes.patch
index bc2390e06..899c60123 100644
--- a/debian/patches/user-group-modes.patch
+++ b/debian/patches/user-group-modes.patch
@@ -1,4 +1,4 @@
1From 7b931d36ad36a93d2b1811858ca29408ec44ecae Mon Sep 17 00:00:00 2001 1From e04a43bd5798ba43d910493d179438845e96f631 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:09:58 +0000 3Date: Sun, 9 Feb 2014 16:09:58 +0000
4Subject: Allow harmless group-writability 4Subject: Allow harmless group-writability
@@ -13,7 +13,7 @@ default.
13 13
14Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1060 14Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1060
15Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=314347 15Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=314347
16Last-Update: 2017-10-04 16Last-Update: 2019-06-05
17 17
18Patch-Name: user-group-modes.patch 18Patch-Name: user-group-modes.patch
19--- 19---
@@ -51,7 +51,7 @@ index 57296e1f6..546aa0495 100644
51 pw->pw_name, buf); 51 pw->pw_name, buf);
52 auth_debug_add("Bad file modes for %.200s", buf); 52 auth_debug_add("Bad file modes for %.200s", buf);
53diff --git a/auth.c b/auth.c 53diff --git a/auth.c b/auth.c
54index d8e6b4a3d..9d1d453f1 100644 54index f7a23afba..8ffd77662 100644
55--- a/auth.c 55--- a/auth.c
56+++ b/auth.c 56+++ b/auth.c
57@@ -473,8 +473,7 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host, 57@@ -473,8 +473,7 @@ check_key_in_hostfiles(struct passwd *pw, struct sshkey *key, const char *host,
@@ -65,10 +65,10 @@ index d8e6b4a3d..9d1d453f1 100644
65 "bad owner or modes for %.200s", 65 "bad owner or modes for %.200s",
66 pw->pw_name, user_hostfile); 66 pw->pw_name, user_hostfile);
67diff --git a/misc.c b/misc.c 67diff --git a/misc.c b/misc.c
68index bdc06fdb3..5159e6692 100644 68index 009e02bc5..634b5060a 100644
69--- a/misc.c 69--- a/misc.c
70+++ b/misc.c 70+++ b/misc.c
71@@ -58,8 +58,9 @@ 71@@ -59,8 +59,9 @@
72 #include <netdb.h> 72 #include <netdb.h>
73 #ifdef HAVE_PATHS_H 73 #ifdef HAVE_PATHS_H
74 # include <paths.h> 74 # include <paths.h>
@@ -79,7 +79,7 @@ index bdc06fdb3..5159e6692 100644
79 #ifdef SSH_TUN_OPENBSD 79 #ifdef SSH_TUN_OPENBSD
80 #include <net/if.h> 80 #include <net/if.h>
81 #endif 81 #endif
82@@ -1028,6 +1029,55 @@ percent_expand(const char *string, ...) 82@@ -1103,6 +1104,55 @@ percent_expand(const char *string, ...)
83 #undef EXPAND_MAX_KEYS 83 #undef EXPAND_MAX_KEYS
84 } 84 }
85 85
@@ -135,7 +135,7 @@ index bdc06fdb3..5159e6692 100644
135 int 135 int
136 tun_open(int tun, int mode, char **ifname) 136 tun_open(int tun, int mode, char **ifname)
137 { 137 {
138@@ -1786,8 +1836,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir, 138@@ -1860,8 +1910,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
139 snprintf(err, errlen, "%s is not a regular file", buf); 139 snprintf(err, errlen, "%s is not a regular file", buf);
140 return -1; 140 return -1;
141 } 141 }
@@ -145,7 +145,7 @@ index bdc06fdb3..5159e6692 100644
145 snprintf(err, errlen, "bad ownership or modes for file %s", 145 snprintf(err, errlen, "bad ownership or modes for file %s",
146 buf); 146 buf);
147 return -1; 147 return -1;
148@@ -1802,8 +1851,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir, 148@@ -1876,8 +1925,7 @@ safe_path(const char *name, struct stat *stp, const char *pw_dir,
149 strlcpy(buf, cp, sizeof(buf)); 149 strlcpy(buf, cp, sizeof(buf));
150 150
151 if (stat(buf, &st) < 0 || 151 if (stat(buf, &st) < 0 ||
@@ -156,10 +156,10 @@ index bdc06fdb3..5159e6692 100644
156 "bad ownership or modes for directory %s", buf); 156 "bad ownership or modes for directory %s", buf);
157 return -1; 157 return -1;
158diff --git a/misc.h b/misc.h 158diff --git a/misc.h b/misc.h
159index 31b207a8d..aaf966e65 100644 159index 5b4325aba..a4bdee187 100644
160--- a/misc.h 160--- a/misc.h
161+++ b/misc.h 161+++ b/misc.h
162@@ -168,6 +168,8 @@ int safe_path_fd(int, const char *, struct passwd *, 162@@ -175,6 +175,8 @@ int safe_path_fd(int, const char *, struct passwd *,
163 char *read_passphrase(const char *, int); 163 char *read_passphrase(const char *, int);
164 int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); 164 int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
165 165
@@ -169,10 +169,10 @@ index 31b207a8d..aaf966e65 100644
169 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b)) 169 #define MAXIMUM(a, b) (((a) > (b)) ? (a) : (b))
170 #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) 170 #define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
171diff --git a/readconf.c b/readconf.c 171diff --git a/readconf.c b/readconf.c
172index 052d4b1ac..6b01f20d2 100644 172index 3d0b6ff90..cd60007f8 100644
173--- a/readconf.c 173--- a/readconf.c
174+++ b/readconf.c 174+++ b/readconf.c
175@@ -1820,8 +1820,7 @@ read_config_file_depth(const char *filename, struct passwd *pw, 175@@ -1846,8 +1846,7 @@ read_config_file_depth(const char *filename, struct passwd *pw,
176 176
177 if (fstat(fileno(f), &sb) == -1) 177 if (fstat(fileno(f), &sb) == -1)
178 fatal("fstat %s: %s", filename, strerror(errno)); 178 fatal("fstat %s: %s", filename, strerror(errno));
@@ -183,10 +183,10 @@ index 052d4b1ac..6b01f20d2 100644
183 } 183 }
184 184
185diff --git a/ssh.1 b/ssh.1 185diff --git a/ssh.1 b/ssh.1
186index 7760c3075..81f29af43 100644 186index a1c7d2305..64ead5f57 100644
187--- a/ssh.1 187--- a/ssh.1
188+++ b/ssh.1 188+++ b/ssh.1
189@@ -1485,6 +1485,8 @@ The file format and configuration options are described in 189@@ -1484,6 +1484,8 @@ The file format and configuration options are described in
190 .Xr ssh_config 5 . 190 .Xr ssh_config 5 .
191 Because of the potential for abuse, this file must have strict permissions: 191 Because of the potential for abuse, this file must have strict permissions:
192 read/write for the user, and not writable by others. 192 read/write for the user, and not writable by others.
@@ -196,13 +196,13 @@ index 7760c3075..81f29af43 100644
196 .It Pa ~/.ssh/environment 196 .It Pa ~/.ssh/environment
197 Contains additional definitions for environment variables; see 197 Contains additional definitions for environment variables; see
198diff --git a/ssh_config.5 b/ssh_config.5 198diff --git a/ssh_config.5 b/ssh_config.5
199index 54e143c93..7d55fa820 100644 199index 250c92d04..bd1e9311d 100644
200--- a/ssh_config.5 200--- a/ssh_config.5
201+++ b/ssh_config.5 201+++ b/ssh_config.5
202@@ -1835,6 +1835,8 @@ The format of this file is described above. 202@@ -1885,6 +1885,8 @@ The format of this file is described above.
203 This file is used by the SSH client. 203 This file is used by the SSH client.
204 Because of the potential for abuse, this file must have strict permissions: 204 Because of the potential for abuse, this file must have strict permissions:
205 read/write for the user, and not accessible by others. 205 read/write for the user, and not writable by others.
206+It may be group-writable provided that the group in question contains only 206+It may be group-writable provided that the group in question contains only
207+the user. 207+the user.
208 .It Pa /etc/ssh/ssh_config 208 .It Pa /etc/ssh/ssh_config