upstream: move client/server SSH-* banners to buffers under
ssh->kex and factor out the banner exchange. This eliminates some common code from the client and server. Also be more strict about handling \r characters - these should only be accepted immediately before \n (pointed out by Jann Horn). Inspired by a patch from Markus Schmidt. (lots of) feedback and ok markus@ OpenBSD-Commit-ID: 1cc7885487a6754f63641d7d3279b0941890275b
This commit is contained in:
parent
434b587afe
commit
0a843d9a0e
6
.depend
6
.depend
|
@ -60,8 +60,8 @@ gss-serv.o: includes.h config.h defines.h platform.h openbsd-compat/openbsd-comp
|
||||||
hash.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
|
hash.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
|
||||||
hmac.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
|
hmac.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
|
||||||
hostfile.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
|
hostfile.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
|
||||||
kex.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
|
kex.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
|
||||||
kex.o: digest.h
|
kex.o: monitor.h ssherr.h sshbuf.h digest.h
|
||||||
kexc25519.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
|
kexc25519.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
|
||||||
kexc25519c.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
|
kexc25519c.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
|
||||||
kexc25519s.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
|
kexc25519s.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/
|
||||||
sshbuf-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
|
sshbuf-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
|
||||||
sshbuf.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
|
sshbuf.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
|
||||||
sshconnect.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
|
sshconnect.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
|
||||||
sshconnect.o: ssherr.h authfd.h
|
sshconnect.o: ssherr.h authfd.h kex.h mac.h
|
||||||
sshconnect2.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
|
sshconnect2.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
|
||||||
sshconnect2.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
|
sshconnect2.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
|
||||||
sshd.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
|
sshd.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
|
||||||
|
|
|
@ -186,7 +186,7 @@ ssh-agent$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-agent.o ssh-pkcs11-client.o
|
||||||
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
|
ssh-keygen$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keygen.o
|
||||||
$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
$(LD) -o $@ ssh-keygen.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
|
||||||
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o
|
ssh-keysign$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-keysign.o readconf.o uidswap.o compat.o
|
||||||
$(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
$(LD) -o $@ ssh-keysign.o readconf.o uidswap.o $(LDFLAGS) -lssh -lopenbsd-compat $(LIBS)
|
||||||
|
|
||||||
ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
|
ssh-pkcs11-helper$(EXEEXT): $(LIBCOMPAT) libssh.a ssh-pkcs11-helper.o ssh-pkcs11.o
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: atomicio.h,v 1.11 2010/09/22 22:58:51 djm Exp $ */
|
/* $OpenBSD: atomicio.h,v 1.12 2018/12/27 03:25:25 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2006 Damien Miller. All rights reserved.
|
* Copyright (c) 2006 Damien Miller. All rights reserved.
|
||||||
|
@ -29,6 +29,8 @@
|
||||||
#ifndef _ATOMICIO_H
|
#ifndef _ATOMICIO_H
|
||||||
#define _ATOMICIO_H
|
#define _ATOMICIO_H
|
||||||
|
|
||||||
|
struct iovec;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ensure all of data on socket comes through. f==read || f==vwrite
|
* Ensure all of data on socket comes through. f==read || f==vwrite
|
||||||
*/
|
*/
|
||||||
|
|
294
kex.c
294
kex.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kex.c,v 1.142 2018/12/07 03:39:40 djm Exp $ */
|
/* $OpenBSD: kex.c,v 1.143 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -25,19 +25,25 @@
|
||||||
|
|
||||||
#include "includes.h"
|
#include "includes.h"
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#ifdef WITH_OPENSSL
|
#ifdef WITH_OPENSSL
|
||||||
#include <openssl/crypto.h>
|
#include <openssl/crypto.h>
|
||||||
#include <openssl/dh.h>
|
#include <openssl/dh.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "ssh.h"
|
||||||
#include "ssh2.h"
|
#include "ssh2.h"
|
||||||
|
#include "atomicio.h"
|
||||||
|
#include "version.h"
|
||||||
#include "packet.h"
|
#include "packet.h"
|
||||||
#include "compat.h"
|
#include "compat.h"
|
||||||
#include "cipher.h"
|
#include "cipher.h"
|
||||||
|
@ -578,32 +584,20 @@ kex_input_kexinit(int type, u_int32_t seq, struct ssh *ssh)
|
||||||
return SSH_ERR_INTERNAL_ERROR;
|
return SSH_ERR_INTERNAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
struct kex *
|
||||||
kex_new(struct ssh *ssh, char *proposal[PROPOSAL_MAX], struct kex **kexp)
|
kex_new(void)
|
||||||
{
|
{
|
||||||
struct kex *kex;
|
struct kex *kex;
|
||||||
int r;
|
|
||||||
|
|
||||||
*kexp = NULL;
|
if ((kex = calloc(1, sizeof(*kex))) == NULL ||
|
||||||
if ((kex = calloc(1, sizeof(*kex))) == NULL)
|
(kex->peer = sshbuf_new()) == NULL ||
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
(kex->my = sshbuf_new()) == NULL ||
|
||||||
if ((kex->peer = sshbuf_new()) == NULL ||
|
(kex->client_version = sshbuf_new()) == NULL ||
|
||||||
(kex->my = sshbuf_new()) == NULL) {
|
(kex->server_version = sshbuf_new()) == NULL) {
|
||||||
r = SSH_ERR_ALLOC_FAIL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if ((r = kex_prop2buf(kex->my, proposal)) != 0)
|
|
||||||
goto out;
|
|
||||||
kex->done = 0;
|
|
||||||
kex->flags = KEX_INITIAL;
|
|
||||||
kex_reset_dispatch(ssh);
|
|
||||||
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
|
|
||||||
r = 0;
|
|
||||||
*kexp = kex;
|
|
||||||
out:
|
|
||||||
if (r != 0)
|
|
||||||
kex_free(kex);
|
kex_free(kex);
|
||||||
return r;
|
return NULL;
|
||||||
|
}
|
||||||
|
return kex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -642,6 +636,9 @@ kex_free(struct kex *kex)
|
||||||
{
|
{
|
||||||
u_int mode;
|
u_int mode;
|
||||||
|
|
||||||
|
if (kex == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
#ifdef WITH_OPENSSL
|
#ifdef WITH_OPENSSL
|
||||||
DH_free(kex->dh);
|
DH_free(kex->dh);
|
||||||
#ifdef OPENSSL_HAS_ECC
|
#ifdef OPENSSL_HAS_ECC
|
||||||
|
@ -654,21 +651,34 @@ kex_free(struct kex *kex)
|
||||||
}
|
}
|
||||||
sshbuf_free(kex->peer);
|
sshbuf_free(kex->peer);
|
||||||
sshbuf_free(kex->my);
|
sshbuf_free(kex->my);
|
||||||
|
sshbuf_free(kex->client_version);
|
||||||
|
sshbuf_free(kex->server_version);
|
||||||
free(kex->session_id);
|
free(kex->session_id);
|
||||||
free(kex->client_version_string);
|
|
||||||
free(kex->server_version_string);
|
|
||||||
free(kex->failed_choice);
|
free(kex->failed_choice);
|
||||||
free(kex->hostkey_alg);
|
free(kex->hostkey_alg);
|
||||||
free(kex->name);
|
free(kex->name);
|
||||||
free(kex);
|
free(kex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
kex_ready(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
|
||||||
|
if ((r = kex_prop2buf(ssh->kex->my, proposal)) != 0)
|
||||||
|
return r;
|
||||||
|
ssh->kex->flags = KEX_INITIAL;
|
||||||
|
kex_reset_dispatch(ssh);
|
||||||
|
ssh_dispatch_set(ssh, SSH2_MSG_KEXINIT, &kex_input_kexinit);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
|
kex_setup(struct ssh *ssh, char *proposal[PROPOSAL_MAX])
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0)
|
if ((r = kex_ready(ssh, proposal)) != 0)
|
||||||
return r;
|
return r;
|
||||||
if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
|
if ((r = kex_send_kexinit(ssh)) != 0) { /* we start */
|
||||||
kex_free(ssh->kex);
|
kex_free(ssh->kex);
|
||||||
|
@ -1043,3 +1053,233 @@ dump_digest(char *msg, u_char *digest, int len)
|
||||||
sshbuf_dump_data(digest, len, stderr);
|
sshbuf_dump_data(digest, len, stderr);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Send a plaintext error message to the peer, suffixed by \r\n.
|
||||||
|
* Only used during banner exchange, and there only for the server.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
send_error(struct ssh *ssh, char *msg)
|
||||||
|
{
|
||||||
|
char *crnl = "\r\n";
|
||||||
|
|
||||||
|
if (!ssh->kex->server)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
|
||||||
|
msg, strlen(msg)) != strlen(msg) ||
|
||||||
|
atomicio(vwrite, ssh_packet_get_connection_out(ssh),
|
||||||
|
crnl, strlen(crnl)) != strlen(crnl))
|
||||||
|
error("%s: write: %.100s", __func__, strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sends our identification string and waits for the peer's. Will block for
|
||||||
|
* up to timeout_ms (or indefinitely if timeout_ms <= 0).
|
||||||
|
* Returns on 0 success or a ssherr.h code on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
kex_exchange_identification(struct ssh *ssh, int timeout_ms,
|
||||||
|
const char *version_addendum)
|
||||||
|
{
|
||||||
|
int remote_major, remote_minor, mismatch;
|
||||||
|
size_t len, i, n;
|
||||||
|
int r, expect_nl;
|
||||||
|
u_char c;
|
||||||
|
struct sshbuf *our_version = ssh->kex->server ?
|
||||||
|
ssh->kex->server_version : ssh->kex->client_version;
|
||||||
|
struct sshbuf *peer_version = ssh->kex->server ?
|
||||||
|
ssh->kex->client_version : ssh->kex->server_version;
|
||||||
|
char *our_version_string = NULL, *peer_version_string = NULL;
|
||||||
|
char *cp, *remote_version = NULL;
|
||||||
|
|
||||||
|
/* Prepare and send our banner */
|
||||||
|
sshbuf_reset(our_version);
|
||||||
|
if (version_addendum != NULL && *version_addendum == '\0')
|
||||||
|
version_addendum = NULL;
|
||||||
|
if ((r = sshbuf_putf(our_version, "SSH-%d.%d-%.100s%s%s\r\n",
|
||||||
|
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
|
||||||
|
version_addendum == NULL ? "" : " ",
|
||||||
|
version_addendum == NULL ? "" : version_addendum)) != 0) {
|
||||||
|
error("%s: sshbuf_putf: %s", __func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atomicio(vwrite, ssh_packet_get_connection_out(ssh),
|
||||||
|
sshbuf_mutable_ptr(our_version),
|
||||||
|
sshbuf_len(our_version)) != sshbuf_len(our_version)) {
|
||||||
|
error("%s: write: %.100s", __func__, strerror(errno));
|
||||||
|
r = SSH_ERR_SYSTEM_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_consume_end(our_version, 2)) != 0) { /* trim \r\n */
|
||||||
|
error("%s: sshbuf_consume_end: %s", __func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
our_version_string = sshbuf_dup_string(our_version);
|
||||||
|
if (our_version_string == NULL) {
|
||||||
|
error("%s: sshbuf_dup_string failed", __func__);
|
||||||
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
debug("Local version string %.100s", our_version_string);
|
||||||
|
|
||||||
|
/* Read other side's version identification. */
|
||||||
|
for (n = 0; ; n++) {
|
||||||
|
if (n >= SSH_MAX_PRE_BANNER_LINES) {
|
||||||
|
send_error(ssh, "No SSH identification string "
|
||||||
|
"received.");
|
||||||
|
error("%s: No SSH version received in first %u lines "
|
||||||
|
"from server", __func__, SSH_MAX_PRE_BANNER_LINES);
|
||||||
|
r = SSH_ERR_INVALID_FORMAT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
sshbuf_reset(peer_version);
|
||||||
|
expect_nl = 0;
|
||||||
|
for (i = 0; ; i++) {
|
||||||
|
if (timeout_ms > 0) {
|
||||||
|
r = waitrfd(ssh_packet_get_connection_in(ssh),
|
||||||
|
&timeout_ms);
|
||||||
|
if (r == -1 && errno == ETIMEDOUT) {
|
||||||
|
send_error(ssh, "Timed out waiting "
|
||||||
|
"for SSH identification string.");
|
||||||
|
error("Connection timed out during "
|
||||||
|
"banner exchange");
|
||||||
|
r = SSH_ERR_CONN_TIMEOUT;
|
||||||
|
goto out;
|
||||||
|
} else if (r == -1) {
|
||||||
|
error("%s: %s",
|
||||||
|
__func__, strerror(errno));
|
||||||
|
r = SSH_ERR_SYSTEM_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
len = atomicio(read, ssh_packet_get_connection_in(ssh),
|
||||||
|
&c, 1);
|
||||||
|
if (len != 1 && errno == EPIPE) {
|
||||||
|
error("%s: Connection closed by remote host",
|
||||||
|
__func__);
|
||||||
|
r = SSH_ERR_CONN_CLOSED;
|
||||||
|
goto out;
|
||||||
|
} else if (len != 1) {
|
||||||
|
error("%s: read: %.100s",
|
||||||
|
__func__, strerror(errno));
|
||||||
|
r = SSH_ERR_SYSTEM_ERROR;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (c == '\r') {
|
||||||
|
expect_nl = 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (c == '\n')
|
||||||
|
break;
|
||||||
|
if (c == '\0' || expect_nl) {
|
||||||
|
error("%s: banner line contains invalid "
|
||||||
|
"characters", __func__);
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
if ((r = sshbuf_put_u8(peer_version, c)) != 0) {
|
||||||
|
error("%s: sshbuf_put: %s",
|
||||||
|
__func__, ssh_err(r));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (sshbuf_len(peer_version) > SSH_MAX_BANNER_LEN) {
|
||||||
|
error("%s: banner line too long", __func__);
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Is this an actual protocol banner? */
|
||||||
|
if (sshbuf_len(peer_version) > 4 &&
|
||||||
|
memcmp(sshbuf_ptr(peer_version), "SSH-", 4) == 0)
|
||||||
|
break;
|
||||||
|
/* If not, then just log the line and continue */
|
||||||
|
if ((cp = sshbuf_dup_string(peer_version)) == NULL) {
|
||||||
|
error("%s: sshbuf_dup_string failed", __func__);
|
||||||
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
/* Do not accept lines before the SSH ident from a client */
|
||||||
|
if (ssh->kex->server) {
|
||||||
|
error("%s: client sent invalid protocol identifier "
|
||||||
|
"\"%.256s\"", __func__, cp);
|
||||||
|
free(cp);
|
||||||
|
goto invalid;
|
||||||
|
}
|
||||||
|
debug("%s: banner line %zu: %s", __func__, n, cp);
|
||||||
|
free(cp);
|
||||||
|
}
|
||||||
|
peer_version_string = sshbuf_dup_string(peer_version);
|
||||||
|
if (peer_version_string == NULL)
|
||||||
|
error("%s: sshbuf_dup_string failed", __func__);
|
||||||
|
/* XXX must be same size for sscanf */
|
||||||
|
if ((remote_version = calloc(1, sshbuf_len(peer_version))) == NULL) {
|
||||||
|
error("%s: calloc failed", __func__);
|
||||||
|
r = SSH_ERR_ALLOC_FAIL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check that the versions match. In future this might accept
|
||||||
|
* several versions and set appropriate flags to handle them.
|
||||||
|
*/
|
||||||
|
if (sscanf(peer_version_string, "SSH-%d.%d-%[^\n]\n",
|
||||||
|
&remote_major, &remote_minor, remote_version) != 3) {
|
||||||
|
error("Bad remote protocol version identification: '%.100s'",
|
||||||
|
peer_version_string);
|
||||||
|
invalid:
|
||||||
|
send_error(ssh, "Invalid SSH identification string.");
|
||||||
|
r = SSH_ERR_INVALID_FORMAT;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
debug("Remote protocol version %d.%d, remote software version %.100s",
|
||||||
|
remote_major, remote_minor, remote_version);
|
||||||
|
ssh->compat = compat_datafellows(remote_version);
|
||||||
|
|
||||||
|
mismatch = 0;
|
||||||
|
switch (remote_major) {
|
||||||
|
case 2:
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
if (remote_minor != 99)
|
||||||
|
mismatch = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mismatch = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (mismatch) {
|
||||||
|
error("Protocol major versions differ: %d vs. %d",
|
||||||
|
PROTOCOL_MAJOR_2, remote_major);
|
||||||
|
send_error(ssh, "Protocol major versions differ.");
|
||||||
|
r = SSH_ERR_NO_PROTOCOL_VERSION;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ssh->kex->server && (ssh->compat & SSH_BUG_PROBE) != 0) {
|
||||||
|
logit("probed from %s port %d with %s. Don't panic.",
|
||||||
|
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
|
||||||
|
peer_version_string);
|
||||||
|
r = SSH_ERR_CONN_CLOSED; /* XXX */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if (ssh->kex->server && (ssh->compat & SSH_BUG_SCANNER) != 0) {
|
||||||
|
logit("scanned from %s port %d with %s. Don't panic.",
|
||||||
|
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
|
||||||
|
peer_version_string);
|
||||||
|
r = SSH_ERR_CONN_CLOSED; /* XXX */
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
|
||||||
|
logit("Remote version \"%.100s\" uses unsafe RSA signature "
|
||||||
|
"scheme; disabling use of RSA keys", remote_version);
|
||||||
|
}
|
||||||
|
/* success */
|
||||||
|
r = 0;
|
||||||
|
out:
|
||||||
|
free(our_version_string);
|
||||||
|
free(peer_version_string);
|
||||||
|
free(remote_version);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
kex.h
20
kex.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kex.h,v 1.92 2018/12/07 03:39:40 djm Exp $ */
|
/* $OpenBSD: kex.h,v 1.93 2018/12/27 03:25:25 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
|
||||||
|
@ -145,12 +145,12 @@ struct kex {
|
||||||
int ext_info_c;
|
int ext_info_c;
|
||||||
struct sshbuf *my;
|
struct sshbuf *my;
|
||||||
struct sshbuf *peer;
|
struct sshbuf *peer;
|
||||||
|
struct sshbuf *client_version;
|
||||||
|
struct sshbuf *server_version;
|
||||||
sig_atomic_t done;
|
sig_atomic_t done;
|
||||||
u_int flags;
|
u_int flags;
|
||||||
int hash_alg;
|
int hash_alg;
|
||||||
int ec_nid;
|
int ec_nid;
|
||||||
char *client_version_string;
|
|
||||||
char *server_version_string;
|
|
||||||
char *failed_choice;
|
char *failed_choice;
|
||||||
int (*verify_host_key)(struct sshkey *, struct ssh *);
|
int (*verify_host_key)(struct sshkey *, struct ssh *);
|
||||||
struct sshkey *(*load_host_public_key)(int, int, struct ssh *);
|
struct sshkey *(*load_host_public_key)(int, int, struct ssh *);
|
||||||
|
@ -173,7 +173,10 @@ char *kex_alg_list(char);
|
||||||
char *kex_names_cat(const char *, const char *);
|
char *kex_names_cat(const char *, const char *);
|
||||||
int kex_assemble_names(char **, const char *, const char *);
|
int kex_assemble_names(char **, const char *, const char *);
|
||||||
|
|
||||||
int kex_new(struct ssh *, char *[PROPOSAL_MAX], struct kex **);
|
int kex_exchange_identification(struct ssh *, int, const char *);
|
||||||
|
|
||||||
|
struct kex *kex_new(void);
|
||||||
|
int kex_ready(struct ssh *, char *[PROPOSAL_MAX]);
|
||||||
int kex_setup(struct ssh *, char *[PROPOSAL_MAX]);
|
int kex_setup(struct ssh *, char *[PROPOSAL_MAX]);
|
||||||
void kex_free_newkeys(struct newkeys *);
|
void kex_free_newkeys(struct newkeys *);
|
||||||
void kex_free(struct kex *);
|
void kex_free(struct kex *);
|
||||||
|
@ -199,22 +202,23 @@ int kexecdh_server(struct ssh *);
|
||||||
int kexc25519_client(struct ssh *);
|
int kexc25519_client(struct ssh *);
|
||||||
int kexc25519_server(struct ssh *);
|
int kexc25519_server(struct ssh *);
|
||||||
|
|
||||||
int kex_dh_hash(int, const char *, const char *,
|
int kex_dh_hash(int, const struct sshbuf *, const struct sshbuf *,
|
||||||
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
|
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
|
||||||
const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
|
const BIGNUM *, const BIGNUM *, const BIGNUM *, u_char *, size_t *);
|
||||||
|
|
||||||
int kexgex_hash(int, const char *, const char *,
|
int kexgex_hash(int, const struct sshbuf *, const struct sshbuf *,
|
||||||
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
|
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
|
||||||
int, int, int,
|
int, int, int,
|
||||||
const BIGNUM *, const BIGNUM *, const BIGNUM *,
|
const BIGNUM *, const BIGNUM *, const BIGNUM *,
|
||||||
const BIGNUM *, const BIGNUM *,
|
const BIGNUM *, const BIGNUM *,
|
||||||
u_char *, size_t *);
|
u_char *, size_t *);
|
||||||
|
|
||||||
int kex_ecdh_hash(int, const EC_GROUP *, const char *, const char *,
|
int kex_ecdh_hash(int, const EC_GROUP *,
|
||||||
|
const struct sshbuf *, const struct sshbuf *,
|
||||||
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
|
const u_char *, size_t, const u_char *, size_t, const u_char *, size_t,
|
||||||
const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *);
|
const EC_POINT *, const EC_POINT *, const BIGNUM *, u_char *, size_t *);
|
||||||
|
|
||||||
int kex_c25519_hash(int, const char *, const char *,
|
int kex_c25519_hash(int, const struct sshbuf *, const struct sshbuf *,
|
||||||
const u_char *, size_t, const u_char *, size_t,
|
const u_char *, size_t, const u_char *, size_t,
|
||||||
const u_char *, size_t, const u_char *, const u_char *,
|
const u_char *, size_t, const u_char *, const u_char *,
|
||||||
const u_char *, size_t, u_char *, size_t *);
|
const u_char *, size_t, u_char *, size_t *);
|
||||||
|
|
10
kexc25519.c
10
kexc25519.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexc25519.c,v 1.10 2016/05/02 08:49:03 djm Exp $ */
|
/* $OpenBSD: kexc25519.c,v 1.11 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||||
|
@ -84,8 +84,8 @@ kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
|
||||||
int
|
int
|
||||||
kex_c25519_hash(
|
kex_c25519_hash(
|
||||||
int hash_alg,
|
int hash_alg,
|
||||||
const char *client_version_string,
|
const struct sshbuf *client_version,
|
||||||
const char *server_version_string,
|
const struct sshbuf *server_version,
|
||||||
const u_char *ckexinit, size_t ckexinitlen,
|
const u_char *ckexinit, size_t ckexinitlen,
|
||||||
const u_char *skexinit, size_t skexinitlen,
|
const u_char *skexinit, size_t skexinitlen,
|
||||||
const u_char *serverhostkeyblob, size_t sbloblen,
|
const u_char *serverhostkeyblob, size_t sbloblen,
|
||||||
|
@ -101,8 +101,8 @@ kex_c25519_hash(
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
return SSH_ERR_INVALID_ARGUMENT;
|
||||||
if ((b = sshbuf_new()) == NULL)
|
if ((b = sshbuf_new()) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 ||
|
if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
|
||||||
(r = sshbuf_put_cstring(b, server_version_string)) < 0 ||
|
(r = sshbuf_put_stringb(b, server_version)) < 0 ||
|
||||||
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
||||||
(r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 ||
|
(r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 ||
|
||||||
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
|
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 ||
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexc25519c.c,v 1.9 2017/12/18 02:25:15 djm Exp $ */
|
/* $OpenBSD: kexc25519c.c,v 1.10 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* 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)
|
||||||
hashlen = sizeof(hash);
|
hashlen = sizeof(hash);
|
||||||
if ((r = kex_c25519_hash(
|
if ((r = kex_c25519_hash(
|
||||||
kex->hash_alg,
|
kex->hash_alg,
|
||||||
kex->client_version_string,
|
kex->client_version,
|
||||||
kex->server_version_string,
|
kex->server_version,
|
||||||
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
||||||
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
||||||
server_host_key_blob, sbloblen,
|
server_host_key_blob, sbloblen,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexc25519s.c,v 1.11 2017/05/31 04:19:28 djm Exp $ */
|
/* $OpenBSD: kexc25519s.c,v 1.12 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* 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)
|
||||||
hashlen = sizeof(hash);
|
hashlen = sizeof(hash);
|
||||||
if ((r = kex_c25519_hash(
|
if ((r = kex_c25519_hash(
|
||||||
kex->hash_alg,
|
kex->hash_alg,
|
||||||
kex->client_version_string,
|
kex->client_version,
|
||||||
kex->server_version_string,
|
kex->server_version,
|
||||||
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
||||||
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
||||||
server_host_key_blob, sbloblen,
|
server_host_key_blob, sbloblen,
|
||||||
|
|
10
kexdh.c
10
kexdh.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexdh.c,v 1.26 2016/05/02 10:26:04 djm Exp $ */
|
/* $OpenBSD: kexdh.c,v 1.27 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -46,8 +46,8 @@
|
||||||
int
|
int
|
||||||
kex_dh_hash(
|
kex_dh_hash(
|
||||||
int hash_alg,
|
int hash_alg,
|
||||||
const char *client_version_string,
|
const struct sshbuf *client_version,
|
||||||
const char *server_version_string,
|
const struct sshbuf *server_version,
|
||||||
const u_char *ckexinit, size_t ckexinitlen,
|
const u_char *ckexinit, size_t ckexinitlen,
|
||||||
const u_char *skexinit, size_t skexinitlen,
|
const u_char *skexinit, size_t skexinitlen,
|
||||||
const u_char *serverhostkeyblob, size_t sbloblen,
|
const u_char *serverhostkeyblob, size_t sbloblen,
|
||||||
|
@ -63,8 +63,8 @@ kex_dh_hash(
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
return SSH_ERR_INVALID_ARGUMENT;
|
||||||
if ((b = sshbuf_new()) == NULL)
|
if ((b = sshbuf_new()) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
|
if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
|
||||||
(r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
|
(r = sshbuf_put_stringb(b, server_version)) < 0 ||
|
||||||
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
||||||
(r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
|
(r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
|
||||||
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
|
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
|
||||||
|
|
6
kexdhc.c
6
kexdhc.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexdhc.c,v 1.22 2018/02/07 02:06:51 jsing Exp $ */
|
/* $OpenBSD: kexdhc.c,v 1.24 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -178,8 +178,8 @@ input_kex_dh(int type, u_int32_t seq, struct ssh *ssh)
|
||||||
hashlen = sizeof(hash);
|
hashlen = sizeof(hash);
|
||||||
if ((r = kex_dh_hash(
|
if ((r = kex_dh_hash(
|
||||||
kex->hash_alg,
|
kex->hash_alg,
|
||||||
kex->client_version_string,
|
kex->client_version,
|
||||||
kex->server_version_string,
|
kex->server_version,
|
||||||
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
||||||
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
||||||
server_host_key_blob, sbloblen,
|
server_host_key_blob, sbloblen,
|
||||||
|
|
6
kexdhs.c
6
kexdhs.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexdhs.c,v 1.27 2018/04/10 00:10:49 djm Exp $ */
|
/* $OpenBSD: kexdhs.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -166,8 +166,8 @@ input_kex_dh_init(int type, u_int32_t seq, struct ssh *ssh)
|
||||||
hashlen = sizeof(hash);
|
hashlen = sizeof(hash);
|
||||||
if ((r = kex_dh_hash(
|
if ((r = kex_dh_hash(
|
||||||
kex->hash_alg,
|
kex->hash_alg,
|
||||||
kex->client_version_string,
|
kex->client_version,
|
||||||
kex->server_version_string,
|
kex->server_version,
|
||||||
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
||||||
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
||||||
server_host_key_blob, sbloblen,
|
server_host_key_blob, sbloblen,
|
||||||
|
|
10
kexecdh.c
10
kexecdh.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexecdh.c,v 1.6 2015/01/19 20:16:15 markus Exp $ */
|
/* $OpenBSD: kexecdh.c,v 1.7 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
||||||
|
@ -50,8 +50,8 @@ int
|
||||||
kex_ecdh_hash(
|
kex_ecdh_hash(
|
||||||
int hash_alg,
|
int hash_alg,
|
||||||
const EC_GROUP *ec_group,
|
const EC_GROUP *ec_group,
|
||||||
const char *client_version_string,
|
const struct sshbuf *client_version,
|
||||||
const char *server_version_string,
|
const struct sshbuf *server_version,
|
||||||
const u_char *ckexinit, size_t ckexinitlen,
|
const u_char *ckexinit, size_t ckexinitlen,
|
||||||
const u_char *skexinit, size_t skexinitlen,
|
const u_char *skexinit, size_t skexinitlen,
|
||||||
const u_char *serverhostkeyblob, size_t sbloblen,
|
const u_char *serverhostkeyblob, size_t sbloblen,
|
||||||
|
@ -67,8 +67,8 @@ kex_ecdh_hash(
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
return SSH_ERR_INVALID_ARGUMENT;
|
||||||
if ((b = sshbuf_new()) == NULL)
|
if ((b = sshbuf_new()) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
|
if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
|
||||||
(r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
|
(r = sshbuf_put_stringb(b, server_version)) < 0 ||
|
||||||
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
||||||
(r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
|
(r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
|
||||||
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
|
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexecdhc.c,v 1.13 2018/02/07 02:06:51 jsing Exp $ */
|
/* $OpenBSD: kexecdhc.c,v 1.14 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* 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)
|
||||||
if ((r = kex_ecdh_hash(
|
if ((r = kex_ecdh_hash(
|
||||||
kex->hash_alg,
|
kex->hash_alg,
|
||||||
group,
|
group,
|
||||||
kex->client_version_string,
|
kex->client_version,
|
||||||
kex->server_version_string,
|
kex->server_version,
|
||||||
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
||||||
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
||||||
server_host_key_blob, sbloblen,
|
server_host_key_blob, sbloblen,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexecdhs.c,v 1.17 2018/02/07 02:06:51 jsing Exp $ */
|
/* $OpenBSD: kexecdhs.c,v 1.18 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2010 Damien Miller. All rights reserved.
|
* 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)
|
||||||
if ((r = kex_ecdh_hash(
|
if ((r = kex_ecdh_hash(
|
||||||
kex->hash_alg,
|
kex->hash_alg,
|
||||||
group,
|
group,
|
||||||
kex->client_version_string,
|
kex->client_version,
|
||||||
kex->server_version_string,
|
kex->server_version,
|
||||||
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
||||||
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
||||||
server_host_key_blob, sbloblen,
|
server_host_key_blob, sbloblen,
|
||||||
|
|
10
kexgex.c
10
kexgex.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexgex.c,v 1.29 2015/01/19 20:16:15 markus Exp $ */
|
/* $OpenBSD: kexgex.c,v 1.30 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
||||||
|
@ -46,8 +46,8 @@
|
||||||
int
|
int
|
||||||
kexgex_hash(
|
kexgex_hash(
|
||||||
int hash_alg,
|
int hash_alg,
|
||||||
const char *client_version_string,
|
const struct sshbuf *client_version,
|
||||||
const char *server_version_string,
|
const struct sshbuf *server_version,
|
||||||
const u_char *ckexinit, size_t ckexinitlen,
|
const u_char *ckexinit, size_t ckexinitlen,
|
||||||
const u_char *skexinit, size_t skexinitlen,
|
const u_char *skexinit, size_t skexinitlen,
|
||||||
const u_char *serverhostkeyblob, size_t sbloblen,
|
const u_char *serverhostkeyblob, size_t sbloblen,
|
||||||
|
@ -66,8 +66,8 @@ kexgex_hash(
|
||||||
return SSH_ERR_INVALID_ARGUMENT;
|
return SSH_ERR_INVALID_ARGUMENT;
|
||||||
if ((b = sshbuf_new()) == NULL)
|
if ((b = sshbuf_new()) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
if ((r = sshbuf_put_cstring(b, client_version_string)) != 0 ||
|
if ((r = sshbuf_put_stringb(b, client_version)) < 0 ||
|
||||||
(r = sshbuf_put_cstring(b, server_version_string)) != 0 ||
|
(r = sshbuf_put_stringb(b, server_version)) < 0 ||
|
||||||
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
/* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */
|
||||||
(r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
|
(r = sshbuf_put_u32(b, ckexinitlen+1)) != 0 ||
|
||||||
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
|
(r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) != 0 ||
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexgexc.c,v 1.27 2018/02/07 02:06:51 jsing Exp $ */
|
/* $OpenBSD: kexgexc.c,v 1.29 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* 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)
|
||||||
hashlen = sizeof(hash);
|
hashlen = sizeof(hash);
|
||||||
if ((r = kexgex_hash(
|
if ((r = kexgex_hash(
|
||||||
kex->hash_alg,
|
kex->hash_alg,
|
||||||
kex->client_version_string,
|
kex->client_version,
|
||||||
kex->server_version_string,
|
kex->server_version,
|
||||||
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
||||||
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
||||||
server_host_key_blob, sbloblen,
|
server_host_key_blob, sbloblen,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: kexgexs.c,v 1.35 2018/10/04 00:04:41 djm Exp $ */
|
/* $OpenBSD: kexgexs.c,v 1.36 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
* Copyright (c) 2000 Niels Provos. All rights reserved.
|
||||||
* Copyright (c) 2001 Markus Friedl. All rights reserved.
|
* 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)
|
||||||
hashlen = sizeof(hash);
|
hashlen = sizeof(hash);
|
||||||
if ((r = kexgex_hash(
|
if ((r = kexgex_hash(
|
||||||
kex->hash_alg,
|
kex->hash_alg,
|
||||||
kex->client_version_string,
|
kex->client_version,
|
||||||
kex->server_version_string,
|
kex->server_version,
|
||||||
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
|
||||||
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
sshbuf_ptr(kex->my), sshbuf_len(kex->my),
|
||||||
server_host_key_blob, sbloblen,
|
server_host_key_blob, sbloblen,
|
||||||
|
|
77
misc.c
77
misc.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: misc.c,v 1.135 2018/12/07 04:36:09 dtucker Exp $ */
|
/* $OpenBSD: misc.c,v 1.136 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
* Copyright (c) 2005,2006 Damien Miller. All rights reserved.
|
||||||
|
@ -38,6 +38,7 @@
|
||||||
#ifdef HAVE_LIBGEN_H
|
#ifdef HAVE_LIBGEN_H
|
||||||
# include <libgen.h>
|
# include <libgen.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <poll.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -234,6 +235,80 @@ set_rdomain(int fd, const char *name)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wait up to *timeoutp milliseconds for fd to be readable. Updates
|
||||||
|
* *timeoutp with time remaining.
|
||||||
|
* Returns 0 if fd ready or -1 on timeout or error (see errno).
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
waitrfd(int fd, int *timeoutp)
|
||||||
|
{
|
||||||
|
struct pollfd pfd;
|
||||||
|
struct timeval t_start;
|
||||||
|
int oerrno, r;
|
||||||
|
|
||||||
|
monotime_tv(&t_start);
|
||||||
|
pfd.fd = fd;
|
||||||
|
pfd.events = POLLIN;
|
||||||
|
for (; *timeoutp >= 0;) {
|
||||||
|
r = poll(&pfd, 1, *timeoutp);
|
||||||
|
oerrno = errno;
|
||||||
|
ms_subtract_diff(&t_start, timeoutp);
|
||||||
|
errno = oerrno;
|
||||||
|
if (r > 0)
|
||||||
|
return 0;
|
||||||
|
else if (r == -1 && errno != EAGAIN)
|
||||||
|
return -1;
|
||||||
|
else if (r == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* timeout */
|
||||||
|
errno = ETIMEDOUT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attempt a non-blocking connect(2) to the specified address, waiting up to
|
||||||
|
* *timeoutp milliseconds for the connection to complete. If the timeout is
|
||||||
|
* <=0, then wait indefinitely.
|
||||||
|
*
|
||||||
|
* Returns 0 on success or -1 on failure.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
timeout_connect(int sockfd, const struct sockaddr *serv_addr,
|
||||||
|
socklen_t addrlen, int *timeoutp)
|
||||||
|
{
|
||||||
|
int optval = 0;
|
||||||
|
socklen_t optlen = sizeof(optval);
|
||||||
|
|
||||||
|
/* No timeout: just do a blocking connect() */
|
||||||
|
if (timeoutp == NULL || *timeoutp <= 0)
|
||||||
|
return connect(sockfd, serv_addr, addrlen);
|
||||||
|
|
||||||
|
set_nonblock(sockfd);
|
||||||
|
if (connect(sockfd, serv_addr, addrlen) == 0) {
|
||||||
|
/* Succeeded already? */
|
||||||
|
unset_nonblock(sockfd);
|
||||||
|
return 0;
|
||||||
|
} else if (errno != EINPROGRESS)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (waitrfd(sockfd, timeoutp) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Completed or failed */
|
||||||
|
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) {
|
||||||
|
debug("getsockopt: %s", strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (optval != 0) {
|
||||||
|
errno = optval;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unset_nonblock(sockfd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Characters considered whitespace in strsep calls. */
|
/* Characters considered whitespace in strsep calls. */
|
||||||
#define WHITESPACE " \t\r\n"
|
#define WHITESPACE " \t\r\n"
|
||||||
#define QUOTE "\""
|
#define QUOTE "\""
|
||||||
|
|
5
misc.h
5
misc.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: misc.h,v 1.77 2018/12/07 04:36:09 dtucker Exp $ */
|
/* $OpenBSD: misc.h,v 1.78 2018/12/27 03:25:25 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
/* Data structure for representing a forwarding request. */
|
/* Data structure for representing a forwarding request. */
|
||||||
struct Forward {
|
struct Forward {
|
||||||
|
@ -51,6 +52,8 @@ void set_nodelay(int);
|
||||||
int set_reuseaddr(int);
|
int set_reuseaddr(int);
|
||||||
char *get_rdomain(int);
|
char *get_rdomain(int);
|
||||||
int set_rdomain(int, const char *);
|
int set_rdomain(int, const char *);
|
||||||
|
int waitrfd(int, int *);
|
||||||
|
int timeout_connect(int, const struct sockaddr *, socklen_t, int *);
|
||||||
int a2port(const char *);
|
int a2port(const char *);
|
||||||
int a2tun(const char *, int *);
|
int a2tun(const char *, int *);
|
||||||
char *put_host_port(const char *, u_short);
|
char *put_host_port(const char *, u_short);
|
||||||
|
|
42
packet.c
42
packet.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: packet.c,v 1.277 2018/07/16 03:09:13 djm Exp $ */
|
/* $OpenBSD: packet.c,v 1.278 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -58,6 +58,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <poll.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -228,6 +229,7 @@ ssh_alloc_session_state(void)
|
||||||
|
|
||||||
if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
|
if ((ssh = calloc(1, sizeof(*ssh))) == NULL ||
|
||||||
(state = calloc(1, sizeof(*state))) == NULL ||
|
(state = calloc(1, sizeof(*state))) == NULL ||
|
||||||
|
(ssh->kex = kex_new()) == NULL ||
|
||||||
(state->input = sshbuf_new()) == NULL ||
|
(state->input = sshbuf_new()) == NULL ||
|
||||||
(state->output = sshbuf_new()) == NULL ||
|
(state->output = sshbuf_new()) == NULL ||
|
||||||
(state->outgoing_packet = sshbuf_new()) == NULL ||
|
(state->outgoing_packet = sshbuf_new()) == NULL ||
|
||||||
|
@ -250,6 +252,10 @@ ssh_alloc_session_state(void)
|
||||||
ssh->state = state;
|
ssh->state = state;
|
||||||
return ssh;
|
return ssh;
|
||||||
fail:
|
fail:
|
||||||
|
if (ssh) {
|
||||||
|
kex_free(ssh->kex);
|
||||||
|
free(ssh);
|
||||||
|
}
|
||||||
if (state) {
|
if (state) {
|
||||||
sshbuf_free(state->input);
|
sshbuf_free(state->input);
|
||||||
sshbuf_free(state->output);
|
sshbuf_free(state->output);
|
||||||
|
@ -257,7 +263,6 @@ ssh_alloc_session_state(void)
|
||||||
sshbuf_free(state->outgoing_packet);
|
sshbuf_free(state->outgoing_packet);
|
||||||
free(state);
|
free(state);
|
||||||
}
|
}
|
||||||
free(ssh);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,8 +277,7 @@ ssh_packet_set_input_hook(struct ssh *ssh, ssh_packet_hook_fn *hook, void *ctx)
|
||||||
int
|
int
|
||||||
ssh_packet_is_rekeying(struct ssh *ssh)
|
ssh_packet_is_rekeying(struct ssh *ssh)
|
||||||
{
|
{
|
||||||
return ssh->state->rekeying ||
|
return ssh->state->rekeying || ssh->kex->done == 0;
|
||||||
(ssh->kex != NULL && ssh->kex->done == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -932,7 +936,7 @@ ssh_packet_need_rekeying(struct ssh *ssh, u_int outbound_packet_len)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Haven't keyed yet or KEX in progress. */
|
/* Haven't keyed yet or KEX in progress. */
|
||||||
if (ssh->kex == NULL || ssh_packet_is_rekeying(ssh))
|
if (ssh_packet_is_rekeying(ssh))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Peer can't rekey */
|
/* Peer can't rekey */
|
||||||
|
@ -2123,6 +2127,7 @@ void
|
||||||
ssh_packet_set_server(struct ssh *ssh)
|
ssh_packet_set_server(struct ssh *ssh)
|
||||||
{
|
{
|
||||||
ssh->state->server_side = 1;
|
ssh->state->server_side = 1;
|
||||||
|
ssh->kex->server = 1; /* XXX unify? */
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2175,9 +2180,9 @@ kex_to_blob(struct sshbuf *m, struct kex *kex)
|
||||||
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
|
(r = sshbuf_put_u32(m, kex->kex_type)) != 0 ||
|
||||||
(r = sshbuf_put_stringb(m, kex->my)) != 0 ||
|
(r = sshbuf_put_stringb(m, kex->my)) != 0 ||
|
||||||
(r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
|
(r = sshbuf_put_stringb(m, kex->peer)) != 0 ||
|
||||||
(r = sshbuf_put_u32(m, kex->flags)) != 0 ||
|
(r = sshbuf_put_stringb(m, kex->client_version)) != 0 ||
|
||||||
(r = sshbuf_put_cstring(m, kex->client_version_string)) != 0 ||
|
(r = sshbuf_put_stringb(m, kex->server_version)) != 0 ||
|
||||||
(r = sshbuf_put_cstring(m, kex->server_version_string)) != 0)
|
(r = sshbuf_put_u32(m, kex->flags)) != 0)
|
||||||
return r;
|
return r;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2327,12 +2332,8 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
|
||||||
struct kex *kex;
|
struct kex *kex;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
if ((kex = calloc(1, sizeof(struct kex))) == NULL ||
|
if ((kex = kex_new()) == NULL)
|
||||||
(kex->my = sshbuf_new()) == NULL ||
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
(kex->peer = sshbuf_new()) == NULL) {
|
|
||||||
r = SSH_ERR_ALLOC_FAIL;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
|
if ((r = sshbuf_get_string(m, &kex->session_id, &kex->session_id_len)) != 0 ||
|
||||||
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
|
(r = sshbuf_get_u32(m, &kex->we_need)) != 0 ||
|
||||||
(r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 ||
|
(r = sshbuf_get_cstring(m, &kex->hostkey_alg, NULL)) != 0 ||
|
||||||
|
@ -2341,23 +2342,20 @@ kex_from_blob(struct sshbuf *m, struct kex **kexp)
|
||||||
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
|
(r = sshbuf_get_u32(m, &kex->kex_type)) != 0 ||
|
||||||
(r = sshbuf_get_stringb(m, kex->my)) != 0 ||
|
(r = sshbuf_get_stringb(m, kex->my)) != 0 ||
|
||||||
(r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
|
(r = sshbuf_get_stringb(m, kex->peer)) != 0 ||
|
||||||
(r = sshbuf_get_u32(m, &kex->flags)) != 0 ||
|
(r = sshbuf_get_stringb(m, kex->client_version)) != 0 ||
|
||||||
(r = sshbuf_get_cstring(m, &kex->client_version_string, NULL)) != 0 ||
|
(r = sshbuf_get_stringb(m, kex->server_version)) != 0 ||
|
||||||
(r = sshbuf_get_cstring(m, &kex->server_version_string, NULL)) != 0)
|
(r = sshbuf_get_u32(m, &kex->flags)) != 0)
|
||||||
goto out;
|
goto out;
|
||||||
kex->server = 1;
|
kex->server = 1;
|
||||||
kex->done = 1;
|
kex->done = 1;
|
||||||
r = 0;
|
r = 0;
|
||||||
out:
|
out:
|
||||||
if (r != 0 || kexp == NULL) {
|
if (r != 0 || kexp == NULL) {
|
||||||
if (kex != NULL) {
|
kex_free(kex);
|
||||||
sshbuf_free(kex->my);
|
|
||||||
sshbuf_free(kex->peer);
|
|
||||||
free(kex);
|
|
||||||
}
|
|
||||||
if (kexp != NULL)
|
if (kexp != NULL)
|
||||||
*kexp = NULL;
|
*kexp = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
kex_free(*kexp);
|
||||||
*kexp = kex;
|
*kexp = kex;
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
|
4
ssh.c
4
ssh.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh.c,v 1.496 2018/11/23 05:08:07 djm Exp $ */
|
/* $OpenBSD: ssh.c,v 1.497 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -1490,7 +1490,7 @@ main(int ac, char **av)
|
||||||
signal(SIGCHLD, main_sigchld_handler);
|
signal(SIGCHLD, main_sigchld_handler);
|
||||||
|
|
||||||
/* Log into the remote system. Never returns if the login fails. */
|
/* Log into the remote system. Never returns if the login fails. */
|
||||||
ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr,
|
ssh_login(ssh, &sensitive_data, host, (struct sockaddr *)&hostaddr,
|
||||||
options.port, pw, timeout_ms);
|
options.port, pw, timeout_ms);
|
||||||
|
|
||||||
if (packet_connection_is_on_socket()) {
|
if (packet_connection_is_on_socket()) {
|
||||||
|
|
6
ssh.h
6
ssh.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh.h,v 1.88 2018/06/06 18:29:18 markus Exp $ */
|
/* $OpenBSD: ssh.h,v 1.89 2018/12/27 03:25:25 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
|
@ -93,3 +93,7 @@
|
||||||
|
|
||||||
/* Listen backlog for sshd, ssh-agent and forwarding sockets */
|
/* Listen backlog for sshd, ssh-agent and forwarding sockets */
|
||||||
#define SSH_LISTEN_BACKLOG 128
|
#define SSH_LISTEN_BACKLOG 128
|
||||||
|
|
||||||
|
/* Limits for banner exchange */
|
||||||
|
#define SSH_MAX_BANNER_LEN 8192
|
||||||
|
#define SSH_MAX_PRE_BANNER_LINES 1024
|
||||||
|
|
125
ssh_api.c
125
ssh_api.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: ssh_api.c,v 1.8 2017/04/30 23:13:25 djm Exp $ */
|
/* $OpenBSD: ssh_api.c,v 1.9 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2012 Markus Friedl. All rights reserved.
|
* Copyright (c) 2012 Markus Friedl. All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -34,8 +34,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
int _ssh_exchange_banner(struct ssh *);
|
int _ssh_exchange_banner(struct ssh *);
|
||||||
int _ssh_send_banner(struct ssh *, char **);
|
int _ssh_send_banner(struct ssh *, struct sshbuf *);
|
||||||
int _ssh_read_banner(struct ssh *, char **);
|
int _ssh_read_banner(struct ssh *, struct sshbuf *);
|
||||||
int _ssh_order_hostkeyalgs(struct ssh *);
|
int _ssh_order_hostkeyalgs(struct ssh *);
|
||||||
int _ssh_verify_host_key(struct sshkey *, struct ssh *);
|
int _ssh_verify_host_key(struct sshkey *, struct ssh *);
|
||||||
struct sshkey *_ssh_host_public_key(int, int, struct ssh *);
|
struct 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)
|
||||||
|
|
||||||
/* Initialize key exchange */
|
/* Initialize key exchange */
|
||||||
proposal = kex_params ? kex_params->proposal : myproposal;
|
proposal = kex_params ? kex_params->proposal : myproposal;
|
||||||
if ((r = kex_new(ssh, proposal, &ssh->kex)) != 0) {
|
if ((r = kex_ready(ssh, proposal)) != 0) {
|
||||||
ssh_free(ssh);
|
ssh_free(ssh);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -236,8 +236,8 @@ ssh_packet_next(struct ssh *ssh, u_char *typep)
|
||||||
* enough data.
|
* enough data.
|
||||||
*/
|
*/
|
||||||
*typep = SSH_MSG_NONE;
|
*typep = SSH_MSG_NONE;
|
||||||
if (ssh->kex->client_version_string == NULL ||
|
if (sshbuf_len(ssh->kex->client_version) == 0 ||
|
||||||
ssh->kex->server_version_string == NULL)
|
sshbuf_len(ssh->kex->server_version) == 0)
|
||||||
return _ssh_exchange_banner(ssh);
|
return _ssh_exchange_banner(ssh);
|
||||||
/*
|
/*
|
||||||
* If we enough data and a dispatch function then
|
* If we enough data and a dispatch function then
|
||||||
|
@ -312,39 +312,46 @@ ssh_input_space(struct ssh *ssh, size_t len)
|
||||||
|
|
||||||
/* Read other side's version identification. */
|
/* Read other side's version identification. */
|
||||||
int
|
int
|
||||||
_ssh_read_banner(struct ssh *ssh, char **bannerp)
|
_ssh_read_banner(struct ssh *ssh, struct sshbuf *banner)
|
||||||
{
|
{
|
||||||
struct sshbuf *input;
|
struct sshbuf *input = ssh_packet_get_input(ssh);
|
||||||
const char *s;
|
|
||||||
char buf[256], remote_version[256]; /* must be same size! */
|
|
||||||
const char *mismatch = "Protocol mismatch.\r\n";
|
const char *mismatch = "Protocol mismatch.\r\n";
|
||||||
int r, remote_major, remote_minor;
|
const u_char *s = sshbuf_ptr(input);
|
||||||
size_t i, n, j, len;
|
u_char c;
|
||||||
|
char *cp, *remote_version;
|
||||||
|
int r, remote_major, remote_minor, expect_nl;
|
||||||
|
size_t n, j;
|
||||||
|
|
||||||
*bannerp = NULL;
|
|
||||||
input = ssh_packet_get_input(ssh);
|
|
||||||
len = sshbuf_len(input);
|
|
||||||
s = (const char *)sshbuf_ptr(input);
|
|
||||||
for (j = n = 0;;) {
|
for (j = n = 0;;) {
|
||||||
for (i = 0; i < sizeof(buf) - 1; i++) {
|
sshbuf_reset(banner);
|
||||||
if (j >= len)
|
expect_nl = 0;
|
||||||
return (0);
|
for (;;) {
|
||||||
buf[i] = s[j++];
|
if (j >= sshbuf_len(input))
|
||||||
if (buf[i] == '\r') {
|
return 0; /* insufficient data in input buf */
|
||||||
buf[i] = '\n';
|
c = s[j++];
|
||||||
buf[i + 1] = 0;
|
if (c == '\r') {
|
||||||
continue; /**XXX wait for \n */
|
expect_nl = 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
if (buf[i] == '\n') {
|
if (c == '\n')
|
||||||
buf[i + 1] = 0;
|
|
||||||
break;
|
break;
|
||||||
}
|
if (expect_nl)
|
||||||
|
goto bad;
|
||||||
|
if ((r = sshbuf_put_u8(banner, c)) != 0)
|
||||||
|
return r;
|
||||||
|
if (sshbuf_len(banner) > SSH_MAX_BANNER_LEN)
|
||||||
|
goto bad;
|
||||||
}
|
}
|
||||||
buf[sizeof(buf) - 1] = 0;
|
if (sshbuf_len(banner) >= 4 &&
|
||||||
if (strncmp(buf, "SSH-", 4) == 0)
|
memcmp(sshbuf_ptr(banner), "SSH-", 4) == 0)
|
||||||
break;
|
break;
|
||||||
debug("ssh_exchange_identification: %s", buf);
|
if ((cp = sshbuf_dup_string(banner)) == NULL)
|
||||||
if (ssh->kex->server || ++n > 65536) {
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
|
debug("%s: %s", __func__, cp);
|
||||||
|
free(cp);
|
||||||
|
/* Accept lines before banner only on client */
|
||||||
|
if (ssh->kex->server || ++n > SSH_MAX_PRE_BANNER_LINES) {
|
||||||
|
bad:
|
||||||
if ((r = sshbuf_put(ssh_packet_get_output(ssh),
|
if ((r = sshbuf_put(ssh_packet_get_output(ssh),
|
||||||
mismatch, strlen(mismatch))) != 0)
|
mismatch, strlen(mismatch))) != 0)
|
||||||
return r;
|
return r;
|
||||||
|
@ -354,11 +361,17 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
|
||||||
if ((r = sshbuf_consume(input, j)) != 0)
|
if ((r = sshbuf_consume(input, j)) != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
if ((cp = sshbuf_dup_string(banner)) == NULL)
|
||||||
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
|
/* XXX remote version must be the same size as banner for sscanf */
|
||||||
|
if ((remote_version = calloc(1, sshbuf_len(banner))) == NULL)
|
||||||
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check that the versions match. In future this might accept
|
* Check that the versions match. In future this might accept
|
||||||
* several versions and set appropriate flags to handle them.
|
* several versions and set appropriate flags to handle them.
|
||||||
*/
|
*/
|
||||||
if (sscanf(buf, "SSH-%d.%d-%[^\n]\n",
|
if (sscanf(cp, "SSH-%d.%d-%[^\n]\n",
|
||||||
&remote_major, &remote_minor, remote_version) != 3)
|
&remote_major, &remote_minor, remote_version) != 3)
|
||||||
return SSH_ERR_INVALID_FORMAT;
|
return SSH_ERR_INVALID_FORMAT;
|
||||||
debug("Remote protocol version %d.%d, remote software version %.100s",
|
debug("Remote protocol version %d.%d, remote software version %.100s",
|
||||||
|
@ -371,27 +384,29 @@ _ssh_read_banner(struct ssh *ssh, char **bannerp)
|
||||||
}
|
}
|
||||||
if (remote_major != 2)
|
if (remote_major != 2)
|
||||||
return SSH_ERR_PROTOCOL_MISMATCH;
|
return SSH_ERR_PROTOCOL_MISMATCH;
|
||||||
chop(buf);
|
debug("Remote version string %.100s", cp);
|
||||||
debug("Remote version string %.100s", buf);
|
free(cp);
|
||||||
if ((*bannerp = strdup(buf)) == NULL)
|
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Send our own protocol version identification. */
|
/* Send our own protocol version identification. */
|
||||||
int
|
int
|
||||||
_ssh_send_banner(struct ssh *ssh, char **bannerp)
|
_ssh_send_banner(struct ssh *ssh, struct sshbuf *banner)
|
||||||
{
|
{
|
||||||
char buf[256];
|
char *cp;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
snprintf(buf, sizeof buf, "SSH-2.0-%.100s\r\n", SSH_VERSION);
|
if ((r = sshbuf_putf(banner, "SSH-2.0-%.100s\r\n", SSH_VERSION)) != 0)
|
||||||
if ((r = sshbuf_put(ssh_packet_get_output(ssh), buf, strlen(buf))) != 0)
|
|
||||||
return r;
|
return r;
|
||||||
chop(buf);
|
if ((r = sshbuf_putb(ssh_packet_get_output(ssh), banner)) != 0)
|
||||||
debug("Local version string %.100s", buf);
|
return r;
|
||||||
if ((*bannerp = strdup(buf)) == NULL)
|
/* Remove trailing \r\n */
|
||||||
|
if ((r = sshbuf_consume_end(banner, 2)) != 0)
|
||||||
|
return r;
|
||||||
|
if ((cp = sshbuf_dup_string(banner)) == NULL)
|
||||||
return SSH_ERR_ALLOC_FAIL;
|
return SSH_ERR_ALLOC_FAIL;
|
||||||
|
debug("Local version string %.100s", cp);
|
||||||
|
free(cp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,25 +423,25 @@ _ssh_exchange_banner(struct ssh *ssh)
|
||||||
|
|
||||||
r = 0;
|
r = 0;
|
||||||
if (kex->server) {
|
if (kex->server) {
|
||||||
if (kex->server_version_string == NULL)
|
if (sshbuf_len(ssh->kex->server_version) == 0)
|
||||||
r = _ssh_send_banner(ssh, &kex->server_version_string);
|
r = _ssh_send_banner(ssh, ssh->kex->server_version);
|
||||||
if (r == 0 &&
|
if (r == 0 &&
|
||||||
kex->server_version_string != NULL &&
|
sshbuf_len(ssh->kex->server_version) != 0 &&
|
||||||
kex->client_version_string == NULL)
|
sshbuf_len(ssh->kex->client_version) == 0)
|
||||||
r = _ssh_read_banner(ssh, &kex->client_version_string);
|
r = _ssh_read_banner(ssh, ssh->kex->client_version);
|
||||||
} else {
|
} else {
|
||||||
if (kex->server_version_string == NULL)
|
if (sshbuf_len(ssh->kex->server_version) == 0)
|
||||||
r = _ssh_read_banner(ssh, &kex->server_version_string);
|
r = _ssh_read_banner(ssh, ssh->kex->server_version);
|
||||||
if (r == 0 &&
|
if (r == 0 &&
|
||||||
kex->server_version_string != NULL &&
|
sshbuf_len(ssh->kex->server_version) != 0 &&
|
||||||
kex->client_version_string == NULL)
|
sshbuf_len(ssh->kex->client_version) == 0)
|
||||||
r = _ssh_send_banner(ssh, &kex->client_version_string);
|
r = _ssh_send_banner(ssh, ssh->kex->client_version);
|
||||||
}
|
}
|
||||||
if (r != 0)
|
if (r != 0)
|
||||||
return r;
|
return r;
|
||||||
/* start initial kex as soon as we have exchanged the banners */
|
/* start initial kex as soon as we have exchanged the banners */
|
||||||
if (kex->server_version_string != NULL &&
|
if (sshbuf_len(ssh->kex->server_version) != 0 &&
|
||||||
kex->client_version_string != NULL) {
|
sshbuf_len(ssh->kex->client_version) != 0) {
|
||||||
if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 ||
|
if ((r = _ssh_order_hostkeyalgs(ssh)) != 0 ||
|
||||||
(r = kex_send_kexinit(ssh)) != 0)
|
(r = kex_send_kexinit(ssh)) != 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
187
sshconnect.c
187
sshconnect.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshconnect.c,v 1.308 2018/11/18 22:43:29 dtucker Exp $ */
|
/* $OpenBSD: sshconnect.c,v 1.309 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -68,9 +68,8 @@
|
||||||
#include "authfile.h"
|
#include "authfile.h"
|
||||||
#include "ssherr.h"
|
#include "ssherr.h"
|
||||||
#include "authfd.h"
|
#include "authfd.h"
|
||||||
|
#include "kex.h"
|
||||||
|
|
||||||
char *client_version_string = NULL;
|
|
||||||
char *server_version_string = NULL;
|
|
||||||
struct sshkey *previous_host_key = NULL;
|
struct sshkey *previous_host_key = NULL;
|
||||||
|
|
||||||
static int matching_host_key_dns = 0;
|
static int matching_host_key_dns = 0;
|
||||||
|
@ -444,73 +443,6 @@ fail:
|
||||||
return sock;
|
return sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Wait up to *timeoutp milliseconds for fd to be readable. Updates
|
|
||||||
* *timeoutp with time remaining.
|
|
||||||
* Returns 0 if fd ready or -1 on timeout or error (see errno).
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
waitrfd(int fd, int *timeoutp)
|
|
||||||
{
|
|
||||||
struct pollfd pfd;
|
|
||||||
struct timeval t_start;
|
|
||||||
int oerrno, r;
|
|
||||||
|
|
||||||
monotime_tv(&t_start);
|
|
||||||
pfd.fd = fd;
|
|
||||||
pfd.events = POLLIN;
|
|
||||||
for (; *timeoutp >= 0;) {
|
|
||||||
r = poll(&pfd, 1, *timeoutp);
|
|
||||||
oerrno = errno;
|
|
||||||
ms_subtract_diff(&t_start, timeoutp);
|
|
||||||
errno = oerrno;
|
|
||||||
if (r > 0)
|
|
||||||
return 0;
|
|
||||||
else if (r == -1 && errno != EAGAIN)
|
|
||||||
return -1;
|
|
||||||
else if (r == 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* timeout */
|
|
||||||
errno = ETIMEDOUT;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
timeout_connect(int sockfd, const struct sockaddr *serv_addr,
|
|
||||||
socklen_t addrlen, int *timeoutp)
|
|
||||||
{
|
|
||||||
int optval = 0;
|
|
||||||
socklen_t optlen = sizeof(optval);
|
|
||||||
|
|
||||||
/* No timeout: just do a blocking connect() */
|
|
||||||
if (*timeoutp <= 0)
|
|
||||||
return connect(sockfd, serv_addr, addrlen);
|
|
||||||
|
|
||||||
set_nonblock(sockfd);
|
|
||||||
if (connect(sockfd, serv_addr, addrlen) == 0) {
|
|
||||||
/* Succeeded already? */
|
|
||||||
unset_nonblock(sockfd);
|
|
||||||
return 0;
|
|
||||||
} else if (errno != EINPROGRESS)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (waitrfd(sockfd, timeoutp) == -1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Completed or failed */
|
|
||||||
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) == -1) {
|
|
||||||
debug("getsockopt: %s", strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (optval != 0) {
|
|
||||||
errno = optval;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
unset_nonblock(sockfd);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Opens a TCP/IP connection to the remote server on the given host.
|
* Opens a TCP/IP connection to the remote server on the given host.
|
||||||
* The address of the remote host will be returned in hostaddr.
|
* The address of the remote host will be returned in hostaddr.
|
||||||
|
@ -629,110 +561,6 @@ ssh_connect(struct ssh *ssh, const char *host, struct addrinfo *addrs,
|
||||||
return ssh_proxy_connect(ssh, host, port, options.proxy_command);
|
return ssh_proxy_connect(ssh, host, port, options.proxy_command);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
send_client_banner(int connection_out, int minor1)
|
|
||||||
{
|
|
||||||
/* Send our own protocol version identification. */
|
|
||||||
xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
|
|
||||||
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION);
|
|
||||||
if (atomicio(vwrite, connection_out, client_version_string,
|
|
||||||
strlen(client_version_string)) != strlen(client_version_string))
|
|
||||||
fatal("write: %.100s", strerror(errno));
|
|
||||||
chop(client_version_string);
|
|
||||||
debug("Local version string %.100s", client_version_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Waits for the server identification string, and sends our own
|
|
||||||
* identification string.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
ssh_exchange_identification(int timeout_ms)
|
|
||||||
{
|
|
||||||
char buf[256], remote_version[256]; /* must be same size! */
|
|
||||||
int remote_major, remote_minor, mismatch;
|
|
||||||
int connection_in = packet_get_connection_in();
|
|
||||||
int connection_out = packet_get_connection_out();
|
|
||||||
u_int i, n;
|
|
||||||
size_t len;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
send_client_banner(connection_out, 0);
|
|
||||||
|
|
||||||
/* Read other side's version identification. */
|
|
||||||
for (n = 0;;) {
|
|
||||||
for (i = 0; i < sizeof(buf) - 1; i++) {
|
|
||||||
if (timeout_ms > 0) {
|
|
||||||
rc = waitrfd(connection_in, &timeout_ms);
|
|
||||||
if (rc == -1 && errno == ETIMEDOUT) {
|
|
||||||
fatal("Connection timed out during "
|
|
||||||
"banner exchange");
|
|
||||||
} else if (rc == -1) {
|
|
||||||
fatal("%s: %s",
|
|
||||||
__func__, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
len = atomicio(read, connection_in, &buf[i], 1);
|
|
||||||
if (len != 1 && errno == EPIPE)
|
|
||||||
fatal("ssh_exchange_identification: "
|
|
||||||
"Connection closed by remote host");
|
|
||||||
else if (len != 1)
|
|
||||||
fatal("ssh_exchange_identification: "
|
|
||||||
"read: %.100s", strerror(errno));
|
|
||||||
if (buf[i] == '\r') {
|
|
||||||
buf[i] = '\n';
|
|
||||||
buf[i + 1] = 0;
|
|
||||||
continue; /**XXX wait for \n */
|
|
||||||
}
|
|
||||||
if (buf[i] == '\n') {
|
|
||||||
buf[i + 1] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (++n > 65536)
|
|
||||||
fatal("ssh_exchange_identification: "
|
|
||||||
"No banner received");
|
|
||||||
}
|
|
||||||
buf[sizeof(buf) - 1] = 0;
|
|
||||||
if (strncmp(buf, "SSH-", 4) == 0)
|
|
||||||
break;
|
|
||||||
debug("ssh_exchange_identification: %s", buf);
|
|
||||||
}
|
|
||||||
server_version_string = xstrdup(buf);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that the versions match. In future this might accept
|
|
||||||
* several versions and set appropriate flags to handle them.
|
|
||||||
*/
|
|
||||||
if (sscanf(server_version_string, "SSH-%d.%d-%[^\n]\n",
|
|
||||||
&remote_major, &remote_minor, remote_version) != 3)
|
|
||||||
fatal("Bad remote protocol version identification: '%.100s'", buf);
|
|
||||||
debug("Remote protocol version %d.%d, remote software version %.100s",
|
|
||||||
remote_major, remote_minor, remote_version);
|
|
||||||
|
|
||||||
active_state->compat = compat_datafellows(remote_version);
|
|
||||||
mismatch = 0;
|
|
||||||
|
|
||||||
switch (remote_major) {
|
|
||||||
case 2:
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
if (remote_minor != 99)
|
|
||||||
mismatch = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mismatch = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (mismatch)
|
|
||||||
fatal("Protocol major versions differ: %d vs. %d",
|
|
||||||
PROTOCOL_MAJOR_2, remote_major);
|
|
||||||
if ((datafellows & SSH_BUG_RSASIGMD5) != 0)
|
|
||||||
logit("Server version \"%.100s\" uses unsafe RSA signature "
|
|
||||||
"scheme; disabling use of RSA keys", remote_version);
|
|
||||||
chop(server_version_string);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* defaults to 'no' */
|
/* defaults to 'no' */
|
||||||
static int
|
static int
|
||||||
confirm(const char *prompt)
|
confirm(const char *prompt)
|
||||||
|
@ -1426,7 +1254,7 @@ out:
|
||||||
* This function does not require super-user privileges.
|
* This function does not require super-user privileges.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
ssh_login(Sensitive *sensitive, const char *orighost,
|
ssh_login(struct ssh *ssh, Sensitive *sensitive, const char *orighost,
|
||||||
struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
|
struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
|
||||||
{
|
{
|
||||||
char *host;
|
char *host;
|
||||||
|
@ -1440,16 +1268,17 @@ ssh_login(Sensitive *sensitive, const char *orighost,
|
||||||
lowercase(host);
|
lowercase(host);
|
||||||
|
|
||||||
/* Exchange protocol version identification strings with the server. */
|
/* Exchange protocol version identification strings with the server. */
|
||||||
ssh_exchange_identification(timeout_ms);
|
if (kex_exchange_identification(ssh, timeout_ms, NULL) != 0)
|
||||||
|
cleanup_exit(255); /* error already logged */
|
||||||
|
|
||||||
/* Put the connection into non-blocking mode. */
|
/* Put the connection into non-blocking mode. */
|
||||||
packet_set_nonblocking();
|
ssh_packet_set_nonblocking(ssh);
|
||||||
|
|
||||||
/* key exchange */
|
/* key exchange */
|
||||||
/* authenticate user */
|
/* authenticate user */
|
||||||
debug("Authenticating to %s:%d as '%s'", host, port, server_user);
|
debug("Authenticating to %s:%d as '%s'", host, port, server_user);
|
||||||
ssh_kex2(host, hostaddr, port);
|
ssh_kex2(ssh, host, hostaddr, port);
|
||||||
ssh_userauth2(local_user, server_user, host, sensitive);
|
ssh_userauth2(ssh, local_user, server_user, host, sensitive);
|
||||||
free(local_user);
|
free(local_user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
15
sshconnect.h
15
sshconnect.h
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshconnect.h,v 1.35 2018/07/19 10:28:47 dtucker Exp $ */
|
/* $OpenBSD: sshconnect.h,v 1.36 2018/12/27 03:25:25 djm Exp $ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
|
@ -37,21 +37,18 @@ int ssh_connect(struct ssh *, const char *, struct addrinfo *,
|
||||||
struct sockaddr_storage *, u_short, int, int, int *, int);
|
struct sockaddr_storage *, u_short, int, int, int *, int);
|
||||||
void ssh_kill_proxy_command(void);
|
void ssh_kill_proxy_command(void);
|
||||||
|
|
||||||
void ssh_login(Sensitive *, const char *, struct sockaddr *, u_short,
|
void ssh_login(struct ssh *, Sensitive *, const char *,
|
||||||
struct passwd *, int);
|
struct sockaddr *, u_short, struct passwd *, int);
|
||||||
|
|
||||||
void ssh_exchange_identification(int);
|
|
||||||
|
|
||||||
int verify_host_key(char *, struct sockaddr *, struct sshkey *);
|
int verify_host_key(char *, struct sockaddr *, struct sshkey *);
|
||||||
|
|
||||||
void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short,
|
void get_hostfile_hostname_ipaddr(char *, struct sockaddr *, u_short,
|
||||||
char **, char **);
|
char **, char **);
|
||||||
|
|
||||||
void ssh_kex(char *, struct sockaddr *);
|
void ssh_kex2(struct ssh *ssh, char *, struct sockaddr *, u_short);
|
||||||
void ssh_kex2(char *, struct sockaddr *, u_short);
|
|
||||||
|
|
||||||
void ssh_userauth1(const char *, const char *, char *, Sensitive *);
|
void ssh_userauth2(struct ssh *ssh, const char *, const char *,
|
||||||
void ssh_userauth2(const char *, const char *, char *, Sensitive *);
|
char *, Sensitive *);
|
||||||
|
|
||||||
void ssh_put_password(char *);
|
void ssh_put_password(char *);
|
||||||
int ssh_local_cmd(const char *);
|
int ssh_local_cmd(const char *);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshconnect2.c,v 1.290 2018/11/28 06:00:38 djm Exp $ */
|
/* $OpenBSD: sshconnect2.c,v 1.291 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
* Copyright (c) 2000 Markus Friedl. All rights reserved.
|
||||||
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
* Copyright (c) 2008 Damien Miller. All rights reserved.
|
||||||
|
@ -155,11 +155,10 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
|
ssh_kex2(struct ssh *ssh, char *host, struct sockaddr *hostaddr, u_short port)
|
||||||
{
|
{
|
||||||
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
|
char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
|
||||||
char *s, *all_key;
|
char *s, *all_key;
|
||||||
struct kex *kex;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
xxx_host = host;
|
xxx_host = host;
|
||||||
|
@ -199,36 +198,33 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
|
||||||
options.rekey_interval);
|
options.rekey_interval);
|
||||||
|
|
||||||
/* start key exchange */
|
/* start key exchange */
|
||||||
if ((r = kex_setup(active_state, myproposal)) != 0)
|
if ((r = kex_setup(ssh, myproposal)) != 0)
|
||||||
fatal("kex_setup: %s", ssh_err(r));
|
fatal("kex_setup: %s", ssh_err(r));
|
||||||
kex = active_state->kex;
|
|
||||||
#ifdef WITH_OPENSSL
|
#ifdef WITH_OPENSSL
|
||||||
kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
|
ssh->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
|
||||||
kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
|
ssh->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
|
||||||
kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client;
|
ssh->kex->kex[KEX_DH_GRP14_SHA256] = kexdh_client;
|
||||||
kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client;
|
ssh->kex->kex[KEX_DH_GRP16_SHA512] = kexdh_client;
|
||||||
kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client;
|
ssh->kex->kex[KEX_DH_GRP18_SHA512] = kexdh_client;
|
||||||
kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
|
ssh->kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
|
||||||
kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
|
ssh->kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
|
||||||
# ifdef OPENSSL_HAS_ECC
|
# ifdef OPENSSL_HAS_ECC
|
||||||
kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
|
ssh->kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
kex->kex[KEX_C25519_SHA256] = kexc25519_client;
|
ssh->kex->kex[KEX_C25519_SHA256] = kexc25519_client;
|
||||||
kex->client_version_string=client_version_string;
|
ssh->kex->verify_host_key=&verify_host_key_callback;
|
||||||
kex->server_version_string=server_version_string;
|
|
||||||
kex->verify_host_key=&verify_host_key_callback;
|
|
||||||
|
|
||||||
ssh_dispatch_run_fatal(active_state, DISPATCH_BLOCK, &kex->done);
|
ssh_dispatch_run_fatal(ssh, DISPATCH_BLOCK, &ssh->kex->done);
|
||||||
|
|
||||||
/* remove ext-info from the KEX proposals for rekeying */
|
/* remove ext-info from the KEX proposals for rekeying */
|
||||||
myproposal[PROPOSAL_KEX_ALGS] =
|
myproposal[PROPOSAL_KEX_ALGS] =
|
||||||
compat_kex_proposal(options.kex_algorithms);
|
compat_kex_proposal(options.kex_algorithms);
|
||||||
if ((r = kex_prop2buf(kex->my, myproposal)) != 0)
|
if ((r = kex_prop2buf(ssh->kex->my, myproposal)) != 0)
|
||||||
fatal("kex_prop2buf: %s", ssh_err(r));
|
fatal("kex_prop2buf: %s", ssh_err(r));
|
||||||
|
|
||||||
session_id2 = kex->session_id;
|
session_id2 = ssh->kex->session_id;
|
||||||
session_id2_len = kex->session_id_len;
|
session_id2_len = ssh->kex->session_id_len;
|
||||||
|
|
||||||
#ifdef DEBUG_KEXDH
|
#ifdef DEBUG_KEXDH
|
||||||
/* send 1st encrypted/maced/compressed message */
|
/* send 1st encrypted/maced/compressed message */
|
||||||
|
@ -365,10 +361,9 @@ Authmethod authmethods[] = {
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
ssh_userauth2(const char *local_user, const char *server_user, char *host,
|
ssh_userauth2(struct ssh *ssh, const char *local_user,
|
||||||
Sensitive *sensitive)
|
const char *server_user, char *host, Sensitive *sensitive)
|
||||||
{
|
{
|
||||||
struct ssh *ssh = active_state;
|
|
||||||
Authctxt authctxt;
|
Authctxt authctxt;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -392,8 +387,10 @@ ssh_userauth2(const char *local_user, const char *server_user, char *host,
|
||||||
authctxt.info_req_seen = 0;
|
authctxt.info_req_seen = 0;
|
||||||
authctxt.agent_fd = -1;
|
authctxt.agent_fd = -1;
|
||||||
pubkey_prepare(&authctxt);
|
pubkey_prepare(&authctxt);
|
||||||
if (authctxt.method == NULL)
|
if (authctxt.method == NULL) {
|
||||||
fatal("ssh_userauth2: internal error: cannot send userauth none request");
|
fatal("%s: internal error: cannot send userauth none request",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 ||
|
if ((r = sshpkt_start(ssh, SSH2_MSG_SERVICE_REQUEST)) != 0 ||
|
||||||
(r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 ||
|
(r = sshpkt_put_cstring(ssh, "ssh-userauth")) != 0 ||
|
||||||
|
|
118
sshd.c
118
sshd.c
|
@ -1,4 +1,4 @@
|
||||||
/* $OpenBSD: sshd.c,v 1.519 2018/11/19 04:12:32 djm Exp $ */
|
/* $OpenBSD: sshd.c,v 1.520 2018/12/27 03:25:25 djm Exp $ */
|
||||||
/*
|
/*
|
||||||
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
* Author: Tatu Ylonen <ylo@cs.hut.fi>
|
||||||
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
|
||||||
|
@ -180,13 +180,6 @@ char **rexec_argv;
|
||||||
int listen_socks[MAX_LISTEN_SOCKS];
|
int listen_socks[MAX_LISTEN_SOCKS];
|
||||||
int num_listen_socks = 0;
|
int num_listen_socks = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* the client's version string, passed by sshd2 in compat mode. if != NULL,
|
|
||||||
* sshd will skip the version-number exchange
|
|
||||||
*/
|
|
||||||
char *client_version_string = NULL;
|
|
||||||
char *server_version_string = NULL;
|
|
||||||
|
|
||||||
/* Daemon's agent connection */
|
/* Daemon's agent connection */
|
||||||
int auth_sock = -1;
|
int auth_sock = -1;
|
||||||
int have_agent = 0;
|
int have_agent = 0;
|
||||||
|
@ -363,108 +356,6 @@ grace_alarm_handler(int sig)
|
||||||
ssh_remote_ipaddr(active_state), ssh_remote_port(active_state));
|
ssh_remote_ipaddr(active_state), ssh_remote_port(active_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
sshd_exchange_identification(struct ssh *ssh, int sock_in, int sock_out)
|
|
||||||
{
|
|
||||||
u_int i;
|
|
||||||
int remote_major, remote_minor;
|
|
||||||
char *s;
|
|
||||||
char buf[256]; /* Must not be larger than remote_version. */
|
|
||||||
char remote_version[256]; /* Must be at least as big as buf. */
|
|
||||||
|
|
||||||
xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s\r\n",
|
|
||||||
PROTOCOL_MAJOR_2, PROTOCOL_MINOR_2, SSH_VERSION,
|
|
||||||
*options.version_addendum == '\0' ? "" : " ",
|
|
||||||
options.version_addendum);
|
|
||||||
|
|
||||||
/* Send our protocol version identification. */
|
|
||||||
if (atomicio(vwrite, sock_out, server_version_string,
|
|
||||||
strlen(server_version_string))
|
|
||||||
!= strlen(server_version_string)) {
|
|
||||||
logit("Could not write ident string to %s port %d",
|
|
||||||
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
|
|
||||||
cleanup_exit(255);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Read other sides version identification. */
|
|
||||||
memset(buf, 0, sizeof(buf));
|
|
||||||
for (i = 0; i < sizeof(buf) - 1; i++) {
|
|
||||||
if (atomicio(read, sock_in, &buf[i], 1) != 1) {
|
|
||||||
logit("Did not receive identification string "
|
|
||||||
"from %s port %d",
|
|
||||||
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
|
|
||||||
cleanup_exit(255);
|
|
||||||
}
|
|
||||||
if (buf[i] == '\r') {
|
|
||||||
buf[i] = 0;
|
|
||||||
/* Kludge for F-Secure Macintosh < 1.0.2 */
|
|
||||||
if (i == 12 &&
|
|
||||||
strncmp(buf, "SSH-1.5-W1.0", 12) == 0)
|
|
||||||
break;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (buf[i] == '\n') {
|
|
||||||
buf[i] = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buf[sizeof(buf) - 1] = 0;
|
|
||||||
client_version_string = xstrdup(buf);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check that the versions match. In future this might accept
|
|
||||||
* several versions and set appropriate flags to handle them.
|
|
||||||
*/
|
|
||||||
if (sscanf(client_version_string, "SSH-%d.%d-%[^\n]\n",
|
|
||||||
&remote_major, &remote_minor, remote_version) != 3) {
|
|
||||||
s = "Protocol mismatch.\n";
|
|
||||||
(void) atomicio(vwrite, sock_out, s, strlen(s));
|
|
||||||
logit("Bad protocol version identification '%.100s' "
|
|
||||||
"from %s port %d", client_version_string,
|
|
||||||
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh));
|
|
||||||
close(sock_in);
|
|
||||||
close(sock_out);
|
|
||||||
cleanup_exit(255);
|
|
||||||
}
|
|
||||||
debug("Client protocol version %d.%d; client software version %.100s",
|
|
||||||
remote_major, remote_minor, remote_version);
|
|
||||||
|
|
||||||
ssh->compat = compat_datafellows(remote_version);
|
|
||||||
|
|
||||||
if ((ssh->compat & SSH_BUG_PROBE) != 0) {
|
|
||||||
logit("probed from %s port %d with %s. Don't panic.",
|
|
||||||
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
|
|
||||||
client_version_string);
|
|
||||||
cleanup_exit(255);
|
|
||||||
}
|
|
||||||
if ((ssh->compat & SSH_BUG_SCANNER) != 0) {
|
|
||||||
logit("scanned from %s port %d with %s. Don't panic.",
|
|
||||||
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
|
|
||||||
client_version_string);
|
|
||||||
cleanup_exit(255);
|
|
||||||
}
|
|
||||||
if ((ssh->compat & SSH_BUG_RSASIGMD5) != 0) {
|
|
||||||
logit("Client version \"%.100s\" uses unsafe RSA signature "
|
|
||||||
"scheme; disabling use of RSA keys", remote_version);
|
|
||||||
}
|
|
||||||
|
|
||||||
chop(server_version_string);
|
|
||||||
debug("Local version string %.200s", server_version_string);
|
|
||||||
|
|
||||||
if (remote_major != 2 &&
|
|
||||||
!(remote_major == 1 && remote_minor == 99)) {
|
|
||||||
s = "Protocol major versions differ.\n";
|
|
||||||
(void) atomicio(vwrite, sock_out, s, strlen(s));
|
|
||||||
close(sock_in);
|
|
||||||
close(sock_out);
|
|
||||||
logit("Protocol major versions differ for %s port %d: "
|
|
||||||
"%.200s vs. %.200s",
|
|
||||||
ssh_remote_ipaddr(ssh), ssh_remote_port(ssh),
|
|
||||||
server_version_string, client_version_string);
|
|
||||||
cleanup_exit(255);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Destroy the host and server keys. They will no longer be needed. */
|
/* Destroy the host and server keys. They will no longer be needed. */
|
||||||
void
|
void
|
||||||
destroy_sensitive_data(void)
|
destroy_sensitive_data(void)
|
||||||
|
@ -2115,7 +2006,9 @@ main(int ac, char **av)
|
||||||
if (!debug_flag)
|
if (!debug_flag)
|
||||||
alarm(options.login_grace_time);
|
alarm(options.login_grace_time);
|
||||||
|
|
||||||
sshd_exchange_identification(ssh, sock_in, sock_out);
|
if (kex_exchange_identification(ssh, -1, options.version_addendum) != 0)
|
||||||
|
cleanup_exit(255); /* error already logged */
|
||||||
|
|
||||||
packet_set_nonblocking();
|
packet_set_nonblocking();
|
||||||
|
|
||||||
/* allocate authentication context */
|
/* allocate authentication context */
|
||||||
|
@ -2303,9 +2196,6 @@ do_ssh2_kex(void)
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
kex->kex[KEX_C25519_SHA256] = kexc25519_server;
|
kex->kex[KEX_C25519_SHA256] = kexc25519_server;
|
||||||
kex->server = 1;
|
|
||||||
kex->client_version_string=client_version_string;
|
|
||||||
kex->server_version_string=server_version_string;
|
|
||||||
kex->load_host_public_key=&get_hostkey_public_by_type;
|
kex->load_host_public_key=&get_hostkey_public_by_type;
|
||||||
kex->load_host_private_key=&get_hostkey_private_by_type;
|
kex->load_host_private_key=&get_hostkey_private_by_type;
|
||||||
kex->host_key_index=&get_hostkey_index;
|
kex->host_key_index=&get_hostkey_index;
|
||||||
|
|
Loading…
Reference in New Issue