summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.depend6
-rw-r--r--Makefile.in2
-rw-r--r--atomicio.h4
-rw-r--r--kex.c294
-rw-r--r--kex.h20
-rw-r--r--kexc25519.c10
-rw-r--r--kexc25519c.c6
-rw-r--r--kexc25519s.c6
-rw-r--r--kexdh.c10
-rw-r--r--kexdhc.c6
-rw-r--r--kexdhs.c6
-rw-r--r--kexecdh.c10
-rw-r--r--kexecdhc.c6
-rw-r--r--kexecdhs.c6
-rw-r--r--kexgex.c10
-rw-r--r--kexgexc.c6
-rw-r--r--kexgexs.c6
-rw-r--r--misc.c77
-rw-r--r--misc.h5
-rw-r--r--packet.c42
-rw-r--r--ssh.c4
-rw-r--r--ssh.h6
-rw-r--r--ssh_api.c125
-rw-r--r--sshconnect.c187
-rw-r--r--sshconnect.h15
-rw-r--r--sshconnect2.c49
-rw-r--r--sshd.c118
27 files changed, 548 insertions, 494 deletions
diff --git a/.depend b/.depend
index f85557c9c..193130f5d 100644
--- a/.depend
+++ b/.depend
@@ -60,8 +60,8 @@ gss-serv.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-comp
60hash.o: crypto_api.h includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h digest.h log.h ssherr.h 60hash.o: crypto_api.h includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h digest.h log.h ssherr.h
61hmac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h digest.h hmac.h 61hmac.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h digest.h hmac.h
62hostfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h sshkey.h hostfile.h log.h misc.h ssherr.h digest.h hmac.h 62hostfile.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h match.h sshkey.h hostfile.h log.h misc.h ssherr.h digest.h hmac.h
63kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh2.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h log.h match.h misc.h monitor.h ssherr.h sshbuf.h 63kex.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssh.h ssh2.h atomicio.h version.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h log.h match.h misc.h
64kex.o: digest.h 64kex.o: monitor.h ssherr.h sshbuf.h digest.h
65kexc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h log.h digest.h ssherr.h 65kexc25519.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshbuf.h ssh2.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h log.h digest.h ssherr.h
66kexc25519c.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssh2.h sshbuf.h digest.h ssherr.h 66kexc25519c.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h kex.h mac.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssh2.h sshbuf.h digest.h ssherr.h
67kexc25519s.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h kex.h mac.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssh2.h sshbuf.h ssherr.h 67kexc25519s.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h sshkey.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h digest.h kex.h mac.h log.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h ssh2.h sshbuf.h ssherr.h
@@ -149,7 +149,7 @@ sshbuf-getput-crypto.o: includes.h config.h defines.h platform.h openbsd-compat/
149sshbuf-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h 149sshbuf-misc.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h
150sshbuf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h misc.h 150sshbuf.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ssherr.h sshbuf.h misc.h
151sshconnect.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h hostfile.h ssh.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h sshkey.h sshconnect.h log.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.h 151sshconnect.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h xmalloc.h hostfile.h ssh.h sshbuf.h packet.h openbsd-compat/sys-queue.h dispatch.h opacket.h compat.h sshkey.h sshconnect.h log.h misc.h readconf.h atomicio.h dns.h monitor_fdpass.h ssh2.h version.h authfile.h
152sshconnect.o: ssherr.h authfd.h 152sshconnect.o: ssherr.h authfd.h kex.h mac.h
153sshconnect2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h packet.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h myproposal.h 153sshconnect2.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshbuf.h packet.h dispatch.h opacket.h compat.h cipher.h cipher-chachapoly.h chacha.h poly1305.h cipher-aesctr.h rijndael.h sshkey.h kex.h mac.h myproposal.h
154sshconnect2.o: sshconnect.h authfile.h dh.h authfd.h log.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h ssherr.h utf8.h 154sshconnect2.o: sshconnect.h authfile.h dh.h authfd.h log.h misc.h readconf.h match.h canohost.h msg.h pathnames.h uidswap.h hostfile.h ssherr.h utf8.h
155sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h opacket.h log.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h chacha.h 155sshd.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-compat.h openbsd-compat/base64.h openbsd-compat/sigact.h openbsd-compat/readpassphrase.h openbsd-compat/vis.h openbsd-compat/getrrsetbyname.h openbsd-compat/sha1.h openbsd-compat/sha2.h openbsd-compat/rmd160.h openbsd-compat/md5.h openbsd-compat/blf.h openbsd-compat/getopt.h openbsd-compat/bsd-misc.h openbsd-compat/bsd-setres_id.h openbsd-compat/bsd-signal.h openbsd-compat/bsd-statvfs.h openbsd-compat/bsd-waitpid.h openbsd-compat/bsd-poll.h openbsd-compat/fake-rfc2553.h openbsd-compat/bsd-cygwin_util.h openbsd-compat/port-aix.h openbsd-compat/port-irix.h openbsd-compat/port-linux.h openbsd-compat/port-solaris.h openbsd-compat/port-net.h openbsd-compat/port-uw.h openbsd-compat/bsd-nextstep.h entropy.h ./openbsd-compat/sys-tree.h openbsd-compat/sys-queue.h xmalloc.h ssh.h ssh2.h sshpty.h packet.h dispatch.h opacket.h log.h sshbuf.h misc.h match.h servconf.h uidswap.h compat.h cipher.h cipher-chachapoly.h chacha.h
diff --git a/Makefile.in b/Makefile.in
index 126b2c742..6ffccb482 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -186,7 +186,7 @@ ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
186ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o 186ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
187 $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 187 $(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
188 188
189ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o 189ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o compat.o
190 $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS) 190 $(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
191 191
192ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o 192ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
diff --git a/atomicio.h b/atomicio.h
index 0d728ac86..8b3cc6e21 100644
--- a/atomicio.h
+++ b/atomicio.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: atomicio.h,v 1.11 2010/09/22 22:58:51 djm Exp $ */ 1/* $OpenBSD: atomicio.h,v 1.12 2018/12/27 03:25:25 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Damien Miller. All rights reserved. 4 * Copyright (c) 2006 Damien Miller. All rights reserved.
@@ -29,6 +29,8 @@
29#ifndef _ATOMICIO_H 29#ifndef _ATOMICIO_H
30#define _ATOMICIO_H 30#define _ATOMICIO_H
31 31
32struct iovec;
33
32/* 34/*
33 * Ensure all of data on socket comes through. f==read || f==vwrite 35 * Ensure all of data on socket comes through. f==read || f==vwrite
34 */ 36 */
diff --git a/kex.c b/kex.c
index 3823a9544..30e1c261d 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.142 2018/12/07 03:39:40 djm Exp $ */ 1/* $OpenBSD: kex.c,v 1.143 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -25,19 +25,25 @@
25 25
26#include "includes.h" 26#include "includes.h"
27 27
28 28#include <sys/types.h>
29#include <errno.h>
29#include <signal.h> 30#include <signal.h>
30#include <stdarg.h> 31#include <stdarg.h>
31#include <stdio.h> 32#include <stdio.h>
32#include <stdlib.h> 33#include <stdlib.h>
33#include <string.h> 34#include <string.h>
35#include <unistd.h>
36#include <poll.h>
34 37
35#ifdef WITH_OPENSSL 38#ifdef WITH_OPENSSL
36#include <openssl/crypto.h> 39#include <openssl/crypto.h>
37#include <openssl/dh.h> 40#include <openssl/dh.h>
38#endif 41#endif
39 42
43#include "ssh.h"
40#include "ssh2.h" 44#include "ssh2.h"
45#include "atomicio.h"
46#include "version.h"
41#include "packet.h" 47#include "packet.h"
42#include "compat.h" 48#include "compat.h"
43#include "cipher.h" 49#include "cipher.h"
@@ -578,32 +584,20 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
578 return SSH_ERR_INTERNAL_ERROR; 584 return SSH_ERR_INTERNAL_ERROR;
579} 585}
580 586
581int 587struct kex *
582kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp) 588kex_new(void)
583{ 589{
584 struct kex *kex; 590 struct kex *kex;
585 int r;
586 591
587 *kexp = NULL; 592 if ((kex = calloc(1, sizeof(*kex))) == NULL ||
588 if ((kex = calloc(1, sizeof(*kex))) == NULL) 593 (kex->peer = sshbuf_new()) == NULL ||
589 return SSH_ERR_ALLOC_FAIL; 594 (kex->my = sshbuf_new()) == NULL ||
590 if ((kex->peer = sshbuf_new()) == NULL || 595 (kex->client_version = sshbuf_new()) == NULL ||
591 (kex->my = sshbuf_new()) == NULL) { 596 (kex->server_version = sshbuf_new()) == NULL) {
592 r = SSH_ERR_ALLOC_FAIL;
593 goto out;
594 }
595 if ((r = kex_prop2buf(kex->my, proposal)) != 0)
596 goto out;
597 kex->done = 0;
598 kex->flags = KEX_INITIAL;
599 kex_reset_dispatch(ssh);
600 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
601 r = 0;
602 *kexp = kex;
603 out:
604 if (r != 0)
605 kex_free(kex); 597 kex_free(kex);
606 return r; 598 return NULL;
599 }
600 return kex;
607} 601}
608 602
609void 603void
@@ -642,6 +636,9 @@ kex_free(struct kex *kex)
642{ 636{
643 u_int mode; 637 u_int mode;
644 638
639 if (kex == NULL)
640 return;
641
645#ifdef WITH_OPENSSL 642#ifdef WITH_OPENSSL
646 DH_free(kex->dh); 643 DH_free(kex->dh);
647#ifdef OPENSSL_HAS_ECC 644#ifdef OPENSSL_HAS_ECC
@@ -654,9 +651,9 @@ kex_free(struct kex *kex)
654 } 651 }
655 sshbuf_free(kex->peer); 652 sshbuf_free(kex->peer);
656 sshbuf_free(kex->my); 653 sshbuf_free(kex->my);
654 sshbuf_free(kex->client_version);
655 sshbuf_free(kex->server_version);
657 free(kex->session_id); 656 free(kex->session_id);
658 free(kex->client_version_string);
659 free(kex->server_version_string);
660 free(kex->failed_choice); 657 free(kex->failed_choice);
661 free(kex->hostkey_alg); 658 free(kex->hostkey_alg);
662 free(kex->name); 659 free(kex->name);
@@ -664,11 +661,24 @@ kex_free(struct kex *kex)
664} 661}
665 662
666int 663int
664kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
665{
666 int r;
667
668 if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
669 return r;
670 ssh->kex->flags = KEX_INITIAL;
671 kex_reset_dispatch(ssh);
672 ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
673 return 0;
674}
675
676int
667kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX]) 677kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
668{ 678{
669 int r; 679 int r;
670 680
671 if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) 681 if ((r = kex_ready(ssh, proposal)) != 0)
672 return r; 682 return r;
673 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */ 683 if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
674 kex_free(ssh->kex); 684 kex_free(ssh->kex);
@@ -1043,3 +1053,233 @@ dump_digest(char *msg, u_char *digest, int len)
1043 sshbuf_dump_data(digest, len, stderr); 1053 sshbuf_dump_data(digest, len, stderr);
1044} 1054}
1045#endif 1055#endif
1056
1057/*
1058 * Send a plaintext error message to the peer, suffixed by \r\n.
1059 * Only used during banner exchange, and there only for the server.
1060 */
1061static void
1062send_error(struct ssh *ssh, char *msg)
1063{
1064 char *crnl = "\r\n";
1065
1066 if (!ssh->kex->server)
1067 return;
1068
1069 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1070 msg, strlen(msg)) != strlen(msg) ||
1071 atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1072 crnl, strlen(crnl)) != strlen(crnl))
1073 error("%s: write: %.100s", __func__, strerror(errno));
1074}
1075
1076/*
1077 * Sends our identification string and waits for the peer's. Will block for
1078 * up to timeout_ms (or indefinitely if timeout_ms <= 0).
1079 * Returns on 0 success or a ssherr.h code on failure.
1080 */
1081int
1082kex_exchange_identification(struct ssh *ssh, int timeout_ms,
1083 const char *version_addendum)
1084{
1085 int remote_major, remote_minor, mismatch;
1086 size_t len, i, n;
1087 int r, expect_nl;
1088 u_char c;
1089 struct sshbuf *our_version = ssh->kex->server ?
1090 ssh->kex->server_version : ssh->kex->client_version;
1091 struct sshbuf *peer_version = ssh->kex->server ?
1092 ssh->kex->client_version : ssh->kex->server_version;
1093 char *our_version_string = NULL, *peer_version_string = NULL;
1094 char *cp, *remote_version = NULL;
1095
1096 /* Prepare and send our banner */
1097 sshbuf_reset(our_version);
1098 if (version_addendum != NULL && *version_addendum == '\0')
1099 version_addendum = NULL;
1100 if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n",
1101 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
1102 version_addendum == NULL ? "" : " ",
1103 version_addendum == NULL ? "" : version_addendum)) != 0) {
1104 error("%s: sshbuf_putf: %s", __func__, ssh_err(r));
1105 goto out;
1106 }
1107
1108 if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
1109 sshbuf_mutable_ptr(our_version),
1110 sshbuf_len(our_version)) != sshbuf_len(our_version)) {
1111 error("%s: write: %.100s", __func__, strerror(errno));
1112 r = SSH_ERR_SYSTEM_ERROR;
1113 goto out;
1114 }
1115 if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
1116 error("%s: sshbuf_consume_end: %s", __func__, ssh_err(r));
1117 goto out;
1118 }
1119 our_version_string = sshbuf_dup_string(our_version);
1120 if (our_version_string == NULL) {
1121 error("%s: sshbuf_dup_string failed", __func__);
1122 r = SSH_ERR_ALLOC_FAIL;
1123 goto out;
1124 }
1125 debug("Local version string %.100s", our_version_string);
1126
1127 /* Read other side's version identification. */
1128 for (n = 0; ; n++) {
1129 if (n >= SSH_MAX_PRE_BANNER_LINES) {
1130 send_error(ssh, "No SSH identification string "
1131 "received.");
1132 error("%s: No SSH version received in first %u lines "
1133 "from server", __func__, SSH_MAX_PRE_BANNER_LINES);
1134 r = SSH_ERR_INVALID_FORMAT;
1135 goto out;
1136 }
1137 sshbuf_reset(peer_version);
1138 expect_nl = 0;
1139 for (i = 0; ; i++) {
1140 if (timeout_ms > 0) {
1141 r = waitrfd(ssh_packet_get_connection_in(ssh),
1142 &timeout_ms);
1143 if (r == -1 && errno == ETIMEDOUT) {
1144 send_error(ssh, "Timed out waiting "
1145 "for SSH identification string.");
1146 error("Connection timed out during "
1147 "banner exchange");
1148 r = SSH_ERR_CONN_TIMEOUT;
1149 goto out;
1150 } else if (r == -1) {
1151 error("%s: %s",
1152 __func__, strerror(errno));
1153 r = SSH_ERR_SYSTEM_ERROR;
1154 goto out;
1155 }
1156 }
1157
1158 len = atomicio(read, ssh_packet_get_connection_in(ssh),
1159 &c, 1);
1160 if (len != 1 && errno == EPIPE) {
1161 error("%s: Connection closed by remote host",
1162 __func__);
1163 r = SSH_ERR_CONN_CLOSED;
1164 goto out;
1165 } else if (len != 1) {
1166 error("%s: read: %.100s",
1167 __func__, strerror(errno));
1168 r = SSH_ERR_SYSTEM_ERROR;
1169 goto out;
1170 }
1171 if (c == '\r') {
1172 expect_nl = 1;
1173 continue;
1174 }
1175 if (c == '\n')
1176 break;
1177 if (c == '\0' || expect_nl) {
1178 error("%s: banner line contains invalid "
1179 "characters", __func__);
1180 goto invalid;
1181 }
1182 if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
1183 error("%s: sshbuf_put: %s",
1184 __func__, ssh_err(r));
1185 goto out;
1186 }
1187 if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
1188 error("%s: banner line too long", __func__);
1189 goto invalid;
1190 }
1191 }
1192 /* Is this an actual protocol banner? */
1193 if (sshbuf_len(peer_version) > 4 &&
1194 memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0)
1195 break;
1196 /* If not, then just log the line and continue */
1197 if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
1198 error("%s: sshbuf_dup_string failed", __func__);
1199 r = SSH_ERR_ALLOC_FAIL;
1200 goto out;
1201 }
1202 /* Do not accept lines before the SSH ident from a client */
1203 if (ssh->kex->server) {
1204 error("%s: client sent invalid protocol identifier "
1205 "\"%.256s\"", __func__, cp);
1206 free(cp);
1207 goto invalid;
1208 }
1209 debug("%s: banner line %zu: %s", __func__, n, cp);
1210 free(cp);
1211 }
1212 peer_version_string = sshbuf_dup_string(peer_version);
1213 if (peer_version_string == NULL)
1214 error("%s: sshbuf_dup_string failed", __func__);
1215 /* XXX must be same size for sscanf */
1216 if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
1217 error("%s: calloc failed", __func__);
1218 r = SSH_ERR_ALLOC_FAIL;
1219 goto out;
1220 }
1221
1222 /*
1223 * Check that the versions match. In future this might accept
1224 * several versions and set appropriate flags to handle them.
1225 */
1226 if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n",
1227 &remote_major, &remote_minor, remote_version) != 3) {
1228 error("Bad remote protocol version identification: '%.100s'",
1229 peer_version_string);
1230 invalid:
1231 send_error(ssh, "Invalid SSH identification string.");
1232 r = SSH_ERR_INVALID_FORMAT;
1233 goto out;
1234 }
1235 debug("Remote protocol version %d.%d, remote software version %.100s",
1236 remote_major, remote_minor, remote_version);
1237 ssh->compat = compat_datafellows(remote_version);
1238
1239 mismatch = 0;
1240 switch (remote_major) {
1241 case 2:
1242 break;
1243 case 1:
1244 if (remote_minor != 99)
1245 mismatch = 1;
1246 break;
1247 default:
1248 mismatch = 1;
1249 break;
1250 }
1251 if (mismatch) {
1252 error("Protocol major versions differ: %d vs. %d",
1253 PROTOCOL_MAJOR_2, remote_major);
1254 send_error(ssh, "Protocol major versions differ.");
1255 r = SSH_ERR_NO_PROTOCOL_VERSION;
1256 goto out;
1257 }
1258
1259 if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) {
1260 logit("probed from %s port %d with %s. Don't panic.",
1261 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1262 peer_version_string);
1263 r = SSH_ERR_CONN_CLOSED; /* XXX */
1264 goto out;
1265 }
1266 if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) {
1267 logit("scanned from %s port %d with %s. Don't panic.",
1268 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
1269 peer_version_string);
1270 r = SSH_ERR_CONN_CLOSED; /* XXX */
1271 goto out;
1272 }
1273 if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
1274 logit("Remote version \"%.100s\" uses unsafe RSA signature "
1275 "scheme; disabling use of RSA keys", remote_version);
1276 }
1277 /* success */
1278 r = 0;
1279 out:
1280 free(our_version_string);
1281 free(peer_version_string);
1282 free(remote_version);
1283 return r;
1284}
1285
diff --git a/kex.h b/kex.h
index 0f67f58db..9ba860954 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.92 2018/12/07 03:39:40 djm Exp $ */ 1/* $OpenBSD: kex.h,v 1.93 2018/12/27 03:25:25 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -145,12 +145,12 @@ struct kex {
145 int ext_info_c; 145 int ext_info_c;
146 struct sshbuf *my; 146 struct sshbuf *my;
147 struct sshbuf *peer; 147 struct sshbuf *peer;
148 struct sshbuf *client_version;
149 struct sshbuf *server_version;
148 sig_atomic_t done; 150 sig_atomic_t done;
149 u_int flags; 151 u_int flags;
150 int hash_alg; 152 int hash_alg;
151 int ec_nid; 153 int ec_nid;
152 char *client_version_string;
153 char *server_version_string;
154 char *failed_choice; 154 char *failed_choice;
155 int (*verify_host_key)(struct sshkey *, struct ssh *); 155 int (*verify_host_key)(struct sshkey *, struct ssh *);
156 struct sshkey *(*load_host_public_key)(int, int, struct ssh *); 156 struct sshkey *(*load_host_public_key)(int, int, struct ssh *);
@@ -173,7 +173,10 @@ char *kex_alg_list(char);
173char *kex_names_cat(const char *, const char *); 173char *kex_names_cat(const char *, const char *);
174int kex_assemble_names(char **, const char *, const char *); 174int kex_assemble_names(char **, const char *, const char *);
175 175
176int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **); 176int kex_exchange_identification(struct ssh *, int, const char *);
177
178struct kex *kex_new(void);
179int kex_ready(struct ssh *, char *[PROPOSAL_MAX]);
177int kex_setup(struct ssh *, char *[PROPOSAL_MAX]); 180int kex_setup(struct ssh *, char *[PROPOSAL_MAX]);
178void kex_free_newkeys(struct newkeys *); 181void kex_free_newkeys(struct newkeys *);
179void kex_free(struct kex *); 182void kex_free(struct kex *);
@@ -199,22 +202,23 @@ int kexecdh_server(struct ssh *);
199int kexc25519_client(struct ssh *); 202int kexc25519_client(struct ssh *);
200int kexc25519_server(struct ssh *); 203int kexc25519_server(struct ssh *);
201 204
202int kex_dh_hash(int, const char *, const char *, 205int kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *,
203 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, 206 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
204 const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *); 207 const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
205 208
206int kexgex_hash(int, const char *, const char *, 209int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *,
207 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, 210 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
208 int, int, int, 211 int, int, int,
209 const BIGNUM *, const BIGNUM *, const BIGNUM *, 212 const BIGNUM *, const BIGNUM *, const BIGNUM *,
210 const BIGNUM *, const BIGNUM *, 213 const BIGNUM *, const BIGNUM *,
211 u_char *, size_t *); 214 u_char *, size_t *);
212 215
213int kex_ecdh_hash(int, const EC_GROUP *, const char *, const char *, 216int kex_ecdh_hash(int, const EC_GROUP *,
217 const struct sshbuf *, const struct sshbuf *,
214 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t, 218 const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
215 const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *); 219 const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *);
216 220
217int kex_c25519_hash(int, const char *, const char *, 221int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *,
218 const u_char *, size_t, const u_char *, size_t, 222 const u_char *, size_t, const u_char *, size_t,
219 const u_char *, size_t, const u_char *, const u_char *, 223 const u_char *, size_t, const u_char *, const u_char *,
220 const u_char *, size_t, u_char *, size_t *); 224 const u_char *, size_t, u_char *, size_t *);
diff --git a/kexc25519.c b/kexc25519.c
index 0897b8c51..712dd523d 100644
--- a/kexc25519.c
+++ b/kexc25519.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexc25519.c,v 1.10 2016/05/02 08:49:03 djm Exp $ */ 1/* $OpenBSD: kexc25519.c,v 1.11 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -84,8 +84,8 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
84int 84int
85kex_c25519_hash( 85kex_c25519_hash(
86 int hash_alg, 86 int hash_alg,
87 const char *client_version_string, 87 const struct sshbuf *client_version,
88 const char *server_version_string, 88 const struct sshbuf *server_version,
89 const u_char *ckexinit, size_t ckexinitlen, 89 const u_char *ckexinit, size_t ckexinitlen,
90 const u_char *skexinit, size_t skexinitlen, 90 const u_char *skexinit, size_t skexinitlen,
91 const u_char *serverhostkeyblob, size_t sbloblen, 91 const u_char *serverhostkeyblob, size_t sbloblen,
@@ -101,8 +101,8 @@ kex_c25519_hash(
101 return SSH_ERR_INVALID_ARGUMENT; 101 return SSH_ERR_INVALID_ARGUMENT;
102 if ((b = sshbuf_new()) == NULL) 102 if ((b = sshbuf_new()) == NULL)
103 return SSH_ERR_ALLOC_FAIL; 103 return SSH_ERR_ALLOC_FAIL;
104 if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 || 104 if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
105 (r = sshbuf_put_cstring(b, server_version_string)) < 0 || 105 (r = sshbuf_put_stringb(b, server_version)) < 0 ||
106 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ 106 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
107 (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 || 107 (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 ||
108 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || 108 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
diff --git a/kexc25519c.c b/kexc25519c.c
index a8d92149c..75e7d8c57 100644
--- a/kexc25519c.c
+++ b/kexc25519c.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexc25519c.c,v 1.9 2017/12/18 02:25:15 djm Exp $ */ 1/* $OpenBSD: kexc25519c.c,v 1.10 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -129,8 +129,8 @@ input_kex_c25519_reply(int type, u_int32_t seq, struct ssh *ssh)
129 hashlen = sizeof(hash); 129 hashlen = sizeof(hash);
130 if ((r = kex_c25519_hash( 130 if ((r = kex_c25519_hash(
131 kex->hash_alg, 131 kex->hash_alg,
132 kex->client_version_string, 132 kex->client_version,
133 kex->server_version_string, 133 kex->server_version,
134 sshbuf_ptr(kex->my), sshbuf_len(kex->my), 134 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
135 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 135 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
136 server_host_key_blob, sbloblen, 136 server_host_key_blob, sbloblen,
diff --git a/kexc25519s.c b/kexc25519s.c
index 0800a7a4b..81f816e56 100644
--- a/kexc25519s.c
+++ b/kexc25519s.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexc25519s.c,v 1.11 2017/05/31 04:19:28 djm Exp $ */ 1/* $OpenBSD: kexc25519s.c,v 1.12 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -110,8 +110,8 @@ input_kex_c25519_init(int type, u_int32_t seq, struct ssh *ssh)
110 hashlen = sizeof(hash); 110 hashlen = sizeof(hash);
111 if ((r = kex_c25519_hash( 111 if ((r = kex_c25519_hash(
112 kex->hash_alg, 112 kex->hash_alg,
113 kex->client_version_string, 113 kex->client_version,
114 kex->server_version_string, 114 kex->server_version,
115 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 115 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
116 sshbuf_ptr(kex->my), sshbuf_len(kex->my), 116 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
117 server_host_key_blob, sbloblen, 117 server_host_key_blob, sbloblen,
diff --git a/kexdh.c b/kexdh.c
index e6925b186..34c55ef9f 100644
--- a/kexdh.c
+++ b/kexdh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexdh.c,v 1.26 2016/05/02 10:26:04 djm Exp $ */ 1/* $OpenBSD: kexdh.c,v 1.27 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -46,8 +46,8 @@
46int 46int
47kex_dh_hash( 47kex_dh_hash(
48 int hash_alg, 48 int hash_alg,
49 const char *client_version_string, 49 const struct sshbuf *client_version,
50 const char *server_version_string, 50 const struct sshbuf *server_version,
51 const u_char *ckexinit, size_t ckexinitlen, 51 const u_char *ckexinit, size_t ckexinitlen,
52 const u_char *skexinit, size_t skexinitlen, 52 const u_char *skexinit, size_t skexinitlen,
53 const u_char *serverhostkeyblob, size_t sbloblen, 53 const u_char *serverhostkeyblob, size_t sbloblen,
@@ -63,8 +63,8 @@ kex_dh_hash(
63 return SSH_ERR_INVALID_ARGUMENT; 63 return SSH_ERR_INVALID_ARGUMENT;
64 if ((b = sshbuf_new()) == NULL) 64 if ((b = sshbuf_new()) == NULL)
65 return SSH_ERR_ALLOC_FAIL; 65 return SSH_ERR_ALLOC_FAIL;
66 if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || 66 if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
67 (r = sshbuf_put_cstring(b, server_version_string)) != 0 || 67 (r = sshbuf_put_stringb(b, server_version)) < 0 ||
68 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ 68 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
69 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || 69 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
70 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || 70 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
diff --git a/kexdhc.c b/kexdhc.c
index 8b56377ad..b367832d5 100644
--- a/kexdhc.c
+++ b/kexdhc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexdhc.c,v 1.22 2018/02/07 02:06:51 jsing Exp $ */ 1/* $OpenBSD: kexdhc.c,v 1.24 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -178,8 +178,8 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
178 hashlen = sizeof(hash); 178 hashlen = sizeof(hash);
179 if ((r = kex_dh_hash( 179 if ((r = kex_dh_hash(
180 kex->hash_alg, 180 kex->hash_alg,
181 kex->client_version_string, 181 kex->client_version,
182 kex->server_version_string, 182 kex->server_version,
183 sshbuf_ptr(kex->my), sshbuf_len(kex->my), 183 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
184 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 184 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
185 server_host_key_blob, sbloblen, 185 server_host_key_blob, sbloblen,
diff --git a/kexdhs.c b/kexdhs.c
index 337aab5be..adf70babd 100644
--- a/kexdhs.c
+++ b/kexdhs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexdhs.c,v 1.27 2018/04/10 00:10:49 djm Exp $ */ 1/* $OpenBSD: kexdhs.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -166,8 +166,8 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
166 hashlen = sizeof(hash); 166 hashlen = sizeof(hash);
167 if ((r = kex_dh_hash( 167 if ((r = kex_dh_hash(
168 kex->hash_alg, 168 kex->hash_alg,
169 kex->client_version_string, 169 kex->client_version,
170 kex->server_version_string, 170 kex->server_version,
171 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 171 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
172 sshbuf_ptr(kex->my), sshbuf_len(kex->my), 172 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
173 server_host_key_blob, sbloblen, 173 server_host_key_blob, sbloblen,
diff --git a/kexecdh.c b/kexecdh.c
index 2a4fec6b1..4380427ea 100644
--- a/kexecdh.c
+++ b/kexecdh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */ 1/* $OpenBSD: kexecdh.c,v 1.7 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -50,8 +50,8 @@ int
50kex_ecdh_hash( 50kex_ecdh_hash(
51 int hash_alg, 51 int hash_alg,
52 const EC_GROUP *ec_group, 52 const EC_GROUP *ec_group,
53 const char *client_version_string, 53 const struct sshbuf *client_version,
54 const char *server_version_string, 54 const struct sshbuf *server_version,
55 const u_char *ckexinit, size_t ckexinitlen, 55 const u_char *ckexinit, size_t ckexinitlen,
56 const u_char *skexinit, size_t skexinitlen, 56 const u_char *skexinit, size_t skexinitlen,
57 const u_char *serverhostkeyblob, size_t sbloblen, 57 const u_char *serverhostkeyblob, size_t sbloblen,
@@ -67,8 +67,8 @@ kex_ecdh_hash(
67 return SSH_ERR_INVALID_ARGUMENT; 67 return SSH_ERR_INVALID_ARGUMENT;
68 if ((b = sshbuf_new()) == NULL) 68 if ((b = sshbuf_new()) == NULL)
69 return SSH_ERR_ALLOC_FAIL; 69 return SSH_ERR_ALLOC_FAIL;
70 if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || 70 if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
71 (r = sshbuf_put_cstring(b, server_version_string)) != 0 || 71 (r = sshbuf_put_stringb(b, server_version)) < 0 ||
72 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ 72 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
73 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || 73 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
74 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || 74 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
diff --git a/kexecdhc.c b/kexecdhc.c
index ac146a362..af556dc58 100644
--- a/kexecdhc.c
+++ b/kexecdhc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexecdhc.c,v 1.13 2018/02/07 02:06:51 jsing Exp $ */ 1/* $OpenBSD: kexecdhc.c,v 1.14 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -175,8 +175,8 @@ input_kex_ecdh_reply(int type, u_int32_t seq, struct ssh *ssh)
175 if ((r = kex_ecdh_hash( 175 if ((r = kex_ecdh_hash(
176 kex->hash_alg, 176 kex->hash_alg,
177 group, 177 group,
178 kex->client_version_string, 178 kex->client_version,
179 kex->server_version_string, 179 kex->server_version,
180 sshbuf_ptr(kex->my), sshbuf_len(kex->my), 180 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
181 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 181 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
182 server_host_key_blob, sbloblen, 182 server_host_key_blob, sbloblen,
diff --git a/kexecdhs.c b/kexecdhs.c
index af4f30309..c690feffe 100644
--- a/kexecdhs.c
+++ b/kexecdhs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexecdhs.c,v 1.17 2018/02/07 02:06:51 jsing Exp $ */ 1/* $OpenBSD: kexecdhs.c,v 1.18 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -145,8 +145,8 @@ input_kex_ecdh_init(int type, u_int32_t seq, struct ssh *ssh)
145 if ((r = kex_ecdh_hash( 145 if ((r = kex_ecdh_hash(
146 kex->hash_alg, 146 kex->hash_alg,
147 group, 147 group,
148 kex->client_version_string, 148 kex->client_version,
149 kex->server_version_string, 149 kex->server_version,
150 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 150 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
151 sshbuf_ptr(kex->my), sshbuf_len(kex->my), 151 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
152 server_host_key_blob, sbloblen, 152 server_host_key_blob, sbloblen,
diff --git a/kexgex.c b/kexgex.c
index 3ca4bd370..a5d591b0a 100644
--- a/kexgex.c
+++ b/kexgex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexgex.c,v 1.29 2015/01/19 20:16:15 markus Exp $ */ 1/* $OpenBSD: kexgex.c,v 1.30 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -46,8 +46,8 @@
46int 46int
47kexgex_hash( 47kexgex_hash(
48 int hash_alg, 48 int hash_alg,
49 const char *client_version_string, 49 const struct sshbuf *client_version,
50 const char *server_version_string, 50 const struct sshbuf *server_version,
51 const u_char *ckexinit, size_t ckexinitlen, 51 const u_char *ckexinit, size_t ckexinitlen,
52 const u_char *skexinit, size_t skexinitlen, 52 const u_char *skexinit, size_t skexinitlen,
53 const u_char *serverhostkeyblob, size_t sbloblen, 53 const u_char *serverhostkeyblob, size_t sbloblen,
@@ -66,8 +66,8 @@ kexgex_hash(
66 return SSH_ERR_INVALID_ARGUMENT; 66 return SSH_ERR_INVALID_ARGUMENT;
67 if ((b = sshbuf_new()) == NULL) 67 if ((b = sshbuf_new()) == NULL)
68 return SSH_ERR_ALLOC_FAIL; 68 return SSH_ERR_ALLOC_FAIL;
69 if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 || 69 if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
70 (r = sshbuf_put_cstring(b, server_version_string)) != 0 || 70 (r = sshbuf_put_stringb(b, server_version)) < 0 ||
71 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ 71 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
72 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 || 72 (r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
73 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 || 73 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
diff --git a/kexgexc.c b/kexgexc.c
index 0d07f73c7..f2be35ab2 100644
--- a/kexgexc.c
+++ b/kexgexc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexgexc.c,v 1.27 2018/02/07 02:06:51 jsing Exp $ */ 1/* $OpenBSD: kexgexc.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -222,8 +222,8 @@ input_kex_dh_gex_reply(int type, u_int32_t seq, struct ssh *ssh)
222 hashlen = sizeof(hash); 222 hashlen = sizeof(hash);
223 if ((r = kexgex_hash( 223 if ((r = kexgex_hash(
224 kex->hash_alg, 224 kex->hash_alg,
225 kex->client_version_string, 225 kex->client_version,
226 kex->server_version_string, 226 kex->server_version,
227 sshbuf_ptr(kex->my), sshbuf_len(kex->my), 227 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
228 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 228 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
229 server_host_key_blob, sbloblen, 229 server_host_key_blob, sbloblen,
diff --git a/kexgexs.c b/kexgexs.c
index dc9c0bc60..cd0e758c4 100644
--- a/kexgexs.c
+++ b/kexgexs.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexgexs.c,v 1.35 2018/10/04 00:04:41 djm Exp $ */ 1/* $OpenBSD: kexgexs.c,v 1.36 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Niels Provos. All rights reserved. 3 * Copyright (c) 2000 Niels Provos. All rights reserved.
4 * Copyright (c) 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2001 Markus Friedl. All rights reserved.
@@ -198,8 +198,8 @@ input_kex_dh_gex_init(int type, u_int32_t seq, struct ssh *ssh)
198 hashlen = sizeof(hash); 198 hashlen = sizeof(hash);
199 if ((r = kexgex_hash( 199 if ((r = kexgex_hash(
200 kex->hash_alg, 200 kex->hash_alg,
201 kex->client_version_string, 201 kex->client_version,
202 kex->server_version_string, 202 kex->server_version,
203 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer), 203 sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
204 sshbuf_ptr(kex->my), sshbuf_len(kex->my), 204 sshbuf_ptr(kex->my), sshbuf_len(kex->my),
205 server_host_key_blob, sbloblen, 205 server_host_key_blob, sbloblen,
diff --git a/misc.c b/misc.c
index 275e68141..bfd786ef8 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: misc.c,v 1.135 2018/12/07 04:36:09 dtucker Exp $ */ 1/* $OpenBSD: misc.c,v 1.136 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2005,2006 Damien Miller. All rights reserved. 4 * Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@@ -38,6 +38,7 @@
38#ifdef HAVE_LIBGEN_H 38#ifdef HAVE_LIBGEN_H
39# include <libgen.h> 39# include <libgen.h>
40#endif 40#endif
41#include <poll.h>
41#include <signal.h> 42#include <signal.h>
42#include <stdarg.h> 43#include <stdarg.h>
43#include <stdio.h> 44#include <stdio.h>
@@ -234,6 +235,80 @@ set_rdomain(int fd, const char *name)
234#endif 235#endif
235} 236}
236 237
238/*
239 * Wait up to *timeoutp milliseconds for fd to be readable. Updates
240 * *timeoutp with time remaining.
241 * Returns 0 if fd ready or -1 on timeout or error (see errno).
242 */
243int
244waitrfd(int fd, int *timeoutp)
245{
246 struct pollfd pfd;
247 struct timeval t_start;
248 int oerrno, r;
249
250 monotime_tv(&t_start);
251 pfd.fd = fd;
252 pfd.events = POLLIN;
253 for (; *timeoutp >= 0;) {
254 r = poll(&pfd, 1, *timeoutp);
255 oerrno = errno;
256 ms_subtract_diff(&t_start, timeoutp);
257 errno = oerrno;
258 if (r > 0)
259 return 0;
260 else if (r == -1 && errno != EAGAIN)
261 return -1;
262 else if (r == 0)
263 break;
264 }
265 /* timeout */
266 errno = ETIMEDOUT;
267 return -1;
268}
269
270/*
271 * Attempt a non-blocking connect(2) to the specified address, waiting up to
272 * *timeoutp milliseconds for the connection to complete. If the timeout is
273 * <=0, then wait indefinitely.
274 *
275 * Returns 0 on success or -1 on failure.
276 */
277int
278timeout_connect(int sockfd, const struct sockaddr *serv_addr,
279 socklen_t addrlen, int *timeoutp)
280{
281 int optval = 0;
282 socklen_t optlen = sizeof(optval);
283
284 /* No timeout: just do a blocking connect() */
285 if (timeoutp == NULL || *timeoutp <= 0)
286 return connect(sockfd, serv_addr, addrlen);
287
288 set_nonblock(sockfd);
289 if (connect(sockfd, serv_addr, addrlen) == 0) {
290 /* Succeeded already? */
291 unset_nonblock(sockfd);
292 return 0;
293 } else if (errno != EINPROGRESS)
294 return -1;
295
296 if (waitrfd(sockfd, timeoutp) == -1)
297 return -1;
298
299 /* Completed or failed */
300 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) {
301 debug("getsockopt: %s", strerror(errno));
302 return -1;
303 }
304 if (optval != 0) {
305 errno = optval;
306 return -1;
307 }
308 unset_nonblock(sockfd);
309 return 0;
310}
311
237/* Characters considered whitespace in strsep calls. */ 312/* Characters considered whitespace in strsep calls. */
238#define WHITESPACE " \t\r\n" 313#define WHITESPACE " \t\r\n"
239#define QUOTE "\"" 314#define QUOTE "\""
diff --git a/misc.h b/misc.h
index 2dd61dc32..47177d838 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: misc.h,v 1.77 2018/12/07 04:36:09 dtucker Exp $ */ 1/* $OpenBSD: misc.h,v 1.78 2018/12/27 03:25:25 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -17,6 +17,7 @@
17 17
18#include <sys/time.h> 18#include <sys/time.h>
19#include <sys/types.h> 19#include <sys/types.h>
20#include <sys/socket.h>
20 21
21/* Data structure for representing a forwarding request. */ 22/* Data structure for representing a forwarding request. */
22struct Forward { 23struct Forward {
@@ -51,6 +52,8 @@ void set_nodelay(int);
51int set_reuseaddr(int); 52int set_reuseaddr(int);
52char *get_rdomain(int); 53char *get_rdomain(int);
53int set_rdomain(int, const char *); 54int set_rdomain(int, const char *);
55int waitrfd(int, int *);
56int timeout_connect(int, const struct sockaddr *, socklen_t, int *);
54int a2port(const char *); 57int a2port(const char *);
55int a2tun(const char *, int *); 58int a2tun(const char *, int *);
56char *put_host_port(const char *, u_short); 59char *put_host_port(const char *, u_short);
diff --git a/packet.c b/packet.c
index dcf35e6e6..e7e6d27a7 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.278 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -58,6 +58,7 @@
58#include <string.h> 58#include <string.h>
59#include <unistd.h> 59#include <unistd.h>
60#include <limits.h> 60#include <limits.h>
61#include <poll.h>
61#include <signal.h> 62#include <signal.h>
62#include <time.h> 63#include <time.h>
63 64
@@ -228,6 +229,7 @@ ssh_alloc_session_state(void)
228 229
229 if ((ssh = calloc(1, sizeof(*ssh))) == NULL || 230 if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
230 (state = calloc(1, sizeof(*state))) == NULL || 231 (state = calloc(1, sizeof(*state))) == NULL ||
232 (ssh->kex = kex_new()) == NULL ||
231 (state->input = sshbuf_new()) == NULL || 233 (state->input = sshbuf_new()) == NULL ||
232 (state->output = sshbuf_new()) == NULL || 234 (state->output = sshbuf_new()) == NULL ||
233 (state->outgoing_packet = sshbuf_new()) == NULL || 235 (state->outgoing_packet = sshbuf_new()) == NULL ||
@@ -250,6 +252,10 @@ ssh_alloc_session_state(void)
250 ssh->state = state; 252 ssh->state = state;
251 return ssh; 253 return ssh;
252 fail: 254 fail:
255 if (ssh) {
256 kex_free(ssh->kex);
257 free(ssh);
258 }
253 if (state) { 259 if (state) {
254 sshbuf_free(state->input); 260 sshbuf_free(state->input);
255 sshbuf_free(state->output); 261 sshbuf_free(state->output);
@@ -257,7 +263,6 @@ ssh_alloc_session_state(void)
257 sshbuf_free(state->outgoing_packet); 263 sshbuf_free(state->outgoing_packet);
258 free(state); 264 free(state);
259 } 265 }
260 free(ssh);
261 return NULL; 266 return NULL;
262} 267}
263 268
@@ -272,8 +277,7 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
272int 277int
273ssh_packet_is_rekeying(struct ssh *ssh) 278ssh_packet_is_rekeying(struct ssh *ssh)
274{ 279{
275 return ssh->state->rekeying || 280 return ssh->state->rekeying || ssh->kex->done == 0;
276 (ssh->kex != NULL && ssh->kex->done == 0);
277} 281}
278 282
279/* 283/*
@@ -932,7 +936,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
932 return 0; 936 return 0;
933 937
934 /* Haven't keyed yet or KEX in progress. */ 938 /* Haven't keyed yet or KEX in progress. */
935 if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh)) 939 if (ssh_packet_is_rekeying(ssh))
936 return 0; 940 return 0;
937 941
938 /* Peer can't rekey */ 942 /* Peer can't rekey */
@@ -2123,6 +2127,7 @@ void
2123ssh_packet_set_server(struct ssh *ssh) 2127ssh_packet_set_server(struct ssh *ssh)
2124{ 2128{
2125 ssh->state->server_side = 1; 2129 ssh->state->server_side = 1;
2130 ssh->kex->server = 1; /* XXX unify? */
2126} 2131}
2127 2132
2128void 2133void
@@ -2175,9 +2180,9 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
2175 (r = sshbuf_put_u32(m, kex->kex_type)) != 0 || 2180 (r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
2176 (r = sshbuf_put_stringb(m, kex->my)) != 0 || 2181 (r = sshbuf_put_stringb(m, kex->my)) != 0 ||
2177 (r = sshbuf_put_stringb(m, kex->peer)) != 0 || 2182 (r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
2178 (r = sshbuf_put_u32(m, kex->flags)) != 0 || 2183 (r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
2179 (r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 || 2184 (r = sshbuf_put_stringb(m, kex->server_version)) != 0 ||
2180 (r = sshbuf_put_cstring(m, kex->server_version_string)) != 0) 2185 (r = sshbuf_put_u32(m, kex->flags)) != 0)
2181 return r; 2186 return r;
2182 return 0; 2187 return 0;
2183} 2188}
@@ -2327,12 +2332,8 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
2327 struct kex *kex; 2332 struct kex *kex;
2328 int r; 2333 int r;
2329 2334
2330 if ((kex = calloc(1, sizeof(struct kex))) == NULL || 2335 if ((kex = kex_new()) == NULL)
2331 (kex->my = sshbuf_new()) == NULL || 2336 return SSH_ERR_ALLOC_FAIL;
2332 (kex->peer = sshbuf_new()) == NULL) {
2333 r = SSH_ERR_ALLOC_FAIL;
2334 goto out;
2335 }
2336 if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 || 2337 if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
2337 (r = sshbuf_get_u32(m, &kex->we_need)) != 0 || 2338 (r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
2338 (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 || 2339 (r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 ||
@@ -2341,23 +2342,20 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
2341 (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 || 2342 (r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
2342 (r = sshbuf_get_stringb(m, kex->my)) != 0 || 2343 (r = sshbuf_get_stringb(m, kex->my)) != 0 ||
2343 (r = sshbuf_get_stringb(m, kex->peer)) != 0 || 2344 (r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
2344 (r = sshbuf_get_u32(m, &kex->flags)) != 0 || 2345 (r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
2345 (r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 || 2346 (r = sshbuf_get_stringb(m, kex->server_version)) != 0 ||
2346 (r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0) 2347 (r = sshbuf_get_u32(m, &kex->flags)) != 0)
2347 goto out; 2348 goto out;
2348 kex->server = 1; 2349 kex->server = 1;
2349 kex->done = 1; 2350 kex->done = 1;
2350 r = 0; 2351 r = 0;
2351 out: 2352 out:
2352 if (r != 0 || kexp == NULL) { 2353 if (r != 0 || kexp == NULL) {
2353 if (kex != NULL) { 2354 kex_free(kex);
2354 sshbuf_free(kex->my);
2355 sshbuf_free(kex->peer);
2356 free(kex);
2357 }
2358 if (kexp != NULL) 2355 if (kexp != NULL)
2359 *kexp = NULL; 2356 *kexp = NULL;
2360 } else { 2357 } else {
2358 kex_free(*kexp);
2361 *kexp = kex; 2359 *kexp = kex;
2362 } 2360 }
2363 return r; 2361 return r;
diff --git a/ssh.c b/ssh.c
index c6cb7847d..16536a97a 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.496 2018/11/23 05:08:07 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.497 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -1490,7 +1490,7 @@ main(int ac, char **av)
1490 signal(SIGCHLD, main_sigchld_handler); 1490 signal(SIGCHLD, main_sigchld_handler);
1491 1491
1492 /* Log into the remote system. Never returns if the login fails. */ 1492 /* Log into the remote system. Never returns if the login fails. */
1493 ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, 1493 ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr,
1494 options.port, pw, timeout_ms); 1494 options.port, pw, timeout_ms);
1495 1495
1496 if (packet_connection_is_on_socket()) { 1496 if (packet_connection_is_on_socket()) {
diff --git a/ssh.h b/ssh.h
index 5abfd7a68..dda6f617e 100644
--- a/ssh.h
+++ b/ssh.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.h,v 1.88 2018/06/06 18:29:18 markus Exp $ */ 1/* $OpenBSD: ssh.h,v 1.89 2018/12/27 03:25:25 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -93,3 +93,7 @@
93 93
94/* Listen backlog for sshd, ssh-agent and forwarding sockets */ 94/* Listen backlog for sshd, ssh-agent and forwarding sockets */
95#define SSH_LISTEN_BACKLOG 128 95#define SSH_LISTEN_BACKLOG 128
96
97/* Limits for banner exchange */
98#define SSH_MAX_BANNER_LEN 8192
99#define SSH_MAX_PRE_BANNER_LINES 1024
diff --git a/ssh_api.c b/ssh_api.c
index 53bbc9b49..ab209c4ca 100644
--- a/ssh_api.c
+++ b/ssh_api.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */ 1/* $OpenBSD: ssh_api.c,v 1.9 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2012 Markus Friedl. All rights reserved. 3 * Copyright (c) 2012 Markus Friedl. All rights reserved.
4 * 4 *
@@ -34,8 +34,8 @@
34#include <string.h> 34#include <string.h>
35 35
36int _ssh_exchange_banner(struct ssh *); 36int _ssh_exchange_banner(struct ssh *);
37int _ssh_send_banner(struct ssh *, char **); 37int _ssh_send_banner(struct ssh *, struct sshbuf *);
38int _ssh_read_banner(struct ssh *, char **); 38int _ssh_read_banner(struct ssh *, struct sshbuf *);
39int _ssh_order_hostkeyalgs(struct ssh *); 39int _ssh_order_hostkeyalgs(struct ssh *);
40int _ssh_verify_host_key(struct sshkey *, struct ssh *); 40int _ssh_verify_host_key(struct sshkey *, struct ssh *);
41struct sshkey *_ssh_host_public_key(int, int, struct ssh *); 41struct sshkey *_ssh_host_public_key(int, int, struct ssh *);
@@ -92,7 +92,7 @@ ssh_init(struct ssh **sshp, int is_server, struct kex_params *kex_params)
92 92
93 /* Initialize key exchange */ 93 /* Initialize key exchange */
94 proposal = kex_params ? kex_params->proposal : myproposal; 94 proposal = kex_params ? kex_params->proposal : myproposal;
95 if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) { 95 if ((r = kex_ready(ssh, proposal)) != 0) {
96 ssh_free(ssh); 96 ssh_free(ssh);
97 return r; 97 return r;
98 } 98 }
@@ -236,8 +236,8 @@ ssh_packet_next(struct ssh *ssh, u_char *typep)
236 * enough data. 236 * enough data.
237 */ 237 */
238 *typep = SSH_MSG_NONE; 238 *typep = SSH_MSG_NONE;
239 if (ssh->kex->client_version_string == NULL || 239 if (sshbuf_len(ssh->kex->client_version) == 0 ||
240 ssh->kex->server_version_string == NULL) 240 sshbuf_len(ssh->kex->server_version) == 0)
241 return _ssh_exchange_banner(ssh); 241 return _ssh_exchange_banner(ssh);
242 /* 242 /*
243 * If we enough data and a dispatch function then 243 * If we enough data and a dispatch function then
@@ -312,39 +312,46 @@ ssh_input_space(struct ssh *ssh, size_t len)
312 312
313/* Read other side's version identification. */ 313/* Read other side's version identification. */
314int 314int
315_ssh_read_banner(struct ssh *ssh, char **bannerp) 315_ssh_read_banner(struct ssh *ssh, struct sshbuf *banner)
316{ 316{
317 struct sshbuf *input; 317 struct sshbuf *input = ssh_packet_get_input(ssh);
318 const char *s;
319 char buf[256], remote_version[256]; /* must be same size! */
320 const char *mismatch = "Protocol mismatch.\r\n"; 318 const char *mismatch = "Protocol mismatch.\r\n";
321 int r, remote_major, remote_minor; 319 const u_char *s = sshbuf_ptr(input);
322 size_t i, n, j, len; 320 u_char c;
321 char *cp, *remote_version;
322 int r, remote_major, remote_minor, expect_nl;
323 size_t n, j;
323 324
324 *bannerp = NULL;
325 input = ssh_packet_get_input(ssh);
326 len = sshbuf_len(input);
327 s = (const char *)sshbuf_ptr(input);
328 for (j = n = 0;;) { 325 for (j = n = 0;;) {
329 for (i = 0; i < sizeof(buf) - 1; i++) { 326 sshbuf_reset(banner);
330 if (j >= len) 327 expect_nl = 0;
331 return (0); 328 for (;;) {
332 buf[i] = s[j++]; 329 if (j >= sshbuf_len(input))
333 if (buf[i] == '\r') { 330 return 0; /* insufficient data in input buf */
334 buf[i] = '\n'; 331 c = s[j++];
335 buf[i + 1] = 0; 332 if (c == '\r') {
336 continue; /**XXX wait for \n */ 333 expect_nl = 1;
334 continue;
337 } 335 }
338 if (buf[i] == '\n') { 336 if (c == '\n')
339 buf[i + 1] = 0;
340 break; 337 break;
341 } 338 if (expect_nl)
339 goto bad;
340 if ((r = sshbuf_put_u8(banner, c)) != 0)
341 return r;
342 if (sshbuf_len(banner) > SSH_MAX_BANNER_LEN)
343 goto bad;
342 } 344 }
343 buf[sizeof(buf) - 1] = 0; 345 if (sshbuf_len(banner) >= 4 &&
344 if (strncmp(buf, "SSH-", 4) == 0) 346 memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0)
345 break; 347 break;
346 debug("ssh_exchange_identification: %s", buf); 348 if ((cp = sshbuf_dup_string(banner)) == NULL)
347 if (ssh->kex->server || ++n > 65536) { 349 return SSH_ERR_ALLOC_FAIL;
350 debug("%s: %s", __func__, cp);
351 free(cp);
352 /* Accept lines before banner only on client */
353 if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) {
354 bad:
348 if ((r = sshbuf_put(ssh_packet_get_output(ssh), 355 if ((r = sshbuf_put(ssh_packet_get_output(ssh),
349 mismatch, strlen(mismatch))) != 0) 356 mismatch, strlen(mismatch))) != 0)
350 return r; 357 return r;
@@ -354,11 +361,17 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
354 if ((r = sshbuf_consume(input, j)) != 0) 361 if ((r = sshbuf_consume(input, j)) != 0)
355 return r; 362 return r;
356 363
364 if ((cp = sshbuf_dup_string(banner)) == NULL)
365 return SSH_ERR_ALLOC_FAIL;
366 /* XXX remote version must be the same size as banner for sscanf */
367 if ((remote_version = calloc(1, sshbuf_len(banner))) == NULL)
368 return SSH_ERR_ALLOC_FAIL;
369
357 /* 370 /*
358 * Check that the versions match. In future this might accept 371 * Check that the versions match. In future this might accept
359 * several versions and set appropriate flags to handle them. 372 * several versions and set appropriate flags to handle them.
360 */ 373 */
361 if (sscanf(buf, "SSH-%d.%d-%[^\n]\n", 374 if (sscanf(cp, "SSH-%d.%d-%[^\n]\n",
362 &remote_major, &remote_minor, remote_version) != 3) 375 &remote_major, &remote_minor, remote_version) != 3)
363 return SSH_ERR_INVALID_FORMAT; 376 return SSH_ERR_INVALID_FORMAT;
364 debug("Remote protocol version %d.%d, remote software version %.100s", 377 debug("Remote protocol version %d.%d, remote software version %.100s",
@@ -371,27 +384,29 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
371 } 384 }
372 if (remote_major != 2) 385 if (remote_major != 2)
373 return SSH_ERR_PROTOCOL_MISMATCH; 386 return SSH_ERR_PROTOCOL_MISMATCH;
374 chop(buf); 387 debug("Remote version string %.100s", cp);
375 debug("Remote version string %.100s", buf); 388 free(cp);
376 if ((*bannerp = strdup(buf)) == NULL)
377 return SSH_ERR_ALLOC_FAIL;
378 return 0; 389 return 0;
379} 390}
380 391
381/* Send our own protocol version identification. */ 392/* Send our own protocol version identification. */
382int 393int
383_ssh_send_banner(struct ssh *ssh, char **bannerp) 394_ssh_send_banner(struct ssh *ssh, struct sshbuf *banner)
384{ 395{
385 char buf[256]; 396 char *cp;
386 int r; 397 int r;
387 398
388 snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION); 399 if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_VERSION)) != 0)
389 if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0) 400 return r;
401 if ((r = sshbuf_putb(ssh_packet_get_output(ssh), banner)) != 0)
402 return r;
403 /* Remove trailing \r\n */
404 if ((r = sshbuf_consume_end(banner, 2)) != 0)
390 return r; 405 return r;
391 chop(buf); 406 if ((cp = sshbuf_dup_string(banner)) == NULL)
392 debug("Local version string %.100s", buf);
393 if ((*bannerp = strdup(buf)) == NULL)
394 return SSH_ERR_ALLOC_FAIL; 407 return SSH_ERR_ALLOC_FAIL;
408 debug("Local version string %.100s", cp);
409 free(cp);
395 return 0; 410 return 0;
396} 411}
397 412
@@ -408,25 +423,25 @@ _ssh_exchange_banner(struct ssh *ssh)
408 423
409 r = 0; 424 r = 0;
410 if (kex->server) { 425 if (kex->server) {
411 if (kex->server_version_string == NULL) 426 if (sshbuf_len(ssh->kex->server_version) == 0)
412 r = _ssh_send_banner(ssh, &kex->server_version_string); 427 r = _ssh_send_banner(ssh, ssh->kex->server_version);
413 if (r == 0 && 428 if (r == 0 &&
414 kex->server_version_string != NULL && 429 sshbuf_len(ssh->kex->server_version) != 0 &&
415 kex->client_version_string == NULL) 430 sshbuf_len(ssh->kex->client_version) == 0)
416 r = _ssh_read_banner(ssh, &kex->client_version_string); 431 r = _ssh_read_banner(ssh, ssh->kex->client_version);
417 } else { 432 } else {
418 if (kex->server_version_string == NULL) 433 if (sshbuf_len(ssh->kex->server_version) == 0)
419 r = _ssh_read_banner(ssh, &kex->server_version_string); 434 r = _ssh_read_banner(ssh, ssh->kex->server_version);
420 if (r == 0 && 435 if (r == 0 &&
421 kex->server_version_string != NULL && 436 sshbuf_len(ssh->kex->server_version) != 0 &&
422 kex->client_version_string == NULL) 437 sshbuf_len(ssh->kex->client_version) == 0)
423 r = _ssh_send_banner(ssh, &kex->client_version_string); 438 r = _ssh_send_banner(ssh, ssh->kex->client_version);
424 } 439 }
425 if (r != 0) 440 if (r != 0)
426 return r; 441 return r;
427 /* start initial kex as soon as we have exchanged the banners */ 442 /* start initial kex as soon as we have exchanged the banners */
428 if (kex->server_version_string != NULL && 443 if (sshbuf_len(ssh->kex->server_version) != 0 &&
429 kex->client_version_string != NULL) { 444 sshbuf_len(ssh->kex->client_version) != 0) {
430 if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 || 445 if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 ||
431 (r = kex_send_kexinit(ssh)) != 0) 446 (r = kex_send_kexinit(ssh)) != 0)
432 return r; 447 return r;
diff --git a/sshconnect.c b/sshconnect.c
index 4862da5ed..884e33628 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.c,v 1.308 2018/11/18 22:43:29 dtucker Exp $ */ 1/* $OpenBSD: sshconnect.c,v 1.309 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -68,9 +68,8 @@
68#include "authfile.h" 68#include "authfile.h"
69#include "ssherr.h" 69#include "ssherr.h"
70#include "authfd.h" 70#include "authfd.h"
71#include "kex.h"
71 72
72char *client_version_string = NULL;
73char *server_version_string = NULL;
74struct sshkey *previous_host_key = NULL; 73struct sshkey *previous_host_key = NULL;
75 74
76static int matching_host_key_dns = 0; 75static int matching_host_key_dns = 0;
@@ -445,73 +444,6 @@ fail:
445} 444}
446 445
447/* 446/*
448 * Wait up to *timeoutp milliseconds for fd to be readable. Updates
449 * *timeoutp with time remaining.
450 * Returns 0 if fd ready or -1 on timeout or error (see errno).
451 */
452static int
453waitrfd(int fd, int *timeoutp)
454{
455 struct pollfd pfd;
456 struct timeval t_start;
457 int oerrno, r;
458
459 monotime_tv(&t_start);
460 pfd.fd = fd;
461 pfd.events = POLLIN;
462 for (; *timeoutp >= 0;) {
463 r = poll(&pfd, 1, *timeoutp);
464 oerrno = errno;
465 ms_subtract_diff(&t_start, timeoutp);
466 errno = oerrno;
467 if (r > 0)
468 return 0;
469 else if (r == -1 && errno != EAGAIN)
470 return -1;
471 else if (r == 0)
472 break;
473 }
474 /* timeout */
475 errno = ETIMEDOUT;
476 return -1;
477}
478
479static int
480timeout_connect(int sockfd, const struct sockaddr *serv_addr,
481 socklen_t addrlen, int *timeoutp)
482{
483 int optval = 0;
484 socklen_t optlen = sizeof(optval);
485
486 /* No timeout: just do a blocking connect() */
487 if (*timeoutp <= 0)
488 return connect(sockfd, serv_addr, addrlen);
489
490 set_nonblock(sockfd);
491 if (connect(sockfd, serv_addr, addrlen) == 0) {
492 /* Succeeded already? */
493 unset_nonblock(sockfd);
494 return 0;
495 } else if (errno != EINPROGRESS)
496 return -1;
497
498 if (waitrfd(sockfd, timeoutp) == -1)
499 return -1;
500
501 /* Completed or failed */
502 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) {
503 debug("getsockopt: %s", strerror(errno));
504 return -1;
505 }
506 if (optval != 0) {
507 errno = optval;
508 return -1;
509 }
510 unset_nonblock(sockfd);
511 return 0;
512}
513
514/*
515 * Opens a TCP/IP connection to the remote server on the given host. 447 * Opens a TCP/IP connection to the remote server on the given host.
516 * The address of the remote host will be returned in hostaddr. 448 * The address of the remote host will be returned in hostaddr.
517 * If port is 0, the default port will be used. 449 * If port is 0, the default port will be used.
@@ -629,110 +561,6 @@ ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs,
629 return ssh_proxy_connect(ssh, host, port, options.proxy_command); 561 return ssh_proxy_connect(ssh, host, port, options.proxy_command);
630} 562}
631 563
632static void
633send_client_banner(int connection_out, int minor1)
634{
635 /* Send our own protocol version identification. */
636 xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
637 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION);
638 if (atomicio(vwrite, connection_out, client_version_string,
639 strlen(client_version_string)) != strlen(client_version_string))
640 fatal("write: %.100s", strerror(errno));
641 chop(client_version_string);
642 debug("Local version string %.100s", client_version_string);
643}
644
645/*
646 * Waits for the server identification string, and sends our own
647 * identification string.
648 */
649void
650ssh_exchange_identification(int timeout_ms)
651{
652 char buf[256], remote_version[256]; /* must be same size! */
653 int remote_major, remote_minor, mismatch;
654 int connection_in = packet_get_connection_in();
655 int connection_out = packet_get_connection_out();
656 u_int i, n;
657 size_t len;
658 int rc;
659
660 send_client_banner(connection_out, 0);
661
662 /* Read other side's version identification. */
663 for (n = 0;;) {
664 for (i = 0; i < sizeof(buf) - 1; i++) {
665 if (timeout_ms > 0) {
666 rc = waitrfd(connection_in, &timeout_ms);
667 if (rc == -1 && errno == ETIMEDOUT) {
668 fatal("Connection timed out during "
669 "banner exchange");
670 } else if (rc == -1) {
671 fatal("%s: %s",
672 __func__, strerror(errno));
673 }
674 }
675
676 len = atomicio(read, connection_in, &buf[i], 1);
677 if (len != 1 && errno == EPIPE)
678 fatal("ssh_exchange_identification: "
679 "Connection closed by remote host");
680 else if (len != 1)
681 fatal("ssh_exchange_identification: "
682 "read: %.100s", strerror(errno));
683 if (buf[i] == '\r') {
684 buf[i] = '\n';
685 buf[i + 1] = 0;
686 continue; /**XXX wait for \n */
687 }
688 if (buf[i] == '\n') {
689 buf[i + 1] = 0;
690 break;
691 }
692 if (++n > 65536)
693 fatal("ssh_exchange_identification: "
694 "No banner received");
695 }
696 buf[sizeof(buf) - 1] = 0;
697 if (strncmp(buf, "SSH-", 4) == 0)
698 break;
699 debug("ssh_exchange_identification: %s", buf);
700 }
701 server_version_string = xstrdup(buf);
702
703 /*
704 * Check that the versions match. In future this might accept
705 * several versions and set appropriate flags to handle them.
706 */
707 if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
708 &remote_major, &remote_minor, remote_version) != 3)
709 fatal("Bad remote protocol version identification: '%.100s'", buf);
710 debug("Remote protocol version %d.%d, remote software version %.100s",
711 remote_major, remote_minor, remote_version);
712
713 active_state->compat = compat_datafellows(remote_version);
714 mismatch = 0;
715
716 switch (remote_major) {
717 case 2:
718 break;
719 case 1:
720 if (remote_minor != 99)
721 mismatch = 1;
722 break;
723 default:
724 mismatch = 1;
725 break;
726 }
727 if (mismatch)
728 fatal("Protocol major versions differ: %d vs. %d",
729 PROTOCOL_MAJOR_2, remote_major);
730 if ((datafellows & SSH_BUG_RSASIGMD5) != 0)
731 logit("Server version \"%.100s\" uses unsafe RSA signature "
732 "scheme; disabling use of RSA keys", remote_version);
733 chop(server_version_string);
734}
735
736/* defaults to 'no' */ 564/* defaults to 'no' */
737static int 565static int
738confirm(const char *prompt) 566confirm(const char *prompt)
@@ -1426,7 +1254,7 @@ out:
1426 * This function does not require super-user privileges. 1254 * This function does not require super-user privileges.
1427 */ 1255 */
1428void 1256void
1429ssh_login(Sensitive *sensitive, const char *orighost, 1257ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
1430 struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms) 1258 struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
1431{ 1259{
1432 char *host; 1260 char *host;
@@ -1440,16 +1268,17 @@ ssh_login(Sensitive *sensitive, const char *orighost,
1440 lowercase(host); 1268 lowercase(host);
1441 1269
1442 /* Exchange protocol version identification strings with the server. */ 1270 /* Exchange protocol version identification strings with the server. */
1443 ssh_exchange_identification(timeout_ms); 1271 if (kex_exchange_identification(ssh, timeout_ms, NULL) != 0)
1272 cleanup_exit(255); /* error already logged */
1444 1273
1445 /* Put the connection into non-blocking mode. */ 1274 /* Put the connection into non-blocking mode. */
1446 packet_set_nonblocking(); 1275 ssh_packet_set_nonblocking(ssh);
1447 1276
1448 /* key exchange */ 1277 /* key exchange */
1449 /* authenticate user */ 1278 /* authenticate user */
1450 debug("Authenticating to %s:%d as '%s'", host, port, server_user); 1279 debug("Authenticating to %s:%d as '%s'", host, port, server_user);
1451 ssh_kex2(host, hostaddr, port); 1280 ssh_kex2(ssh, host, hostaddr, port);
1452 ssh_userauth2(local_user, server_user, host, sensitive); 1281 ssh_userauth2(ssh, local_user, server_user, host, sensitive);
1453 free(local_user); 1282 free(local_user);
1454} 1283}
1455 1284
diff --git a/sshconnect.h b/sshconnect.h
index 890d85733..44a5071c7 100644
--- a/sshconnect.h
+++ b/sshconnect.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.h,v 1.35 2018/07/19 10:28:47 dtucker Exp $ */ 1/* $OpenBSD: sshconnect.h,v 1.36 2018/12/27 03:25:25 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -37,21 +37,18 @@ int ssh_connect(struct ssh *, const char *, struct addrinfo *,
37 struct sockaddr_storage *, u_short, int, int, int *, int); 37 struct sockaddr_storage *, u_short, int, int, int *, int);
38void ssh_kill_proxy_command(void); 38void ssh_kill_proxy_command(void);
39 39
40void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short, 40void ssh_login(struct ssh *, Sensitive *, const char *,
41 struct passwd *, int); 41 struct sockaddr *, u_short, struct passwd *, int);
42
43void ssh_exchange_identification(int);
44 42
45int verify_host_key(char *, struct sockaddr *, struct sshkey *); 43int verify_host_key(char *, struct sockaddr *, struct sshkey *);
46 44
47void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short, 45void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short,
48 char **, char **); 46 char **, char **);
49 47
50void ssh_kex(char *, struct sockaddr *); 48void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short);
51void ssh_kex2(char *, struct sockaddr *, u_short);
52 49
53void ssh_userauth1(const char *, const char *, char *, Sensitive *); 50void ssh_userauth2(struct ssh *ssh, const char *, const char *,
54void ssh_userauth2(const char *, const char *, char *, Sensitive *); 51 char *, Sensitive *);
55 52
56void ssh_put_password(char *); 53void ssh_put_password(char *);
57int ssh_local_cmd(const char *); 54int ssh_local_cmd(const char *);
diff --git a/sshconnect2.c b/sshconnect2.c
index adb4e4cbd..19caebabc 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.290 2018/11/28 06:00:38 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.291 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -155,11 +155,10 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
155} 155}
156 156
157void 157void
158ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 158ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
159{ 159{
160 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT }; 160 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
161 char *s, *all_key; 161 char *s, *all_key;
162 struct kex *kex;
163 int r; 162 int r;
164 163
165 xxx_host = host; 164 xxx_host = host;
@@ -199,36 +198,33 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
199 options.rekey_interval); 198 options.rekey_interval);
200 199
201 /* start key exchange */ 200 /* start key exchange */
202 if ((r = kex_setup(active_state, myproposal)) != 0) 201 if ((r = kex_setup(ssh, myproposal)) != 0)
203 fatal("kex_setup: %s", ssh_err(r)); 202 fatal("kex_setup: %s", ssh_err(r));
204 kex = active_state->kex;
205#ifdef WITH_OPENSSL 203#ifdef WITH_OPENSSL
206 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 204 ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
207 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 205 ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
208 kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client; 206 ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client;
209 kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client; 207 ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client;
210 kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client; 208 ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client;
211 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 209 ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
212 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 210 ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
213# ifdef OPENSSL_HAS_ECC 211# ifdef OPENSSL_HAS_ECC
214 kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 212 ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
215# endif 213# endif
216#endif 214#endif
217 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 215 ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client;
218 kex->client_version_string=client_version_string; 216 ssh->kex->verify_host_key=&verify_host_key_callback;
219 kex->server_version_string=server_version_string;
220 kex->verify_host_key=&verify_host_key_callback;
221 217
222 ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done); 218 ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done);
223 219
224 /* remove ext-info from the KEX proposals for rekeying */ 220 /* remove ext-info from the KEX proposals for rekeying */
225 myproposal[PROPOSAL_KEX_ALGS] = 221 myproposal[PROPOSAL_KEX_ALGS] =
226 compat_kex_proposal(options.kex_algorithms); 222 compat_kex_proposal(options.kex_algorithms);
227 if ((r = kex_prop2buf(kex->my, myproposal)) != 0) 223 if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0)
228 fatal("kex_prop2buf: %s", ssh_err(r)); 224 fatal("kex_prop2buf: %s", ssh_err(r));
229 225
230 session_id2 = kex->session_id; 226 session_id2 = ssh->kex->session_id;
231 session_id2_len = kex->session_id_len; 227 session_id2_len = ssh->kex->session_id_len;
232 228
233#ifdef DEBUG_KEXDH 229#ifdef DEBUG_KEXDH
234 /* send 1st encrypted/maced/compressed message */ 230 /* send 1st encrypted/maced/compressed message */
@@ -365,10 +361,9 @@ Authmethod authmethods[] = {
365}; 361};
366 362
367void 363void
368ssh_userauth2(const char *local_user, const char *server_user, char *host, 364ssh_userauth2(struct ssh *ssh, const char *local_user,
369 Sensitive *sensitive) 365 const char *server_user, char *host, Sensitive *sensitive)
370{ 366{
371 struct ssh *ssh = active_state;
372 Authctxt authctxt; 367 Authctxt authctxt;
373 int r; 368 int r;
374 369
@@ -392,8 +387,10 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
392 authctxt.info_req_seen = 0; 387 authctxt.info_req_seen = 0;
393 authctxt.agent_fd = -1; 388 authctxt.agent_fd = -1;
394 pubkey_prepare(&authctxt); 389 pubkey_prepare(&authctxt);
395 if (authctxt.method == NULL) 390 if (authctxt.method == NULL) {
396 fatal("ssh_userauth2: internal error: cannot send userauth none request"); 391 fatal("%s: internal error: cannot send userauth none request",
392 __func__);
393 }
397 394
398 if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 || 395 if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 ||
399 (r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 || 396 (r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 ||
diff --git a/sshd.c b/sshd.c
index fb9d9b60f..3461383a0 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.519 2018/11/19 04:12:32 djm Exp $ */ 1/* $OpenBSD: sshd.c,v 1.520 2018/12/27 03:25:25 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -180,13 +180,6 @@ char **rexec_argv;
180int listen_socks[MAX_LISTEN_SOCKS]; 180int listen_socks[MAX_LISTEN_SOCKS];
181int num_listen_socks = 0; 181int num_listen_socks = 0;
182 182
183/*
184 * the client's version string, passed by sshd2 in compat mode. if != NULL,
185 * sshd will skip the version-number exchange
186 */
187char *client_version_string = NULL;
188char *server_version_string = NULL;
189
190/* Daemon's agent connection */ 183/* Daemon's agent connection */
191int auth_sock = -1; 184int auth_sock = -1;
192int have_agent = 0; 185int have_agent = 0;
@@ -363,108 +356,6 @@ grace_alarm_handler(int sig)
363 ssh_remote_ipaddr(active_state), ssh_remote_port(active_state)); 356 ssh_remote_ipaddr(active_state), ssh_remote_port(active_state));
364} 357}
365 358
366static void
367sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out)
368{
369 u_int i;
370 int remote_major, remote_minor;
371 char *s;
372 char buf[256]; /* Must not be larger than remote_version. */
373 char remote_version[256]; /* Must be at least as big as buf. */
374
375 xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n",
376 PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
377 *options.version_addendum == '\0' ? "" : " ",
378 options.version_addendum);
379
380 /* Send our protocol version identification. */
381 if (atomicio(vwrite, sock_out, server_version_string,
382 strlen(server_version_string))
383 != strlen(server_version_string)) {
384 logit("Could not write ident string to %s port %d",
385 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
386 cleanup_exit(255);
387 }
388
389 /* Read other sides version identification. */
390 memset(buf, 0, sizeof(buf));
391 for (i = 0; i < sizeof(buf) - 1; i++) {
392 if (atomicio(read, sock_in, &buf[i], 1) != 1) {
393 logit("Did not receive identification string "
394 "from %s port %d",
395 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
396 cleanup_exit(255);
397 }
398 if (buf[i] == '\r') {
399 buf[i] = 0;
400 /* Kludge for F-Secure Macintosh < 1.0.2 */
401 if (i == 12 &&
402 strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
403 break;
404 continue;
405 }
406 if (buf[i] == '\n') {
407 buf[i] = 0;
408 break;
409 }
410 }
411 buf[sizeof(buf) - 1] = 0;
412 client_version_string = xstrdup(buf);
413
414 /*
415 * Check that the versions match. In future this might accept
416 * several versions and set appropriate flags to handle them.
417 */
418 if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
419 &remote_major, &remote_minor, remote_version) != 3) {
420 s = "Protocol mismatch.\n";
421 (void) atomicio(vwrite, sock_out, s, strlen(s));
422 logit("Bad protocol version identification '%.100s' "
423 "from %s port %d", client_version_string,
424 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
425 close(sock_in);
426 close(sock_out);
427 cleanup_exit(255);
428 }
429 debug("Client protocol version %d.%d; client software version %.100s",
430 remote_major, remote_minor, remote_version);
431
432 ssh->compat = compat_datafellows(remote_version);
433
434 if ((ssh->compat & SSH_BUG_PROBE) != 0) {
435 logit("probed from %s port %d with %s. Don't panic.",
436 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
437 client_version_string);
438 cleanup_exit(255);
439 }
440 if ((ssh->compat & SSH_BUG_SCANNER) != 0) {
441 logit("scanned from %s port %d with %s. Don't panic.",
442 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
443 client_version_string);
444 cleanup_exit(255);
445 }
446 if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
447 logit("Client version \"%.100s\" uses unsafe RSA signature "
448 "scheme; disabling use of RSA keys", remote_version);
449 }
450
451 chop(server_version_string);
452 debug("Local version string %.200s", server_version_string);
453
454 if (remote_major != 2 &&
455 !(remote_major == 1 && remote_minor == 99)) {
456 s = "Protocol major versions differ.\n";
457 (void) atomicio(vwrite, sock_out, s, strlen(s));
458 close(sock_in);
459 close(sock_out);
460 logit("Protocol major versions differ for %s port %d: "
461 "%.200s vs. %.200s",
462 ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
463 server_version_string, client_version_string);
464 cleanup_exit(255);
465 }
466}
467
468/* Destroy the host and server keys. They will no longer be needed. */ 359/* Destroy the host and server keys. They will no longer be needed. */
469void 360void
470destroy_sensitive_data(void) 361destroy_sensitive_data(void)
@@ -2115,7 +2006,9 @@ main(int ac, char **av)
2115 if (!debug_flag) 2006 if (!debug_flag)
2116 alarm(options.login_grace_time); 2007 alarm(options.login_grace_time);
2117 2008
2118 sshd_exchange_identification(ssh, sock_in, sock_out); 2009 if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0)
2010 cleanup_exit(255); /* error already logged */
2011
2119 packet_set_nonblocking(); 2012 packet_set_nonblocking();
2120 2013
2121 /* allocate authentication context */ 2014 /* allocate authentication context */
@@ -2303,9 +2196,6 @@ do_ssh2_kex(void)
2303# endif 2196# endif
2304#endif 2197#endif
2305 kex->kex[KEX_C25519_SHA256] = kexc25519_server; 2198 kex->kex[KEX_C25519_SHA256] = kexc25519_server;
2306 kex->server = 1;
2307 kex->client_version_string=client_version_string;
2308 kex->server_version_string=server_version_string;
2309 kex->load_host_public_key=&get_hostkey_public_by_type; 2199 kex->load_host_public_key=&get_hostkey_public_by_type;
2310 kex->load_host_private_key=&get_hostkey_private_by_type; 2200 kex->load_host_private_key=&get_hostkey_private_by_type;
2311 kex->host_key_index=&get_hostkey_index; 2201 kex->host_key_index=&get_hostkey_index;